测试自动化,或所谓的自动化测试,并不像听起来那样容易。 必须考虑所有可能的用户交互的所有排列和组合,并且在此基础上,您将必须创建测试脚本以通过多种浏览器和OS组合来验证Web应用程序。 这就是参数化在Selenium自动化测试中起关键作用的地方。 在本TestNG教程中,我将向您展示如何在TestNG中执行参数化以进行Selenium自动化测试。
为什么我们要参数化?
在用于Web UI测试的现实世界中,我们希望我们的网站或Web应用程序可以在各种输入下正常工作,并且实际上不可能仅凭一个数据集来验证我们的方案。 因此,当暴露给浏览器和OS的不同数据集或不同组合时,我们确保应用程序能够按预期运行。 多个测试组合意味着多个输入值。
现在,您不能每次都在测试自动化脚本中对测试值进行硬编码,否则,进行一项更改将需要您编辑许多测试自动化脚本。 这就是TestNG或其他任何参数中出现参数的地方,而我们参数化Selenium自动化测试脚本的原因是在运行时为Web应用程序提供了不同的数据集。
为什么要使用TestNG?
如果您的应用程序涉及输入不同类型的用户交互,则必须进行参数化。 我们可以根据所使用的框架对自动化脚本进行参数化,例如用于硒自动化测试的TestNG框架中的参数化。 我们可以考虑使用excel文件来获取数据集,然后在自动化脚本中使用它,但是随着我们增强自动化套件,有必要使用更强大的测试自动化框架(如TestNG)来以更强大的方式涵盖广泛的测试。 在本文中,我们将主要关注TestNG中的参数化,在TestNG中可以实现的方法以及如何在Selenium自动化测试脚本中编写这些参数。 首先让我们开始理解TestNG中不同类型的参数化,以及如何实现相同的功能。
TestNG中的参数化类型
因此,首先我们可以通过两种方式在TestNG中实现参数化。
- 使用“参数注释”和TestNG XML文件。
- 使用“ DataProvider批注”。
使用@Parameters注释和XML文件在TestNG中进行参数化
首先让我们看看在类中编写参数注释的简单语法:
@Parameter({“parameter name”})
请注意,我们也可以在注释中使用多个参数,这些参数可以编写如下: @Parameters({“param1”,”param2”,”param3”})
到目前为止,参数已被限定为testng.xml文件中的Suite或Test标签。 如果在Suite和Test中都传递了相同的参数值,则优先级将赋予Test标记中传递的参数值。
在继续进行参数化示例之前,我们需要了解在TestNG中使用参数化对Selenium自动化测试活动有什么好处。 考虑一种在Google之类的搜索引擎中搜索某些关键字的方案。 我们将必须为每个关键字编写相同的代码行才能获得不同的结果,但这不是可行的方法。 这就是TestNG或Selenium的任何其他测试自动化框架中的参数化出现的地方。 使用TestNG中的参数化,可以将这些关键字作为不同的参数传递到testng.xml中,并在Selenium自动化测试套件中添加@parameters批注。 让我们以示例来看。
场景:在浏览器中打开google.com并分别搜索3个关键字
要完成此方案,以下是我们的脚本必须执行的详细步骤:
- 启动浏览器并打开www.google.com。
- 在搜索框中添加第一个关键字作为输入,然后点击搜索。
- 验证UI上的输入值是否与测试数据相同。
- 对其他2个关键字重复上述两个步骤。
搜寻关键字 |
---|
硒 |
QTP |
杰米特 |
下面的代码显示了如何在TestNG中不进行参数化的情况下做到这一点。
package parameterization;
import java.util.concurrent.TimeUnit;
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.Test;
public class WithoutParameter {
WebDriver driver;
@Test
public void noParam(){
//Declaring our first keyword
String keyWord="Selenium";
//Initializing Driver
System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
//Opening search engine
driver.get("https://google.com");
//Finding search text box
WebElement searchBox = driver.findElement(By.name("q"));
//Sending keyword value
searchBox.sendKeys(keyWord);
System.out.println("The search keyword entered is : " +keyWord);
//Verifying the keyword on UI
Assert.assertTrue(searchBox.getAttribute("value").equalsIgnoreCase(keyWord));
driver.quit();
}
}
为了传递其他2个关键字,我们将不得不再次为字符串' keyWord '用不同的关键字值编写同一段代码,这将导致冗长且重复的代码。 而且,将来,如果您必须测试更多的关键字值,就必须编写更多的测试。
现在让我们通过在testng.xml中绕过这些关键字作为参数并在测试中添加@parameters注释来简化问题。
Java代码:
package parameterization;
import java.util.concurrent.TimeUnit;
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.Parameters;
import org.testng.annotations.Test;
public class ParameterizedClass {
WebDriver driver;
@Parameters("keyWord")
@Test
public void Parameterpassing(String keyWord){
//Initializing Driver
//Mention the path to your local webdriver
System.setProperty("webdriver.chrome.driver", "D:\\LocalDriver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
//Opening search engine
driver.get("https://google.com");
//Finding search text box
WebElement searchBox = driver.findElement(By.name("q"));
//Sending keyword value
searchBox.sendKeys(keyWord);
System.out.println("The search keyword entered is : " +keyWord);
//Verifying the keyword on UI
Assert.assertTrue(searchBox.getAttribute("value").equalsIgnoreCase(keyWord));
driver.quit();
}
}
这是TestNG.xml,将用于在Selenium自动化测试的TestNG中执行参数化。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="3" parallel="tests" name="suite">
<test name="demo1" >
<parameter name="keyWord" value="Selenium" />
<classes>
<class name="com.lambdatest.ParameterizedClass"/>
</classes>
</test> <!-- Test -->
<test name="demo2" >
<parameter name="keyWord" value="LambdaTest" />
<classes>
<class name="com.lambdatest.ParameterizedClass"/>
</classes>
</test> <!-- Test -->
<parameter name="keyWord" value="Browser Testing" />
<test name="demo3" >
<classes>
<class name="com.lambdatest.ParameterizedClass"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
现在,您可以运行此测试以检查是否将我们的参数值传递给我们的测试方法,从而获得了所需的结果。 您可以按照以下步骤运行:
步骤1:在项目浏览器中的testng.xml文件上单击鼠标右键,然后单击“运行方式”:
![](https://i-blog.csdnimg.cn/blog_migrate/eecef6bc370fafad0759585fea4f68bd.png)
步骤2:选择以TestNG Suite运行,您可以看到可通过电子邮件发送的报告或摘要以查看结果。
![](https://i-blog.csdnimg.cn/blog_migrate/00f5ca08e294e4988177d71c9ba0bc56.png)
因此,下一次我们必须针对不同的测试值运行相同的测试,而不是将同一段代码复制复制到多个文件中时,我们只需编辑.xml文件,包括更多的值并运行套件。 而已。 这就是通过利用TestNG中的参数化来实现Selenium自动化测试的效率和节省时间的方式。
TestNG中的参数设置是否可以帮助我们进行自动浏览器测试?
到目前为止,在此用于参数化的TestNG教程中,您可能已经通过上一节中说明的示例认识到了参数的重要性。 现在,您可能已经在考虑将参数化合并到TestNG脚本中以进行自动浏览器测试的方法。 让我帮助您从一个非常普遍的场景开始,在这个场景中我们需要在多个浏览器上执行测试,让我们看看如何利用参数来执行自动化的浏览器测试。
场景:通过将浏览器名称作为参数来打印特定的浏览器值。
Java代码:
package parameterization;
import org.testng.annotations.Test;
import org.testng.annotations.Parameters;
public class ParameterPass {
@Parameters("browser")
@Test
public void test1(String browser) {
if(browser.equalsIgnoreCase("FF"))
{
System.out.println("The browser value is : " +browser);
}else if(browser.equalsIgnoreCase("Chrome"))
{
System.out.println("The browser value is : " +browser);
}else if(browser.equalsIgnoreCase("IE"))
{
System.out.println("The browser value is : " +browser);
}
else
{
System.out.println("Incorrect browser value passed.");
}
}
}
Testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Firefox Test">
<parameter name="browser" value="FF"/>
<classes>
<class name="parameterization.ParameterPass"/>
</classes>
</test>
<test name="IE Test">
<parameter name="browser" value="IE"/>
<classes>
<class name="parameterization.ParameterPass"/>
</classes>
</test>
<test name="Incorrect Browser">
<parameter name="browser" value="XYZ"/>
<classes>
<class name="parameterization.ParameterPass"/>
</classes>
</test>
</suite>
运行上述testng xml时,您将在控制台中看到以下输出:
![](https://i-blog.csdnimg.cn/blog_migrate/1f8b545d9bba9bd4ae84e6681316dcf7.png)
如果查看详细的结果,您会发现在测试结果摘要中还打印了XML中传递的参数值:
![](https://i-blog.csdnimg.cn/blog_migrate/54565aaf137700b634186f1ebc11dd59.png)
可通过电子邮件发送的报告显示了传递给不同测试的不同参数,因此可以更轻松地合并结果:
![](https://i-blog.csdnimg.cn/blog_migrate/cda70ab45d0231ea1813aca1c35856e2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/133356d4b752900fb9017960a1ba8a65.png)
现在让我们尝试将2个参数传递给我们的测试,以了解如何利用参数组合进行Selenium自动化测试。 请注意,无论传递给测试的参数数量是多少,都需要在测试方法中以正确的顺序接受相同数量的参数。
方案:通过传递浏览器名称以及URL作为参数来打印特定的浏览器和URL值。
package parameterization;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterPass_Multiple {
@Parameters({"url","browser"})
@Test
public void test1(String url,String browser)
{
if(browser.equalsIgnoreCase("FF"))
{
System.out.println("The browser value is : " +browser);
}
else if(browser.equalsIgnoreCase("Chrome"))
{
System.out.println("The browser value is : " +browser);
}
else if(browser.equalsIgnoreCase("IE"))
{
System.out.println("The browser value is : " +browser);
}
else
{
System.out.println("Incorrect browser value passed.");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Firefox Test">
<parameter name="url" value="http://www.google.com"/>
<parameter name="browser" value="FF"/>
<classes>
<class name="parameterization.ParameterPass_Multiple"/>
</classes>
</test>
<test name="Chrome Test">
<parameter name="url" value="http://www.yahoo.com"/>
<parameter name="browser" value="Chrome"/>
<classes>
<class name="parameterization.ParameterPass_Multiple"/>
</classes>
</test>
</suite>
现在,在运行上述xml时,将生成以下输出,其中将输出已传递的两个参数:
![](https://i-blog.csdnimg.cn/blog_migrate/e7b7e3e23bc1823db54008bde012d3f9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0fe4dd210b84e08a78b5e2e547fff73b.png)
电子邮件报告:
![](https://i-blog.csdnimg.cn/blog_migrate/ddb8b0f7c9369361f71e9f32f907cecb.png)
在线硒网格的TestNG中的参数化
参数化是使用TestNG构建简洁的“测试驱动测试”框架的一种巧妙方法。 由您决定如何在TestNG中利用不同类型的参数化,或者在用例需要时同时利用两者。
下一个要回答的问题是,TestNG中的参数化是否可以与LambdaTest提供的包含2000多种实际浏览器的在线Selenium Grid一起使用?
是的,它确实! 实际上,TestNG或任何其他框架中的参数化被认为是在多个不同的测试环境上并行运行测试的最佳方法之一,尤其是在必须定期更改要测试的测试环境的情况下。
例如,让我们假设您有一个要在多个测试环境上运行的测试,以确保该网页与跨浏览器兼容。 这是自动跨浏览器测试的一个典型示例,现在几乎是每个通过Web开展业务的组织的主要要求。
要在LambdaTest Selenium Grid上运行测试,您需要定义所需的功能对象,该对象指示我们的在线Selenium Grid有关在哪些环境上运行测试的知识。 为此,您可以参数化所需功能对象的值。 例如,考虑以下代码。 这是一个简单的脚本,可打开待办事项列表并执行一些操作。 通过在XML文件中参数化所需功能环境值,可以在多个环境中运行同一脚本。
package com.lambdatest;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.By;
//import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
//import org.testng.annotations.AfterSuite;
import org.testng.annotations.Parameters;
import org.testng.annotations.AfterTest;
//import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class TestNGTodo4 {
private RemoteWebDriver driver;
private String Status="failed";
@BeforeTest
@Parameters({ "os", "browser", "version", "build" })
public void setup( String os, String browser, String version, String build) throws MalformedURLException {
String username = "mudits";
String authkey = "kIVQzcwYkSMgZFWoSMxQjcR3ASJo2BIOUQ97GmTwdnPEOFEO2b";
String hub = "@hub.lambdatest.com/wd/hub";
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("platform", os);
caps.setCapability("browserName", browser);
caps.setCapability("version", version);
caps.setCapability("build", build);
caps.setCapability("name", "TestNG-Todo-Script-4");
caps.setCapability("network", true);
caps.setCapability("visual", true);
caps.setCapability("video", true);
caps.setCapability("console", true);
driver = new RemoteWebDriver(new URL("https://" + username + ":" + authkey + hub), caps);
}
@Test
public void basicTest() throws InterruptedException {
String spanText;
System.out.println("Loading Url");
driver.get("https://4dvanceboy.github.io/lambdatest/todo.html");
System.out.println("Checking Box");
driver.findElement(By.name("todo-1")).click();
System.out.println("Checking Another Box");
driver.findElement(By.name("todo-2")).click();
System.out.println("Checking Box");
driver.findElement(By.name("todo-3")).click();
System.out.println("Checking Another Box");
driver.findElement(By.name("todo-4")).click();
driver.findElement(By.id("todotext")).sendKeys(" List Item 6");
driver.findElement(By.id("addbutton")).click();
driver.findElement(By.id("todotext")).sendKeys(" List Item 7");
driver.findElement(By.id("addbutton")).click();
driver.findElement(By.id("todotext")).sendKeys(" List Item 8");
driver.findElement(By.id("addbutton")).click();
System.out.println("Entering Text");
driver.findElement(By.id("todotext")).sendKeys("Get Taste of Lambda and Stick to It");
driver.findElement(By.id("addbutton")).click();
System.out.println("Checking Another Box");
driver.findElement(By.name("todo-9")).click();
// Let's also assert that the todo we added is present in the list.
spanText = driver.findElementByXPath("/html/body/div/div/div/ul/li[9]/span").getText();
Assert.assertEquals("Get Taste of Lambda and Stick to It", spanText);
Status="passed";
//Thread.sleep(150);
System.out.println("TestFinished");
}
@AfterTest
public void tearDown() {
driver.executeScript("lambda-status=" + Status);
System.out.println(this.getClass().getName());
driver.quit();
}
}
Here’s the Corresponding XML file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="3" parallel="tests" name="suite">
<parameter name="build" value="Demo-TestNG" />
<test name="demo1" >
<parameter name="os" value="windows 10" />
<parameter name="browser" value="chrome" />
<parameter name="version" value="73" />
<classes>
<class name="com.lambdatest.TestNGTodo4"/>
</classes>
</test> <!-- Test -->
<test name="demo2" >
<parameter name="os" value="windows 8.1" />
<parameter name="browser" value="firefox" />
<parameter name="version" value="59" />
<classes>
<class name="com.lambdatest.TestNGTodo5"/>
</classes>
</test> <!-- Test -->
<parameter name="os" value="macOS Mojave" />
<parameter name="browser" value="safari" />
<parameter name="version" value="12" />
<test name="demo3" >
<classes>
<class name="com.lambdatest.TestNGTodo6"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
您是否注意到我如何将Suite标记中的线程数和并行值用于Selenium自动化测试?
上面的脚本将在3个不同的环境中运行相同的测试类,而最好的部分是它们将并行运行。 这意味着所有三个测试将同时执行,从而将您的测试执行时间缩短了很多倍。 感谢Selenium Grid允许我们利用Selenium进行并行测试 。
要考虑的事情
在参加完此TestNG教程之后,到目前为止,您必须对在下一个项目中使用参数进行Selenium自动化测试感到信心满满,也许有些激动,但要花一会儿时间。 在使用@Parameters批注时,必须注意几点。
⟶如果尝试将testng.xml中的参数值类型转换为相应的测试方法参数,则将引发错误。 例如,如果您将method参数指定为integer ,但是在TestNG.xml中传递了String值,则会出现如下异常:
![](https://i-blog.csdnimg.cn/blog_migrate/1b8376016791292362affa4910081b55.png)
Testng.xml:
![](https://i-blog.csdnimg.cn/blog_migrate/56fdb39e7eafd4f0df33717c6983fc52.png)
Optional 使用@Optional批注
如果我们在方法中定义的参数未出现在testng.xml中,则将出现testNG异常,并且测试将跳过。 为了克服这种情况,我们可以使用@Optional注释。 首先让我们看看它的语法:
@Parameter(“browser”)
@Test
public void paramCheck(@Optional(“OptionalParameter”) String val) { …. }
让我们通过此TestNG教程中的示例深入了解这一点。
Java代码:
package parameterization;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class optionalParameter {
@Parameters("Param One")
@Test
public void testOptionOne(String firstParam){
System.out.println("The first parameter is : " +firstParam);
}
@Parameters("Param Two")
@Test
public void testOptionTwo(@Optional("OptionalParameter")String secondParam){
System.out.println("The second parameter is : " +secondParam);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<parameter name="Param One" value="My First Parameter"/>
<parameter name="Param Two" value="My Second Parameter"/>
<test name="Test">
<classes>
<class name="parameterization.optionalParameter"/>
</classes>
</test>
</suite>
运行上述testng.xml时,我们将获得简单的结果,其中将显示第一个和第二个参数,因为这两个参数均已在XML中明确声明。 在下面的输出图像中也显示了相同的内容。
![](https://i-blog.csdnimg.cn/blog_migrate/62128500ad32427d34202f1bd65fdcbe.png)
现在让我们对xml中的第二个参数进行注释,并查看@Optional注释的工作方式:
新的testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<parameter name="Param One" value="My First Parameter"/>
<!-- <parameter name="Param Two" value="My Second Parameter"/> -->
<test name="Test">
<classes>
<class name="parameterization.optionalParameter"/>
</classes>
</test>
</suite>
在运行此新XML时,我们看到TestNG中的Optional参数已在现在正在打印的测试方法中声明,并且在任何地方都没有抛出异常:
![](https://i-blog.csdnimg.cn/blog_migrate/8cc5680df0b029dfe6760f843911911e.png)
may在某些情况下,您需要使用testng.xml测试参数的多个值。 @Parameters注释不能达到目的。 我们可以有很多参数,但是每个参数都可以有一个值,从而使我们的代码可重用。 它更像我们项目的配置文件。 您可以使用多个值作为参数来使用数据提供程序。
该TestNG教程的下一部分将详细讨论数据提供程序及其在Selenium自动化测试中的用法。
使用数据提供程序在TestNG中进行参数化
在上面的部分中,我们看到了如何在框架中使用@Parameters批注来获得各种结果。 现在,在继续进行过程中,我们将遇到不得不对多组数据使用测试脚本的情况。 我们可能需要在一次执行中使用庞大的数据集。 这种类型的测试也称为数据驱动测试,可以通过我们的TestNG框架中的@DataProvider注释方便地实现。
现在让我们首先查看@DataProvider批注的语法。
@DataProvider(name=”testData”)
public Object[ ][ ] TestDataFeed(){
在开始使用它在TestNG中进行参数化之前,需要注意两点,首先,@DataProvider仅具有一个属性“ name ”。 其次,它是可选的,如果您未指定它,则名称将与相应的方法名称相同。
此数据提供程序返回二维数组对象。
让我们尝试通过一个简单的示例来理解这一点,在该示例中,我们尝试使用数据提供程序传递纪念碑和城市名称。 您可以进一步将此示例用作使用其他电子邮件ID和密码登录Gmail或Facebook的基础。
场景:在浏览器中打开google.com并分别搜索3个关键字组合。
以下是执行此操作的步骤:
- 启动浏览器以打开www.google.com。
- 搜索第一个关键字组合。
- 获取页面标题。
- 重复上述步骤,即对其他2个关键字组合使用2和3。
纪念碑 | 市 |
---|---|
印度门 | 新德里 |
泰姬陵 | 阿格拉 |
查尔·米纳尔 | 海得拉巴 |
Java代码:
package dataProvider;
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.DataProvider;
import org.testng.annotations.Test;
public class Data_Provider {
WebDriver driver;
@Test(dataProvider="searchText")
public void paramByDataProvider(String monument,String city) throws InterruptedException {
//Initializing Driver
System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
driver = new FirefoxDriver();
//Opening search engine
driver.get("https://google.com");
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(monument +" "+city);
System.out.println("You are trying to search " +monument+ " which is in " +city);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
driver.quit();
}
/*Data Provider which returns Object[][] wherein
* first column has 'monument' and the second one has 'city'
**/
@DataProvider(name="searchText")
public Object[][] getDataProviderData(){
Object[][] searchWords=new Object[3][2];
//Enter data into Object Array
searchWords[0][0]="India Gate";
searchWords[0][1]="Delhi";
searchWords[1][0]="Taj Mahal";
searchWords[1][1]="Agra";
searchWords[2][0]="Char Minar";
searchWords[2][1]="Hyderabad";
return searchWords;
}
}
要运行上面的代码,我们在TestNG.xml下面使用并像在上面的示例中一样进行测试:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Firefox Test">
<classes>
<class name="parameterization.Data_provider"/>
</classes>
</test>
</suite> <!-- Suite -->
我们将收到以下输出,其中总结了传递的数据提供者和相应的结果:
![](https://i-blog.csdnimg.cn/blog_migrate/ee0a55fa33211b24f6434b8774525f76.png)
可通过电子邮件发送的报告:
![](https://i-blog.csdnimg.cn/blog_migrate/3eba4f8d9b8852e9d9ccbe3e7618112b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bac05afe1841ad231073b3eff2a0ff47.png)
在上面的示例中,我们尝试了从同一类调用数据提供程序。 您还可以通过简单地使数据提供者方法静态化并在测试方法注释中提供数据提供者类来从另一个类调用数据提供者。 让我们为数据提供者创建一个不同的类,看看同一示例。
数据提供程序类的Java代码:
package dataProvider;
import org.testng.annotations.DataProvider;
public class DataProviderClass {
@DataProvider(name="searchText")
public static Object[][] getDataProviderData(){
Object[][] searchWords=new Object[3][2];
//Enter data into Object Array
searchWords[0][0]="India Gate";
searchWords[0][1]="Delhi";
searchWords[1][0]="Taj Mahal";
searchWords[1][1]="Agra";
searchWords[2][0]="Char Minar";
searchWords[2][1]="Hyderabad";
return searchWords;
}
}
调用数据提供程序的类的Java代码:
package dataProvider;
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.Test;
public class ClassLevelDataProvider {
WebDriver driver;
@Test(dataProvider="searchText",dataProviderClass=DataProviderClass.class)
public void paramByDataProvider(String monument,String city) throws InterruptedException {
//Initializing Driver
System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
driver = new FirefoxDriver();
//Opening search engine
driver.get("https://google.com");
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(monument +" "+city);
System.out.println("You are trying to search " +monument+ " which is in " +city);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
driver.quit();
}
}
TestNG.xml运行上面的代码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Firefox Test">
<classes>
<class name="parameterization.ClassLevelDataProvider"/>
</classes>
</test>
</suite> <!-- Suite -->
在跑步时,您可以亲自看到我们收到的结果与以前相同。 为了更多地了解我们在自动化中可能遇到的各种情况,重要的是要理解更多一些使用带有参数viz Method和ITestContext的Data Provider注释的示例 。
示例1 –在TestNG中使用方法参数
如果我们希望同一个数据提供者为不同的方法工作而不同,例如在为不同的测试方法测试不同的数据集的情况下,我们将在TestNG中使用方法参数。 让我们看一个遵循以下步骤的示例:
- 检查方法名称是否为国内
- 如果是,则返回一组值
- 如果不是,那么另一套价值
Java代码:
package dataProvider;
import java.lang.reflect.Method;
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.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class dataProviders {
WebDriver driver;
@BeforeMethod
public void setUp(){
//Initializing Driver
System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
driver = new FirefoxDriver();
//Opening search engine
driver.get("https://google.com");
}
@AfterMethod
public void tearDown(){
driver.quit();
}
@Test(dataProvider="destinations")
public void domesticMonuments(String monument,String city) throws InterruptedException{
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(monument +" "+city);
System.out.println("You are trying to search " +monument+ " which is in " +city);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
}
@Test(dataProvider="destinations")
public void intlDestinations(String location) throws InterruptedException{
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(location);
System.out.println("You are trying to search : " +location);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
}
@DataProvider(name="destinations")
public Object[][] getDataProviderData(Method m){
if(m.getName().equalsIgnoreCase("domesticMonuments")){
return new Object[][]{
{ "India Gate", "Delhi" },
{ "Taj Mahal", "Agra" },
{ "Char Minar", "Hyderabad" }
};
}
else{
return new Object[][]{
{"Paris"},
{"Cairo"},
{"Washington"}
};
}
}
}
Testng.XML运行上面的代码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" >
<test name="Firefox Test">
<classes>
<class name="parameterization.dataProviders"/>
</classes>
</test>
</suite>
运行xml的结果如下所示,您将能够看到所使用的数据提供者的详细信息。
![](https://i-blog.csdnimg.cn/blog_migrate/499819eeeb75642779a34ef8a7598f31.png)
示例2 –在TestNG中使用ITestContext参数
假设我的测试方法分配给不同的组,并且我需要对不同的组使用不同的测试数据。 在这种情况下,我们可以将ITestContext参数与数据提供程序注释一起使用。 让我们看一个相同的例子。
Java代码:
package dataProvider;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ITestContext_DP {
WebDriver driver;
@BeforeMethod(groups={"One","Two"})
public void setUp(){
//Initializing Driver
System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
driver = new FirefoxDriver();
//Opening search engine
driver.get("https://google.com");
}
@AfterMethod(groups={"One","Two"})
public void tearDown(){
driver.quit();
}
@Test(dataProvider="searchKey" , groups="One")
public void testMethodOne(String monument,String city) throws InterruptedException{
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(monument +" "+city);
System.out.println("You are trying to search " +monument+ " which is in " +city);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
}
@Test(dataProvider="searchKey" , groups="Two")
public void testMethodTwo(String location) throws InterruptedException{
WebElement searchBox=driver.findElement(By.name("q"));
searchBox.sendKeys(location);
System.out.println("You are trying to search : " +location);
WebElement srchBtn = driver.findElement(By.name("btnK"));
srchBtn.submit();
Thread.sleep(3000);
System.out.println("The page title is: " +driver.getTitle());
}
@DataProvider(name="searchKey")
public Object[][] getDataProviderData(ITestContext c){
Object[][] grpArr = null;
for (String grp : c.getIncludedGroups()){
if(grp.equalsIgnoreCase("One")){
grpArr = new Object[][]{
{ "India Gate", "Delhi" },
{ "Taj Mahal", "Agra" },
{ "Char Minar", "Hyderabad" }
};
break;
}
else if(grp.equalsIgnoreCase("Two")){
grpArr = new Object[][]{
{"Paris"},
{"Cairo"},
{"Washington"}
};
}
}
return grpArr;
}
}
要调用这个testNG类,可以在xml下面使用,它将基于不同的组运行两个测试集。
Testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" >
<test name="First DP Run">
<groups>
<run>
<include name = "One" />
</run>
</groups>
<classes>
<class name="dataProvider.ITestContext_DP"/>
</classes>
</test>
<test name="Second DP Run">
<groups>
<run>
<include name = "Two" />
</run>
</groups>
<classes>
<class name="dataProvider.ITestContext_DP"/>
</classes>
</test>
</suite>
运行上面的xml将产生如下结果:
![](https://i-blog.csdnimg.cn/blog_migrate/27ab7ac987020a3c3515829a2b9710ee.png)
结论
TestNG中的参数化允许您以更有效的方式执行数据驱动的测试。 通过声明参数,您不必为单个测试套件的不同测试输入编写多个测试自动化脚本,从而使维护维护自动化代码更容易。 我希望这个TestNG教程能够帮助您利用Selenium自动化测试脚本。 可以使用DataProvider或带有TestNG.xml的Parameter批注来完成Selenium自动化测试脚本的TestNG中的参数化。 我们通过示例详细讨论了两种方式的参数化。 我们意识到DataProvider进一步提供了两个参数,即Method和ITestContext 。 现在,您可以使用TestNG中的参数化为下一个项目启动测试自动化脚本。 在下面的评论部分中,让我知道您对此TestNG教程的想法。 如果您有任何疑问或疑问,请随时发布。 祝您测试愉快!