データプロバイダー TestNG: Selenium パラメータ化の例
⚡ スマートサマリー
パラメータ化 Selenium 単一のテストメソッドを異なるデータセットに対して繰り返し実行することで、1つのスクリプトをデータ駆動型のカバレッジに変換します。 TestNG これには、testng.xml によってサポートされる @Parameters アノテーションと、2 次元オブジェクト配列を返す @DataProvider アノテーションという 2 つのメカニズムが用意されています。

ソフトウェアを開発する際、私たちは常に、さまざまなデータセットで正しく動作することを望んでいます。 テスト ソフトウェアの検証において、単一のデータセットをチェックするだけでは不十分です。システムがサポートするはずのすべての組み合わせを受け入れることを検証する必要があります。そのためには、テストスクリプトをパラメータ化する必要があります。ここでパラメータ化が役立ちます。
パラメータ化 Selenium
パラメータ化 Selenium 実行時に複数のデータをアプリケーションに渡すために、テスト スクリプトをパラメータ化するプロセスです。 これは、異なる値を使用してテスト ケースを複数回自動的に実行する実行戦略です。 テスト スクリプトをパラメータ化することで実現される概念は、 データ駆動型テスト.
パラメータ化のタイプ TestNG
パラメータ化をより明確にするために、最も人気のあるフレームワークの 1 つにおけるパラメータ化オプションについて説明します。 Selenium WebDriver — TestNG.
全 二つの方法 これによりパラメータ化を実現できます。 TestNG:
- の助けを借りて パラメータ注釈 TestNG XML ファイルにソフトウェアを指定する必要があります。
- の助けを借りて データプロバイダー 注釈。
上記の図は分割をまとめたものです。testng.xml のパラメータはスイートまたはテストレベルで宣言できますが、DataProvider のパラメータは受け入れることができます。 Method (NAIST) と ITestContext それ自体が論拠となる。それらを詳しく見ていこう。
パラメータの注釈 TestNG
パラメータの注釈 TestNG これは、.xml ファイルを使用して値をテスト メソッドに引数として渡すための方法です。実行時に、ユーザーはテスト メソッドに値を渡す必要がある場合があります。@Parameters アノテーション メソッドは、@Test、@Before、@After、または @Factory アノテーションを持つすべてのメソッドで使用できます。
Testng.xml によるパラメータ注釈
複雑さを扱いたくない場合や、入力の組み合わせ数が少ない場合は、注釈を使用したパラメータ化を選択してください。
これがどのように機能するか見てみましょう。
テストシナリオ
ステップ1) ブラウザを起動して、 Google.com
ステップ2) 検索キーワードを入力してください
ステップ3) 入力された値がテストデータによって提供される値と同じであることを確認してください。
ステップ4) すべての値が入力されるまで、手順2と3を繰り返します。
| テスト作成者 | 検索キー |
|---|---|
| Guru99 | India |
| Krishna | USA |
| ブペシュ |
以下にその方法の例を示します。 無し パラメータ:
package parameters; import org.testng.annotations.Test; import org.testng.AssertJUnit; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class NoParameterWithTestNGXML { WebDriver driver; @Test public void testNoParameter() throws InterruptedException { String author = "guru99"; String searchKey = "india"; driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); // Searching text in the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); System.out.println("Value in Google Search Box = " + searchText.getDomProperty("value") + " ::: Value given by input = " + searchKey); // Verifying the value in the Google search box AssertJUnit.assertTrue(searchText.getDomProperty("value").equalsIgnoreCase(searchKey)); } }
⚠️ Selenium 4年の注記: この例の元のバージョンにある3行は、現在のバージョンではコンパイルできないか、非推奨になっています。 Selenium リリース。 System.setProperty("webdriver.gecko.driver", …) 不要です Selenium 4.6以降は Selenium マネージャーはドライババイナリを自動的に解決します。 implicitlyWait(10, TimeUnit.SECONDS) 過負荷は Selenium 4 に置き換えられ、 implicitlyWait(Duration.ofSeconds(10)). getAttribute() は非推奨になりました Selenium 4.27なので、テキストボックスの読み取りには getDomProperty("value")以下の例はすべて、同じ3つの修正を適用しています。
上記の例をよく見て、これを3つの入力の組み合わせに対して繰り返すと、コードがどれほど複雑になるかを想像してみてください。
それでは、これをパラメータ化してみましょう TestNGそのためには、以下の手順が必要です。
- パラメータを保存するXMLファイルを作成します。
- テストでは、@Parameters アノテーションを追加します。
以下に完全なコードを示します。
テストレベル TestNG。のXml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="TestSuite" thread-count="3"> <parameter name="author" value="Guru99" /> <parameter name="searchKey" value="India" /> <test name="testGuru"> <parameter name="searchKey" value="UK" /> <classes> <class name="parameters.ParameterWithTestNGXML"></class> </classes> </test> </suite>
パラメータありTestNGXML.java ファイル
package parameters; import org.testng.AssertJUnit; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParameterWithTestNGXML { WebDriver driver; @Test @Parameters({"author", "searchKey"}) public void testParameterWithXML(@Optional("Abc") String author, String searchKey) throws InterruptedException { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); // Searching text in the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); System.out.println("Value in Google Search Box = " + searchText.getDomProperty("value") + " ::: Value given by input = " + searchKey); // Verifying the value in the Google search box AssertJUnit.assertTrue(searchText.getDomProperty("value").equalsIgnoreCase(searchKey)); } }
スクリプトを実行するには、XML ファイルを選択して、 TestNG 上。
.xml ファイルを右クリックして「実行」を選択します。 TestNG スイート(注:スイート)
パラメータは2つのレベルで定義できます。
- スイートレベル — 内部のパラメータ
<suite>タグ TestNG XMLファイルはスイートレベルのパラメータです。 - テストレベル — 内部のパラメータ
<test>タグ TestNG XMLファイルはテストレベルのパラメータです。
以下は、スイートレベルのパラメータを使用した同じテストです。
注: スイートレベルとテストレベルでパラメータ名が同じ場合、テストレベルのパラメータがスイートレベルのパラメータよりも優先されます。この場合、そのテストレベル内のすべてのクラスは上書きされたパラメータを共有し、そのテストレベル外のクラスは引き続きスイートレベルのパラメータを使用します。
トラブルシューティング
問題 #1: testng.xml内のパラメータ値が、対応するテストメソッドのパラメータに型変換できない場合、エラーが発生します。
次の例を考えてみます。
ここで、「著者」属性は「Guru'99' は文字列ですが、対応するテストメソッドは整数値を期待しているため、例外が発生します。
問題 #2: @Parameters に対応する値が testng.xml に存在しません。
これを解決するには、 @Optional アノテーション 試験方法における対応するパラメータに。
問題 #3: testng.xmlを使用して、同じパラメータの複数の値をテストしたい場合。
簡単に言うと、これは不可能です。複数の異なるパラメータを持つことはできますが、各パラメータには単一の値しか設定できません。これは、スクリプトに値をハードコーディングすることを防ぎ、コードの再利用性を維持するためです。スクリプトの設定ファイルのようなものと考えてください。1つのパラメータに複数の値が必要な場合は、代わりにDataProviderを使用してください。
データプロバイダーの TestNG
データプロバイダーの TestNG は、ユーザーが複雑なパラメータを渡す必要がある場合に使用されるメソッドです。複雑なパラメータは、 Java 複雑なオブジェクト、プロパティファイルからのオブジェクト、またはデータベースからのオブジェクトは、データプロバイダメソッドを介して渡すことができます。このメソッドには@DataProviderアノテーションが付与されており、オブジェクトの配列を返します。
データプロバイダーを使用したパラメーター
@Parameters アノテーションは簡単ですが、複数のデータセットでテストするには、データプロバイダーを使用する必要があります。
当社のテストフレームワークを使用して数千ものWebフォームにデータを入力するには、単一の実行フローで非常に大規模なデータセットを提供できる、別の方法論が必要です。
このデータ駆動型コンセプトは、 @データプロバイダー の注釈 TestNG.
XNUMX つだけあります 属性、「名前」name属性を指定しない場合、DataProviderの名前は対応するメソッド名と同じになります。
データプロバイダーが返します 二次元 Java オブジェクト テストメソッドに渡され、M×N個のオブジェクト配列に対してテストメソッドがM回呼び出されます。例えば、DataProviderが2×3個のオブジェクトの配列を返す場合、対応するテストケースが3つのパラメータで2回呼び出されます。
完全な例
package parameters; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByDataprovider { WebDriver driver; @BeforeTest public void setup() { // Create the Firefox driver object driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } /** Test case to verify the Google search box */ @Test(dataProvider = "SearchProvider") public void testMethod(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); // Search value in the Google search box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); // Verify if the value in the Google search box is correct Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** * @return Object[][] where the first column contains 'author' * and the second column contains 'searchKey' */ @DataProvider(name = "SearchProvider") public Object[][] getDataFromDataprovider() { return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; } }
別のクラスから DataProvider を呼び出す
デフォルトでは、DataProvider はテスト メソッドと同じクラス、またはその基底クラスに存在します。別のクラスに配置するには、データ プロバイダーをメソッドにします。 静的な 属性を追加する データプロバイダクラス から @テスト 注釈。
Code 例:
TestClass ParameterDataproviderWithClassLevel.java
package parameters; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class ParameterDataproviderWithClassLevel { WebDriver driver; @BeforeTest public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } @Test(dataProvider = "SearchProvider", dataProviderClass = DataproviderClass.class) public void testMethod(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); // Search text in the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); // Get text from the search box String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); // Verify if the search box has the correct value Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } }
データプロバイダクラス.java
package parameters; import org.testng.annotations.DataProvider; public class DataproviderClass { @DataProvider(name = "SearchProvider") public static Object[][] getDataFromDataprovider() { return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; } }
データプロバイダーのパラメータの種類
DataProvider メソッドでサポートされているパラメータには、2 種類あります。
方法 — もし 同じ DataProviderはテスト方法によって異なる動作をするように設定する必要があります。そのためには、Methodパラメーターを使用してください。
次の例では:
- メソッド名がtestMethodAであるかどうかを確認します。
- はいの場合、値のセットを1つ返します。
- それ以外の場合は、別の値のセットを返します。
package parameters; import java.lang.reflect.Method; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByMethodInDataprovider { WebDriver driver; @BeforeTest public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } @Test(dataProvider = "SearchProvider") public void testMethodA(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); // Print author and search string System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } @Test(dataProvider = "SearchProvider") public void testMethodB(String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); // Print only the search string System.out.println("Welcome ->Unknown user Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** The DataProvider returns values based on the test method name */ @DataProvider(name = "SearchProvider") public Object[][] getDataFromDataprovider(Method m) { if (m.getName().equalsIgnoreCase("testMethodA")) { return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; } else { return new Object[][] { { "Canada" }, { "Russia" }, { "Japan" } }; } } }
出力は次のとおりです。
ITestContext これは、グループに基づいてテストケースの異なるパラメータを作成するために使用できます。
実際の運用では、ITestContext を使用して、テスト方法、ホスト、またはテスト構成に基づいてパラメータ値を変更することができます。
以下のコード例では、
- 私たちはAとBの2つのグループに分かれています。
- 各テストメソッドはグループに割り当てられます
- グループ値がAの場合、1つのデータセットが返されます。
- グループ値がBの場合、別のデータセットが返されます。
package parameters; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByITestContextInDataprovider { WebDriver driver; @BeforeTest(groups = {"A", "B"}) public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } @Test(dataProvider = "SearchProvider", groups = "A") public void testMethodA(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } @Test(dataProvider = "SearchProvider", groups = "B") public void testMethodB(String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); System.out.println("Welcome ->Unknown user Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** The DataProvider supplies an Object array based on ITestContext */ @DataProvider(name = "SearchProvider") public Object[][] getDataFromDataprovider(ITestContext c) { Object[][] groupArray = null; for (String group : c.getIncludedGroups()) { if (group.equalsIgnoreCase("A")) { groupArray = new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; break; } else if (group.equalsIgnoreCase("B")) { groupArray = new Object[][] { { "Canada" }, { "Russia" }, { "Japan" } }; break; } } return groupArray; } }
注意: 実行すると TestNG クラスを直接呼び出すと、まずデータプロバイダが呼び出されますが、グループがまだ利用できないため、プロバイダはグループ情報を読み取ることができません。testng.xml を介してクラスを呼び出すと、ITestContext を介してグループ情報が利用可能になります。テストを実行するには、次の XML を使用してください。
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="test-parameter"> <test name="example1"> <groups> <run> <include name="A" /> </run> </groups> <classes> <class name="parameters.ParameterByITestContextInDataprovider" /> </classes> </test> <test name="example2"> <groups> <run> <include name="B" /> </run> </groups> <classes> <class name="parameters.ParameterByITestContextInDataprovider" /> </classes> </test> </suite>
どちらの仕組みも説明済みなので、実際的な問題はどちらを採用するかということだ。
@Parametersと@DataProvider:どちらを使うべきか
この2つのアプローチは互換性がありません。どちらを選択するかは、テストに必要な値の組み合わせの数と、それらの値がどこから発生するかによって決まります。
| 基準 | @Parameters + testng.xml | @データプロバイダー |
|---|---|---|
| パラメータごとの値 | ちょうど1つ | 行数無制限 |
| 情報元 | XMLファイル内の静的テキスト | Java コード、Excel、CSV、データベース、API |
| サポートされている型 | 文字列から型変換された値 | 任意 Java オブジェクト |
| テスト呼び出し | 構成ごとに1回 | データ行ごとに1回 |
| データの変更には | XMLファイルの編集 | ソースコードを編集するだけで、多くの場合再コンパイルは不要です。 |
| に最適 | ブラウザなどの環境および構成値、 URL、 資格 | さまざまな入力組み合わせにおけるデータ駆動型テスト |
実際には、ほとんどのスイートでは両方を使用します。@Parameters は実行全体を通して一定の環境設定を保持し、@DataProvider は変化するビジネスデータを提供します。データセットがハードコードされた配列のサイズを超えた場合、次のステップはスプレッドシートからデータを読み込むことです。
DataProviderを使用してExcelファイルからテストデータを読み込む方法
ハードコードされた配列は、テスターが記述しない限りスケーリングを停止します Java データの維持管理が必要です。行をスプレッドシートに移動すると、テストデータとテストロジックが分離され、これは実用上、 データ駆動型テストApache POI はワークブックを読み込み、DataProvider は各行を 1 つのテスト呼び出しに変換します。
- 依存関係を追加します。 含める
org.apache.poi:poi-ooxmlMaven または Gradle 構築する。ooxmlアーティファクトは.xlsx形式を処理します。プレーンpoi従来の.xlsファイルのみを読み取ります。 - ワークブックを作成します。 ヘッダー行を0行目に配置し、その下に1行につき1つのテストケースを配置し、テストメソッドの引数ごとに1列を配置してください。
- シートを配列に読み込む。 行数とセル数に基づいてオブジェクト[][]のサイズを設定することで、コードを変更することなく新しい行を取得できます。
- 提供元から返却してください。 テストメソッドのシグネチャは以前と全く同じままです。
import java.io.FileInputStream; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "SearchProvider") public Object[][] readSearchData() throws Exception { FileInputStream file = new FileInputStream("src/test/resources/testdata.xlsx"); Workbook workbook = new XSSFWorkbook(file); Sheet sheet = workbook.getSheetAt(0); // Skip the header row, so subtract one from the physical row count int rows = sheet.getLastRowNum(); int cols = sheet.getRow(0).getPhysicalNumberOfCells(); Object[][] data = new Object[rows][cols]; for (int i = 1; i <= rows; i++) { for (int j = 0; j < cols; j++) { data[i - 1][j] = sheet.getRow(i).getCell(j).getStringCellValue(); } } workbook.close(); file.close(); return data; } }
💡ヒント: コール getStringCellValue() テキストとして書式設定されたセルのみ。数値セルではエラーが発生します。 IllegalStateExceptionこれは、スプレッドシートにIDや金額が含まれている場合に最もよく発生するエラーです。 DataFormatter すべてのセルタイプを文字列として読み込むか、 cell.getCellType() そして明示的に変換する。
データが外部化されると、100 個のテスト ケースを追加することはコードの変更ではなくスプレッドシートの編集になり、同じプロバイダーが複数のテスト クラスを dataProviderClass 先に示されていた属性。
















