SeleniumWebDriverとJavaを使って自動テストを行う際、データ駆動テストを行いたいときがあります。

データ駆動とは

テストの入力値と期待結果を、表やスプレッドシートの形でデータとして保持し、このデータ表に含まれる全てのテストを1つの制御スクリプトで実行できるようにしたスクリプティング技法。(システムテスト自動化標準ガイド より)

です。

たとえばAmazonで商品を購入する場合、

  • 非会員/通常会員/プライム会員
  • 送料有料/無料
  • 通常配送/お急ぎ便

など、いろいろな選択肢があります。

これらの選択肢の組合せを自動でテストしたい、と思ったとき、それぞれの組合せに対して独立に自動テストスクリプトを書いていては、メンテナンスも大変ですし、新しい組合せを追加するのも手間がかかります。

そこで、これらの組合せをExcelなどの表にもたせておいて、1つの「商品を購入する」という自動テストスクリプトに読ませると、表に従って様々なパターンのテストを行ってくれます。

そうすると、メンテナンスをする自動テストスクリプトは組合せのパターン数によらず一つですし、もし組合せが漏れていたり、新しい組合せを追加したいと思ったら、表を更新するだけで済みます。

といった具合に効果を発揮するのがデータ駆動テストです。

(※テストの自動化を行う場合には必ずデータ駆動にしたほうがいい、という話ではありません。念の為。)

このデータ駆動テストを、JavaでSeleniumWebDriverで使うサンプルを紹介します。

Java+Selenium+ApachePOIでデータ駆動

必要なもの

データ駆動に使う表は、Excelの表を読み込ませて行おうと思います。

JavaでExcelの読み書きをするのにはApache POIというライブラリを使います。

Apache POI – the Java API for Microsoft Documents

mavenを使う場合はpom.xmlに以下を追加。

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>


### .xlsxを読む処理を作成

まず、そもそものExcelファイルを読み込む処理を書きます。

``` Java
private&nbsp;static&nbsp;XSSFSheet&nbsp;ExcelWSheet;
private&nbsp;static&nbsp;XSSFWorkbook&nbsp;ExcelWBook;

public&nbsp;static&nbsp;void&nbsp;setExcelFile(String&nbsp;Path,&nbsp;String&nbsp;SheetName)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileInputStream&nbsp;ExcelFile&nbsp;=&nbsp;new&nbsp;FileInputStream(Path);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExcelWBook&nbsp;=&nbsp;new&nbsp;XSSFWorkbook(ExcelFile);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExcelWSheet&nbsp;=&nbsp;ExcelWBook.getSheet(SheetName);
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e.getStackTrace());
&nbsp;&nbsp;&nbsp;&nbsp;}
}

これで、Excelファイルのパスと、シート名を渡すと、内容を取得できるようになります。

あとは、シートのセルを読み込んでいく処理が必要です。

今回はデータ駆動テストのため、指定したシートのA列には必ず「テストケースID」が設定されていて、1行目はラベル行である、とします。

もしラベル行に同じ値のセルが複数あった場合、正常に動作しないのでご注意ください。

public&nbsp;static&nbsp;String&nbsp;getCellValue(String&nbsp;caseID,&nbsp;String&nbsp;colLabel)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cell&nbsp;=&nbsp;ExcelWSheet.getRow(getRowNumOf(caseID)).getCell(getColNumOf(colLabel));
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;CellData&nbsp;=&nbsp;Cell.getStringCellValue();
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CellData;
}

private&nbsp;static&nbsp;int&nbsp;getRowNumOf(String&nbsp;TestID)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;ExcelWSheet.getLastRowNum();&nbsp;i++)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cell&nbsp;=&nbsp;ExcelWSheet.getRow(i).getCell(0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Cell.getStringCellValue().equals(TestID))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;i;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;
}

private&nbsp;static&nbsp;int&nbsp;getColNumOf(String&nbsp;colName)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;j&nbsp;=&nbsp;1;&nbsp;getCellData(0,&nbsp;j).length()&nbsp;&gt;&nbsp;0;&nbsp;j++)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cell&nbsp;=&nbsp;ExcelWSheet.getRow(0).getCell(j);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Cell.getStringCellValue().equals(colName))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;j;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;
}

便宜上3つのメソッドに分けていますが、使いたいのはgetCellValueです。

これに、ケースIDと列ラベルを渡すと、該当するセルの値を取得します。

先のAmazonでの商品購入の例で言うと、たとえば「ケース2の発送列の値」を取得したいと思ったら、getCellValue("ケース2", "発送")です。

使用例

Excelの表を読み込んで、そこに書かれた値をGoogle検索する、という例を作りました。

private&nbsp;static&nbsp;WebDriver&nbsp;driver;
private&nbsp;String&nbsp;caseID;

//&nbsp;DataTableを読み込む
private&nbsp;static&nbsp;void&nbsp;importDataTable()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Excelのデータテーブルのパスとシート名を指定
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExcelUtils.setExcelFile("C:\\DataTable.xlsx",&nbsp;"Sheet1");
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();
&nbsp;&nbsp;&nbsp;&nbsp;}
}

@Parameters(name&nbsp;=&nbsp;"{0}")
public&nbsp;static&nbsp;Collection&lt;Object[]&gt;&nbsp;TestcaseIdList()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;importDataTable();
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;getTestCases();
}

public&nbsp;SearchOnGoogle(String&nbsp;input)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;this.caseID&nbsp;=&nbsp;input;
}

@Before
public&nbsp;void&nbsp;before()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;System.setProperty("webdriver.chrome.driver",&nbsp;C:\\pleiades\\workspace\\webdriver\\chromedriver.exe");
&nbsp;&nbsp;&nbsp;&nbsp;driver&nbsp;=&nbsp;new&nbsp;ChromeDriver();
}

@Test
public&nbsp;void&nbsp;Test()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Googleを開く
&nbsp;&nbsp;&nbsp;&nbsp;driver.get("http://google.com");

&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Excelのシートから読み込んだ文字列を検索欄に入れる
&nbsp;&nbsp;&nbsp;&nbsp;driver.findElement(By.id("lst-ib")).sendKeys(getCellValue(caseID,&nbsp;"keyword"));
}

ApachePOIで読み込んだExcelのシートの内容を、JUnit4のparametersアノテーションを使って繰り返し実行させることで、データ駆動テストを実現しています。

動くサンプル作って置きました

YoshikiIto/selenium-junit4-datadriven-sample

を見てみてください。

参考