ผู้ให้บริการข้อมูลใน TestNG: Selenium ตัวอย่างการกำหนดพารามิเตอร์
⚡ สรุปอย่างชาญฉลาด
การกำหนดพารามิเตอร์ใน Selenium เรียกใช้เมธอดทดสอบเดียวซ้ำๆ กับชุดข้อมูลที่แตกต่างกัน เปลี่ยนสคริปต์เดียวให้เป็นการครอบคลุมการทดสอบที่ขับเคลื่อนด้วยข้อมูล TestNG มีกลไกสองอย่างสำหรับเรื่องนี้ ได้แก่ คำอธิบายประกอบ @Parameters ที่ทำงานร่วมกับ testng.xml และคำอธิบายประกอบ @DataProvider ที่ส่งคืนอาร์เรย์ของอ็อบเจ็กต์สองมิติ

ในการพัฒนาซอฟต์แวร์ เราต้องการให้มันทำงานได้อย่างถูกต้องกับชุดข้อมูลที่หลากหลายเสมอ เมื่อพูดถึงเรื่องนี้ การทดสอบ ซอฟต์แวร์นั้น การตรวจสอบชุดข้อมูลเพียงชุดเดียวไม่เพียงพอ เราจำเป็นต้องตรวจสอบว่าระบบยอมรับทุกชุดค่าผสมที่คาดหวังไว้หรือไม่ สำหรับเรื่องนั้น เราจำเป็นต้องกำหนดพารามิเตอร์ให้กับสคริปต์ทดสอบของเรา นี่คือจุดที่การกำหนดพารามิเตอร์เข้ามามีบทบาท
การกำหนดพารามิเตอร์ใน Selenium
การกำหนดพารามิเตอร์ใน Selenium เป็นกระบวนการในการกำหนดพารามิเตอร์ของสคริปต์ทดสอบเพื่อส่งข้อมูลหลายรายการไปยังแอปพลิเคชันขณะรันไทม์ เป็นกลยุทธ์ในการดำเนินการซึ่งจะรันกรณีทดสอบหลายครั้งโดยอัตโนมัติโดยใช้ค่าที่แตกต่างกัน แนวคิดที่ทำได้โดยการกำหนดพารามิเตอร์ของสคริปต์ทดสอบเรียกว่า การทดสอบที่ขับเคลื่อนด้วยข้อมูล.
ประเภทของการกำหนดพารามิเตอร์ใน TestNG
เพื่อให้เข้าใจเรื่องการกำหนดพารามิเตอร์ได้ชัดเจนยิ่งขึ้น เราจะมาดูตัวเลือกการกำหนดพารามิเตอร์ในเฟรมเวิร์กยอดนิยมตัวหนึ่งกัน Selenium เว็บไดรเวอร์ — TestNG.
มี สองทาง ซึ่งเราสามารถบรรลุถึงการกำหนดพารามิเตอร์ได้ TestNG:
- ด้วยความช่วยเหลือของ คำอธิบายพารามิเตอร์ และ TestNG XML ไฟล์
- ด้วยความช่วยเหลือของ ผู้ให้บริการข้อมูล คำอธิบายประกอบ
แผนภาพด้านบนสรุปการแบ่งประเภทได้ดังนี้: พารามิเตอร์จาก testng.xml สามารถประกาศได้ที่ระดับชุดทดสอบหรือระดับการทดสอบ ในขณะที่พารามิเตอร์จาก DataProvider สามารถรับค่าได้ Method และ ITestContext ในฐานะที่เป็นข้อโต้แย้งของตัวเอง เรามาศึกษาข้อโต้แย้งเหล่านั้นอย่างละเอียดกันเถอะ
พารามิเตอร์ คำอธิบายประกอบใน TestNG
พารามิเตอร์ คำอธิบายประกอบใน TestNG @Parameters เป็นวิธีการที่ใช้ในการส่งค่าไปยังเมธอดทดสอบเป็นอาร์กิวเมนต์โดยใช้ไฟล์ .xml ผู้ใช้อาจต้องส่งค่าไปยังเมธอดทดสอบในระหว่างการทำงาน วิธีการใช้ @Parameters สามารถใช้ได้ในเมธอดใดๆ ที่มี @Test, @Before, @After หรือ @Factory อยู่แล้ว
คำอธิบายพารามิเตอร์ด้วย Testng.xml
เลือกใช้การกำหนดพารามิเตอร์โดยใช้คำอธิบายประกอบเมื่อคุณไม่ต้องการจัดการกับความซับซ้อน และจำนวนชุดค่าผสมของอินพุตมีน้อย
มาดูกันว่ามันทำงานอย่างไร
สถานการณ์ทดสอบ
ขั้นตอน 1) เปิดเบราว์เซอร์แล้วไปที่ Googleด้วย.
ขั้นตอน 2) ป้อนคำค้นหา
ขั้นตอน 3) ตรวจสอบว่าค่าที่ป้อนตรงกับค่าที่ได้จากข้อมูลทดสอบของเรา
ขั้นตอน 4) ทำซ้ำขั้นตอนที่ 2 และ 3 จนกว่าจะป้อนค่าทั้งหมดเสร็จ
| ผู้เขียนทดสอบ | ค้นหาคีย์ |
|---|---|
| Guru99 | อินเดีย |
| Krishna | สหรัฐอเมริกา |
| ภุพเพช | สาธารณรัฐประชาชนจีน |
นี่คือตัวอย่างวิธีการทำ ไม่มี พารามิเตอร์:
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: สามบรรทัดในเวอร์ชันดั้งเดิมของตัวอย่างนี้ไม่สามารถคอมไพล์ได้อีกต่อไป หรือถูกยกเลิกการใช้งานในเวอร์ชันปัจจุบัน 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")ตัวอย่างทั้งหมดด้านล่างนี้ใช้การแก้ไขสามประการเดียวกัน
ศึกษาตัวอย่างข้างต้นและลองนึกภาพว่าโค้ดจะซับซ้อนแค่ไหนเมื่อทำซ้ำแบบนี้สำหรับชุดข้อมูลป้อนเข้าสามแบบ
ต่อไปเรามาทำการกำหนดค่าพารามิเตอร์โดยใช้ 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>
พารามิเตอร์ด้วยTestNGไฟล์ XML.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 แล้วเรียกใช้ในฐานะไฟล์ XML TestNG บน
คลิกขวาที่ไฟล์ .xml -> เรียกใช้ในฐานะ -> TestNG ห้องสวีท (หมายเหตุ: ห้องสวีท)
สามารถกำหนดพารามิเตอร์ได้สองระดับ:
- ห้องสวีท — พารามิเตอร์ภายใน
<suite>แท็กของ TestNG ไฟล์ XML คือพารามิเตอร์ระดับชุดโปรแกรม - ระดับการทดสอบ — พารามิเตอร์ภายใน
<test>แท็กของ TestNG ไฟล์ XML คือพารามิเตอร์ระดับการทดสอบ
ต่อไปนี้คือการทดสอบแบบเดียวกันโดยใช้พารามิเตอร์ระดับชุดทดสอบ:
หมายเหตุ: หากชื่อพารามิเตอร์เหมือนกันทั้งในระดับชุดทดสอบและระดับการทดสอบ พารามิเตอร์ในระดับการทดสอบจะมีลำดับความสำคัญเหนือกว่าพารามิเตอร์ในระดับชุดทดสอบ ในกรณีนั้น คลาสทั้งหมดที่อยู่ภายในระดับการทดสอบนั้นจะใช้พารามิเตอร์ที่ถูกแทนที่ร่วมกัน ในขณะที่คลาสที่อยู่นอกระดับการทดสอบนั้นจะยังคงใช้พารามิเตอร์ในระดับชุดทดสอบต่อไป
การแก้ไขปัญหา
ฉบับที่ 1: หากค่าพารามิเตอร์ในไฟล์ testng.xml ไม่สามารถแปลงประเภทให้ตรงกับพารามิเตอร์ของเมธอดทดสอบที่เกี่ยวข้องได้ จะทำให้เกิดข้อผิดพลาด
พิจารณาตัวอย่างต่อไปนี้:
ในที่นี้ คุณลักษณะ 'ผู้เขียน' เท่ากับ 'Guruค่า '99' เป็นสตริง ในขณะที่เมธอดทดสอบที่เกี่ยวข้องคาดหวังค่าจำนวนเต็ม ดังนั้นจึงเกิดข้อผิดพลาดขึ้น
ฉบับที่ 2: ค่า @Parameters ของคุณไม่มีค่าที่ตรงกันในไฟล์ testng.xml
คุณสามารถแก้ไขปัญหานี้ได้โดยการเพิ่ม @คำอธิบายประกอบเพิ่มเติม (ไม่จำเป็น) ไปยังพารามิเตอร์ที่เกี่ยวข้องในวิธีการทดสอบ
ฉบับที่ 3: คุณต้องการทดสอบค่าหลายค่าของพารามิเตอร์เดียวกันโดยใช้ไฟล์ testng.xml
คำตอบง่ายๆ คือ ทำแบบนั้นไม่ได้ คุณสามารถมีพารามิเตอร์ได้หลายตัว แต่แต่ละพารามิเตอร์สามารถเก็บค่าได้เพียงค่าเดียวเท่านั้น วิธีนี้จะป้องกันการกำหนดค่าตายตัวลงในสคริปต์และทำให้โค้ดสามารถนำกลับมาใช้ใหม่ได้ — คิดว่ามันเป็นเหมือนไฟล์การตั้งค่าสำหรับสคริปต์ของคุณ หากคุณต้องการค่าหลายค่าสำหรับพารามิเตอร์ตัวเดียว ให้ใช้ DataProvider แทน
ผู้ให้บริการข้อมูลใน TestNG
ผู้ให้บริการข้อมูลใน TestNG เป็นวิธีการที่ใช้เมื่อผู้ใช้จำเป็นต้องส่งพารามิเตอร์ที่ซับซ้อน พารามิเตอร์ที่ซับซ้อนจำเป็นต้องสร้างขึ้นจาก Java — สามารถส่งผ่านอ็อบเจ็กต์ที่ซับซ้อน อ็อบเจ็กต์จากไฟล์คุณสมบัติ หรืออ็อบเจ็กต์จากฐานข้อมูลได้โดยใช้เมธอดตัวให้บริการข้อมูล เมธอดนี้จะมีคำอธิบายประกอบด้วย @DataProvider และจะส่งคืนอาร์เรย์ของอ็อบเจ็กต์
พารามิเตอร์ที่ใช้ Dataprovider
การใช้ annotation @Parameters นั้นง่าย แต่หากต้องการทดสอบด้วยชุดข้อมูลหลายชุด เราจำเป็นต้องใช้ Data Provider
ในการกรอกแบบฟอร์มออนไลน์หลายพันรายการโดยใช้เฟรมเวิร์กการทดสอบของเรา เราต้องการวิธีการที่แตกต่างออกไป ซึ่งสามารถรองรับชุดข้อมูลขนาดใหญ่มากในขั้นตอนการทำงานเดียว
แนวคิดที่ขับเคลื่อนด้วยข้อมูลนี้บรรลุผลได้โดย @DataProvider คำอธิบายประกอบใน TestNG.
มันมีเพียงหนึ่งเดียว คุณลักษณะ 'ชื่อ'หากคุณไม่ได้ระบุแอตทริบิวต์ name ชื่อของ DataProvider จะเหมือนกับชื่อของเมธอดที่เกี่ยวข้อง
ผู้ให้บริการข้อมูลส่งคืนข้อมูล สองมิติ Java วัตถุ ไปยังเมธอดทดสอบ และเมธอดทดสอบจะถูกเรียกใช้ M ครั้งสำหรับอาร์เรย์ของอ็อบเจ็กต์ขนาด M×N ตัวอย่างเช่น หาก DataProvider ส่งคืนอาร์เรย์ของอ็อบเจ็กต์ขนาด 2×3 กรณีทดสอบที่เกี่ยวข้องจะถูกเรียกใช้ 2 ครั้ง โดยแต่ละครั้งมีพารามิเตอร์ 3 ตัว
ตัวอย่างที่สมบูรณ์
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 จะอยู่ในคลาสเดียวกับเมธอดทดสอบ หรือในคลาสพื้นฐานของเมธอดนั้น หากต้องการย้ายไปอยู่ในคลาสอื่น ให้สร้างเมธอด DataProvider ขึ้นมาใหม่ คงที่ และเพิ่มแอตทริบิวต์ dataProviderClass ไป @ทดสอบ คำอธิบายประกอบ
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)); } }
DataproviderClass.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
เมธอด DataProvider รองรับพารามิเตอร์สองประเภท
วิธี — ถ้าหาก เดียวกัน DataProvider ควรทำงานแตกต่างกันไปตามวิธีการทดสอบแต่ละแบบ โปรดใช้พารามิเตอร์ Method
ในตัวอย่างต่อไปนี้:
- เราตรวจสอบว่าชื่อเมธอดคือ testMethodA หรือไม่
- ถ้าใช่ ให้ส่งคืนชุดค่าหนึ่งชุด
- มิเช่นนั้น ให้ส่งค่าชุดอื่นกลับมา
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 เพื่อปรับเปลี่ยนค่าพารามิเตอร์ตามวิธีการทดสอบ โฮสต์ หรือการกำหนดค่าการทดสอบได้
ในตัวอย่างโค้ดต่อไปนี้:
- เรามี 2 กลุ่ม คือ กลุ่ม A และกลุ่ม B
- วิธีการทดสอบแต่ละวิธีถูกกำหนดให้กับกลุ่ม
- ถ้าค่ากลุ่มเป็น A จะส่งคืนชุดข้อมูลหนึ่งชุด
- ถ้าค่ากลุ่มเป็น 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: ควรใช้อันไหนดี
ทั้งสองแนวทางไม่สามารถใช้แทนกันได้ การตัดสินใจขึ้นอยู่กับว่าการทดสอบต้องการค่าผสมกี่แบบ และค่าเหล่านั้นมาจากแหล่งใด
| เกณฑ์ | @พารามิเตอร์ + testng.xml | @DataProvider |
|---|---|---|
| ค่าต่อพารามิเตอร์ | หนึ่งอันพอดี | แถวไม่จำกัดจำนวน |
| แหล่งข้อมูล | ข้อความคงที่ในไฟล์ XML | Java โค้ด, Excel, CSV, ฐานข้อมูล, API |
| ประเภทที่รองรับ | การแปลงประเภทค่าจากสตริง | ใด Java วัตถุ |
| การเรียกใช้การทดสอบ | ครั้งละหนึ่งครั้งต่อการกำหนดค่า | ครั้งละหนึ่งแถวข้อมูล |
| การเปลี่ยนแปลงข้อมูลจำเป็นต้อง | การแก้ไขไฟล์ XML | การแก้ไขซอร์สโค้ด มักไม่จำเป็นต้องคอมไพล์ใหม่ |
| เหมาะที่สุดสำหรับ | ค่าสภาพแวดล้อมและการตั้งค่าต่างๆ เช่น เบราว์เซอร์ URLข้อมูลประจำตัว | การทดสอบโดยใช้ข้อมูลเป็นหลัก ครอบคลุมการผสมผสานข้อมูลป้อนเข้าหลายรูปแบบ |
ในทางปฏิบัติ ชุดโปรแกรมส่วนใหญ่ใช้ทั้งสองอย่าง: @Parameters ทำหน้าที่เก็บค่าการตั้งค่าสภาพแวดล้อมซึ่งคงที่ตลอดการทำงาน และ @DataProvider ทำหน้าที่จัดหาข้อมูลทางธุรกิจที่เปลี่ยนแปลงไป เมื่อชุดข้อมูลมีขนาดใหญ่เกินกว่าอาร์เรย์ที่กำหนดไว้ตายตัว ขั้นตอนต่อไปคือการอ่านข้อมูลจากสเปรดชีต
วิธีการอ่านข้อมูลทดสอบจากไฟล์ Excel โดยใช้ DataProvider
อาร์เรย์ที่กำหนดค่าตายตัวจะหยุดปรับขนาดเมื่อผู้ทดสอบที่ไม่ได้เขียนโค้ด Java จำเป็นต้องรักษาข้อมูลไว้ การย้ายแถวลงในสเปรดชีตจะแยกข้อมูลทดสอบออกจากตรรกะการทดสอบ ซึ่งเป็นรูปแบบที่ใช้งานได้จริงของ การทดสอบที่ขับเคลื่อนด้วยข้อมูลApache POI อ่านเวิร์กบุ๊ก และ DataProvider จะแปลงแต่ละแถวให้เป็นการเรียกใช้งานทดสอบหนึ่งครั้ง
- เพิ่มการพึ่งพา (dependency) เพิ่ม
org.apache.poi:poi-ooxmlใน Maven ของคุณ หรือ Gradle สร้าง.ooxmlartifact รองรับรูปแบบไฟล์ .xlsx; แบบธรรมดาpoiรองรับเฉพาะไฟล์ .xls รุ่นเก่าเท่านั้น - สร้างเวิร์กบุ๊ก วางแถวส่วนหัวไว้ในแถวที่ 0 และวางกรณีทดสอบหนึ่งกรณีต่อแถวถัดจากนั้น โดยแต่ละคอลัมน์จะแทนอาร์กิวเมนต์ของวิธีการทดสอบหนึ่งข้อ
- อ่านข้อมูลจากชีตลงในอาร์เรย์ กำหนดขนาดของอ็อบเจ็กต์[][] จากจำนวนแถวและเซลล์ เพื่อให้สามารถดึงแถวใหม่ได้โดยไม่ต้องแก้ไขโค้ด
- ส่งคืนจากผู้ให้บริการ ลายเซ็นของเมธอดทดสอบยังคงเหมือนเดิมทุกประการ
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ซึ่งเป็นข้อผิดพลาดที่พบบ่อยที่สุดเมื่อสเปรดชีตมีรหัสหรือจำนวนเงิน ใช้ DataFormatter เพื่ออ่านเซลล์ทุกประเภทเป็นสตริง หรือเปิดใช้งาน cell.getCellType() และแปลงอย่างชัดเจน
เมื่อข้อมูลถูกแยกออกมาภายนอก การเพิ่มกรณีทดสอบอีกร้อยกรณีก็กลายเป็นเพียงการแก้ไขสเปรดชีตแทนที่จะเป็นการแก้ไขโค้ด และผู้ให้บริการรายเดียวกันสามารถป้อนคลาสทดสอบหลายคลาสผ่านทางระบบได้ dataProviderClass คุณลักษณะที่แสดงไว้ก่อนหน้านี้
















