5. テストの合否判定
自動テストを実行した結果、正常なのか何かのエラーが発生したのかを判定するのはテストシナリオの仕事です。合否の判定はテスト内容により様々な基準で判断されるため、テストシナリオの作成者しか決めることができないためです。
表示値による判定
ブラウザ上に表示されている内容を期待した値と比較することで判定する方法です。
例えば、以下のページで「トップメニュー」と表示されていることを確認する場合です。
確認するページをPC上のブラウザ(ここではChromeブラウザ)で表示し「デベロッパーツール」を表示します。
「Elements」タブを選択して、赤丸の選択アイコンをクリックすると、右側ペインのHTMLページ上で確認したい要素にマウスカーソルを重ねると、右側ペインに対応するエレメントが選択表示されます。
右ペインのエレメント上で右クリックしてコンテキストメニューを表示し、「Copy」> 「Copy XPath」を選択すると、該当エレメントを指すXPath文字列がクリップボードにコピーされます。
コピーしたXPathでエレメントを検索し、文字列を取得するためには以下のように記述します。
const { Builder, Capabilities, Key, until, By } = require("selenium-webdriver");
let driver = null;
try {
console.log("capabilitiesの設定");
const capabilities = new Capabilities()
.setBrowserName("safari+G.O");
console.log("WebDriverへ接続");
driver = new Builder()
.usingServer("http://192.168.1.147:7000/wd/hub")
.withCapabilities(capabilities)
.build();
console.log("テスト対象アプリのindex.htmlをロード");
await driver.get("http://dev01.nexaweb.co.jp/GHOST_Operator/demo/index.html");
console.log("コピーしたXPathでelementの配置を3秒待機する");
const elm = await driver.wait(until.elementLocated(By.xpath("/html/body/div[1]/header/div/h1")), 3000);
console.log("elementのテキストを取得する");
const text = await elm.getText();
console.log("結果=<"+text+">");
// 合否判定
if(text !== "トップメニュー")
throw new Error("トップメニュー不一致 <" + text+ ">");
} catch (e) {
console.log(e);
} finally {
if(driver !== null)
await driver.quit();
}
実行結果は以下のようになります。
capabilitiesの設定WebDriverへ接続
テスト対象アプリのindex.htmlをロード
コピーしたXPathでelementの配置を3秒待機する
elementのテキストを取得する
結果=<トップメニュー>
alertによる判定
テストシナリオでalertの表示を待つことができ、alertの表示有無やその表示内容を取得し期待する値と比較することでテストの合否判定を行うことができます。
また、alertが表示されると、テストシナリオでalertを閉じるまで後続WebDriver API呼び出しは失敗するので必ず明示的にalertを処理する必要があります。
サンプルアプリでは、「トップメニュー」クリックするとalertを表示するようになっており、そのalertを捉えるためには以下のように記述します。
const { Builder, Capabilities, Key, until, By } = require("selenium-webdriver");
let driver = null;
try {
console.log("capabilitiesの設定");
const capabilities = new Capabilities()
.setBrowserName("safari+G.O");
console.log("WebDriverへ接続");
driver = new Builder()
.usingServer("http://192.168.1.147:7000/wd/hub")
.withCapabilities(capabilities)
.build();
console.log("テスト対象アプリのindex.htmlをロード");
await driver.get("http://dev01.nexaweb.co.jp/GHOST_Operator/demo/index.html");
console.log("コピーしたXPathでelementの配置を3秒待機する");
const elm = await driver.wait(until.elementLocated(By.xpath("/html/body/div[1]/header/div/h1")), 3000);
console.log("elementのテキストを取得する");
const text = await elm.getText();
console.log("結果=<"+text+">");
// ここからalertの処理です
console.log("トップメニューをクリック");
await elm.click();
console.log("Alertの表示を1秒だけ待つ");
await driver.wait(until.alertIsPresent(), 1000);
console.log("Alertのテキストを取得する");
let alert = await driver.switchTo().alert();
const alertText = await alert.getText();
console.log("alert=<"+alertText+">");
console.log("Alertを閉じる");
await alert.dismiss();
} catch (e) {
console.log(e);
} finally {
if(driver !== null)
await driver.quit();
}
実行結果は以下のようになります。
この処理で、もしalertが表示されない場合には33行目でタイムアウトの例外がスローされテストは失敗します。
画面キャプチャイメージによる判定
表示されたページ全体の画像を取得して、期待する画像と比較して合否を判定することができます。ただし、この方法はiPadの高解像度スクリーンでは負荷が高くなりますし、1ピクセル未満のアンチエイリアシングの状況次第で人が見ても違いを認識できない画像でも不一致と判断されることがあり、お勧めできません。
画面キャプチャイメージでテストの合否を判定するためには、正解画像との比較が必要となります。グラデーションや文字のアンチエイリアシングの微細な画像の差異による不一致を抑止して合否を判定するためには、色差を求めて閾値以下の違いであれば一致と判断するような比較処理が有効です。
このドキュメントの範囲を超えるため詳細な処理は省きますが、比較対象画像の同一座標の2点の色(R1,G1,B1とR2,G2,B2)について、ユークリッド距離( Math.sqrt((R2-R1)*(R2-R1)+(G2-G1)*(G2-G1)+(B2-B1)*(B2-B1)) )を求め、結果を閾値(通常は5程度)未満であれば一致とします。この判定を画像の全画素について行い、すべての画素で一致と判断されれば画像は同じと見なすことができます。
上記の画素の比較は、負荷のかかる処理で多用するとテスト時間が長くなり、正解画像の管理面でも手間のかかるテストとなります。従って、もう少し簡易的に色差を考慮せずに完全一致で合否判定を行う事も考慮する価値があります。
例えば、キャプチャイメージのビットマップからハッシュを算出し、正解画像からあらかじめ算出しておいたハッシュ値と比較する方法であれば、より手軽にキャプチャイメージによる合否判定が可能となります。
以下は、キャプチャイメージからSHA256ハッシュを算出して、正解画像のハッシュ値と比較して合否判定する例です。
URLによる判定
現在表示されているページのURLが意図したURLなのかを比較することで、テストの合否を判定する方法です。
この例では「送信する」ボタンをクリック後、3秒以内に想定したURLに遷移しない場合タイムアウト例外がスローされテストは失敗します。
JavaScriptによる判定
WebDriverには様々な状態把握用のAPIが用意されていますが、すべてHTMLレベルの状態を把握できる機能です。Webブラウザ内のJavaScriptの変数の状態などWebDriver APIでは取得できない情報により合否判定を行いたい場合、JavaScriptプログラムをWebブラウザ内に転送して実行して合否判定を行う事も可能です。