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>
要素ではなく、ドキュメント ツリーの下部のどこかにドロップダウン リストが分離されたテキスト入力です。ComboBox の選択を適切にシミュレートするために、最初にドロップダウン矢印のクリックをシミュレートしてから、表示されるリストをクリックすることができます。ただし、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
フィールド検証
validationDelay
検証用の正規表現または vtype が関連付けられているフォーム フィールド (Ext.form.* コンポーネント)は、ユーザーがテキストを入力した後、またはフィールドが失われた直後に、一定の遅延 (デフォルトで 250 ミリ秒に設定されているプロパティを参照) で検証をトリガーします。 focus -- またはぼかします (validateOnDelay
プロパティを参照)。type Selenium コマンドを発行してフィールド内にテキストを入力した後にフィールドの検証をトリガーするには、次のいずれかを実行する必要があります。
遅延検証のトリガー
ExtJS は、フィールドがキーアップ イベントを受け取ると、検証遅延タイマーを起動します。このタイマーをトリガーするには、単純にダミーの keyup イベントを発行し (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"))]
「display: none」チェックが必要であることに注意してください。これは、エラー フィールドが表示されてから非表示にする必要がある場合、ExtJS はエラー フィールドを DOM ツリーから完全に削除するのではなく、単純に非表示にするためです。
要素固有のヒント
Ext.form.Button のクリック
Ext.form.ComboBox から値を選択する
Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
最初に値を設定してから、オブザーバーが存在する場合に選択イベントを明示的に発生させます。