[解決済み] ブラウザでextjsのコードをテストするための提案、できればseleniumで?
質問
私たちは、高レベルのWebサイトのテスト(モジュールレベルでの広範なPythonのdoctestsに加えて)を処理するために大きな成功を収めているseleniumを使用してきました。 しかし、現在、私たちは多くのページで extjs を使用しており、グリッドのような複雑なコンポーネントのために Selenium テストを組み込むことが困難であることが分かっています。
誰かがextjsベースのWebページのために自動化されたテストを書くことに成功したことがありますか? 多くのググりは、同様の問題を持つ人々を見つけますが、答えはほとんどありません。 ありがとうございます。
どのように解決するのですか?
SeleniumでExtJSをテストする際の最大のハードルは、ExtJSが標準のHTML要素をレンダリングしないため、Selenium IDEが単純に(そして当然)装飾として機能する要素、つまりデスクトップ全体のルック&フィールでExtJSを助ける余分な要素に的を絞ってコマンドを生成することです。ここでは、ExtJSアプリに対して自動化されたSeleniumテストを書きながら、私が集めたいくつかのヒントとトリックを紹介します。
一般的なヒント
要素を探す
Firefox上のSelenium IDEでユーザーのアクションを記録してSeleniumテストケースを生成するとき、SeleniumはHTML要素のidに基づいて記録されたアクションを基づかせるでしょう。しかし、ほとんどのクリック可能な要素に対して、ExtJS は "ext-gen-345" のような生成された ID を使用します。これは、たとえコードが変更されていなくても、同じページへの次の訪問で変更される可能性が高いです。テストのためにユーザーのアクションを記録した後、生成された ID に依存するすべてのアクションを調べ、それらを置き換えるための手作業が必要です。置き換えには2つのタイプがあります。
ID ロケータを CSS または XPath ロケータに置き換える
CSS ロケータは "css=" で始まり、XPath ロケータは "//" で始まります ("xpath=" のプレフィックスはオプションです)。CSS ロケータは冗長でなく読みやすいので、XPath ロケータよりも優先されるべきです。しかし、CSS ロケータでは対応できないため、XPath ロケータを使用しなければならない場合もあります。
JavaScript の実行
一部の要素は、ExtJSによって実行される複雑なレンダリングのために、単純なマウス/キーボード操作以上のものを必要とします。例えば、Ext.form.CombBoxは実際には
<select>
要素ではなく、ドキュメントツリーの下部にあるドロップダウン・リストが分離されたテキスト入力です。コンボボックスの選択を適切にシミュレートするには、まずドロップダウン矢印をクリックし、次に表示されるリストをクリックするようにシミュレートすることが可能です。しかし、CSS や XPath ロケータを使用してこれらの要素を見つけるのは面倒です。代替案は、ComoBox コンポーネント自体を見つけ、そのメソッドを呼び出して、選択をシミュレートすることです。
var combo = Ext.getCmp('genderComboBox'); // returns the ComboBox components
combo.setValue('female'); // set the value
combo.fireEvent('select'); // because setValue() doesn't trigger the event
Seleniumでは
runScript
コマンドを使用すると、より簡潔な形式で上記の操作を実行できます。
with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
AJAXと遅いレンダリングへの対応
Seleniumは、ユーザーアクションがページ遷移または再ロードをもたらすとき、ページロードを待機するためのすべてのコマンドのために"*AndWait"のフレーバーを持っています。しかし、AJAXフェッチは実際のページロードを伴わないので、これらのコマンドは同期のために使用することができません。解決策としては、AJAX進捗インジケーターの有無や、グリッド内の行、追加コンポーネント、リンクなどの外観上の手がかりを利用することです。たとえば
Command: waitForElementNotPresent
Target: css=div:contains('Loading...')
ユーザーアクションによってビューが変更された後、ExtJSがコンポーネントをレンダリングする速度に応じて、ある要素が一定の時間後にのみ表示されることがあります。このような場合、恣意的な遅延を使用する代わりに
pause
コマンドで任意に遅延させるのではなく、関心のある要素が手の届くところに来るまで待つのが理想的な方法です。例えば、アイテムが表示されるのを待ってからクリックすることです。
Command: waitForElementPresent
Target: css=span:contains('Do the funky thing')
Command: click
Target: css=span:contains('Do the funky thing')
異なるブラウザや異なるマシンでテストを実行することによるタイミングの違いは、テストケースを不安定にするので、任意の休止に依存するのは良いアイデアではありません。
非クリック項目
一部の要素は、トリガーできないように
click
コマンドでトリガーできない要素もあります。それは、イベントリスナーが実際にはコンテナ上にあり、子要素のマウスイベントを監視し、それが最終的に親要素にバブルアップされるからです。タブコントロールがその一例です。タブをクリックするために
mouseDown
イベントをシミュレートする必要があります。
Command: mouseDownAt
Target: css=.x-tab-strip-text:contains('Options')
Value: 0,0
フィールドの検証
フォームフィールド(Ext.form.*コンポーネント)で、検証用の正規表現またはvtypesが関連付けられているものは、一定の遅延をもって検証を開始します(
validationDelay
プロパティを参照。デフォルトでは 250ms に設定されています)、ユーザーがテキストを入力した後、またはフィールドがフォーカスを失った時(またはぼやけた時)直ちに検証を開始します (
validateOnDelay
プロパティを参照)。フィールド内にテキストを入力するために Selenium type コマンドを発行した後にフィールドバリデーションをトリガーするためには、次のどちらかを行う必要があります。
-
遅延検証のトリガー
ExtJSは、フィールドがキーアップイベントを受信すると、検証遅延タイマーを起動します。このタイマーを起動するには、単にダミーのキーアップイベントを発行し(ExtJSはそれを無視するので、どのキーを使用してもかまいません)、その後にvalidationDelayよりも長い短いポーズをとります。
Command: keyUp Target: someTextArea Value: x Command: pause Target: 500
-
即時検証のトリガー
即時検証をトリガするために、フィールドにブラーイベントを注入することができます。
Command: runScript Target: someComponent.nameTextField.fireEvent("blur")
バリデーション結果の確認
バリデーションの後、エラーフィールドの有無を確認することができます。
Command: verifyElementNotPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Command: verifyElementPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
エラーフィールドが一度表示され、その後非表示にする必要がある場合、ExtJSはエラーフィールドをDOMツリーから完全に削除するのではなく、単に非表示にするため、 "display: none" のチェックが必要であることに注意してください。
要素固有のヒント
Ext.form.Buttonをクリックする
-
オプション1
コマンド:クリック ターゲット:css=button:contains('Save')
ボタンのキャプションで選択する
-
オプション2
コマンド:クリック ターゲット:css=#save-optionsボタン
ボタンをidで選択する
Ext.form.ComboBoxから値を選択する
Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
まず値を設定し、オブザーバがいる場合は明示的に select イベントを発生させます。
関連
-
[解決済み] ユニットテストの命名のベストプラクティス [終了しました]。
-
[解決済み] NUnit vs. MbUnit vs. MSTest vs. xUnit.net [終了しました。]
-
[解決済み】ユニットテスト、インテグレーションテスト、スモークテスト、リグレッションテストとは何ですか?終了
-
[解決済み】ユニットテストと機能テストの違いは何ですか?
-
[解決済み】Selenium WebDriver for Pythonでページが読み込まれるまで待機する。
-
[解決済み】mochaのテスト用ディレクトリを指定するには?
-
[解決済み] 抽象クラスのテスト
-
[解決済み] ユニットテストでは重複したコードが許容されるのか?
-
[解決済み] Kotlinで期待される例外をテストする
-
[解決済み] パニックが発生したことを確認するRustのユニットテストはどのように書けばよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ユニットテストの妥当なコードカバレッジは何%ですか(とその理由)?[クローズド]です。
-
[解決済み】mochaのテスト用ディレクトリを指定するには?
-
[解決済み】ユニットテストとは何ですか?[クローズド]
-
[解決済み】Angular 2 Unit Tests。名前 'describe' が見つからない
-
[解決済み】Unit Testsの一般的な命名規則にはどのようなものがありますか?[クローズド]。
-
[解決済み] モックオブジェクトは何のためにあるのか?
-
[解決済み] いつモックすればいい?
-
[解決済み] 既存のプロダクションプロジェクトにユニットテストをうまく追加することができますか?もしそうなら、どのように、そして、それは価値があるのでしょうか?
-
[解決済み] ファイルシステムに依存するコードの単体テスト
-
[解決済み] 単体テスト?統合テスト? 回帰テスト? 受入テスト?