seleniumテストが失敗する問題のデバッグと解決
====
# TL;DR
関数名のtypoを修正すると、それまで通っていたテストが落ちる。
原因は、テストシステムが生成して渡した不正な引数による異常系終了だった。
対処として、テストケース実行を汚い実装で検出して特別に処理することで問題を回避することとした。
# 問題
## 詳細
electron製アプリのdaisy-sequenceに対して、selenium/mochaでウィンドウの起動テストを行っている。
これはほぼselenium公式サンプルと同じシンプルなテストである。
daisy-sequenceではコマンドライン引数を受け取る。
コマンドライン引数のパースは`js/cli.js` の `class Cli.parse(argv)`にて行っている。
この中で、`sprintf-js`パッケージの`sprintf()`関数をtypoしていた。
```js
const sprintf = require('sprintf-js').sprintf;
(略)
if(2 < argv.length){
if(argv[2] !== '-o'){
arg.err = {
'message': spirntf('invalid argment. `%s`', argv[2])
};
return arg;
}
```
これを修正したところ、ウィンドウが即座に終了し、seleniumテストに失敗する。
```bash
make unit-test
make[1]: ディレクトリ '/home/nuka/daisy_sequence' に入ります
cd daisy_sequence && npm run test test/
> daisy_sequence@201812.2.0 test /home/nuka/daisy_sequence/daisy_sequence
> mocha --require intelli-espower-loader "test/"
Array
#indexOf()
✓ should return -1 when the value is not present
Application launch
1) shows an initial window
2) "after each" hook for "shows an initial window"
1 passing (3s)
2 failing
1) Application launch
shows an initial window:
chrome not reachable
Error: Request timed out after the element was still found on the page.
at windowHandles() - application.js:240:17
2) Application launch
"after each" hook for "shows an initial window":
chrome not reachable
Error: Request timed out after the element was still found on the page.
at windowHandles() - application.js:246:17
^CTerminated
Makefile:20: recipe for target 'unit-test' failed
```
# デバッグ
前提として、typoを修正するとテストに失敗する。
別のtypoを入れる、alart()を挿入する等すると、テストに成功するようになる。 // alart()を入れるのは不正なのか?
> これまでテスト失敗が起こらなかったのは、不正で止まることが原因だったらしい。
arg.errへの代入(arg.errはエラーフラグを兼ねる)を消すとテストに成功する。
> arg.errへの代入がおかしい? それとも、parse()がエラーを返すと失敗する?
Cli.parse()エラー時の`process.exit(-1);`を消すと、テストに成功する。
> parse()がエラーを返すとテストが失敗する!
ところでprocess.exit()するとウィンドウが即座に閉じる。ウィンドウが閉じればテストは失敗する。
つまり不正な引数を受け取っていることが原因の可能性がある。
引数を確認する。
console.error()系, process.write.stderr()等を使用しても出力されない。
// 上記デバッグの際もこれが作業の困難さを増した。
対処として、単にファイルに書き出すこととした。
`fs.writeFileSync("daisy-arg", JSON.stringify(remote.process.argv));`
結果、取得できたselenium/mocha実行時のコマンドライン引数。
```js
["/home/nuka/daisy_sequence/daisy_sequence/node_modules/electron/dist/electron","/home/nuka/daisy_sequence/daisy_sequence","--disable-background-networking","--disable-client-side-phishing-detection","--disable-default-apps","--disable-hang-monitor","--disable-popup-blocking","--disable-prompt-on-repost","--disable-sync","--disable-web-resources","--enable-automation","--enable-logging","--force-fieldtrials=SiteIsolationExtensions/Control","--ignore-certificate-errors","--load-extension=/tmp/.org.chromium.Chromium.oi97WO/internal","--log-level=0","--metrics-recording-only","--no-first-run","--password-store=basic","--remote-debugging-port=12106","--test-type=webdriver","--use-mock-keychain","--user-data-dir=/tmp/.org.chromium.Chromium.h85Kss","data:,"]
```
daisy-sequenceは、第二引数が存在する場合に`-o`でなければ、不正なコマンドライン引数として即座に失敗終了する。
(ただし、先頭がelectronで終了する場合これを引数に数えない。)
原因は不正な引数を受け取っていたことによる不正終了により、ウィンドウが即時終了していたことであると考えられる。
## 現象
大筋は以下。
typo修正前の動作はこのようになっていた。
- selenium/mocha実行はelectronに対してテストに適したコマンドライン引数を渡し、アプリケーションはそれを受け取る。
- アプリケーションはtypoにより「未知の関数を実行しようとした例外」で停止する。
- selenium/mocha実行は途中でアプリケーション側に例外が発生しても検知(失敗判定)しない。
- seleniumはウィンドウが起動している・終了できたことに満足してテストをOK判定する。
以上のことからseleniumによるウィンドウ起動テストは成功していた。
なお、「不正な引数を受け取ったことによる不正終了」と「未知の関数を実行しようとした例外」はどちらもアプリケーションの不正終了を起こす。他のテストでは不正な引数をわたしたことによる不正終了が起こりその理由の区別はつかないので、テスト成功となっていた。
typoを修正したことで、以下のように変化した。
- selenium/mocha実行時のコマンドライン引数を受け取ることで、アプリケーションは不正な引数エラーで即座に不正終了する。
- seleniumはウィンドウが起動していないためテストをNG判定する。
// ところで「不正終了」という言葉の使い方が正しくない気がする。まあいいけど。
# 対処
コマンドライン引数からそれらしい引数を検出したらselenium実行と判定してコマンドライン処理をskipすることとした。
キー文字列は"--test-type="にした。
# 今後の課題
- selenium/mocha実行は途中でアプリケーション側に例外が発生しても検知(失敗判定)しないが、検出して失敗判定するようにしたい。
daisy-sequenceは幸い、正常系で(起動時にwarningが一件出るのと、編集削除操作でエラーログを出力する以外に)例外が発生しない。
- アプリケーション側でパースする際にelectron向けコマンドライン引数を適切に排除する。
登録:
コメントの投稿 (Atom)
食洗機の分岐水栓をDIY工事はあきらめてお願いした(結果的によかった)
食洗機の『プチ食洗(NP-TCR3)』を購入しました。 食洗機にはビルトイン・据え置き水栓・据え置きタンク式、がありますが、購入したのは水栓をつなげる必要がある機種です。 わたしが購入前に参考にしたブログでは『買って取り付ければ終了だよ』で、『分岐水栓を取り付ける必要があるけれ...


-
RENAULT LIGHT10 RENAULT LIGHT10 を購入 しました。Web上にあまり開封写真等の詳細がなかったので残しておきます。 開封 モノが大きいためか、知らない運送会社でおくられてきた。 ...
-
プログラマならば家の掃除は自動化せよという風潮に習い、遅ればせながらロボット掃除機ILIFE V3s Proを導入しました。 その2ヶ月使用のレビューです。 主な使用環境 - 一人部屋 - 掃除するのは玄関・廊下・キッチン・部屋 - 風呂場・トイレは掃除させない ...
-
例および失敗例は、自作のJavaScriptソースから抜粋。 ※例ごとにマッチする文字列が違いますがご容赦ください。 JavaScriptで正規表現を使う方法は2つあって、 (1)正規表現を引数に与える 例: 空行あるいはコメントアウト(行頭が"...

0 件のコメント:
コメントを投稿