数据提供程序和测试XML: Selenium中的参数化

创建软件时,总是希望它能以不同的方式处理不同的数据集。当涉及到测试同样的软件,不能用一组数据来测试它。我们需要参数化。

Selenium中的参数化

Selenium中的参数化是一个参数化测试脚本的过程,以便在运行时将多个数据传递给应用程序。通过参数化测试脚本实现的概念称为数据驱动测试 。

在本教程中,将了解-

  • TestNG中的参数化类型
  • 使用Testng.xml进行参数标注
  • 故障排除
  • 使用数据提供程序的参数
  • 从不同的类调用DataProvider
  • 数据提供程序中的参数类型

TestNG中的参数化类型

为了使参数化更清楚,将在Selenium Webdriver最流行的框架中介绍参数化选项- TestNG 。 确实有两种方式可以实现测试过程中的参数化

  1. 注解和测试XML。
TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium
  1. 数据提供程序下注解。
TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

Testng.xml中的参数可以是套件级别或测试级别

DataProvider中的参数可以采用Method和ITestContext作为参数。

TestNG中的参数注解

TestNG中的参数标注是一种使用.xml文件将值作为参数传递给测试方法的方法。 @Parameters注解方法可用于任何具有 @Test @Before @After或 @Factory注解的方法

使用Testng.xml进行参数标注

如果确实想要处理复杂性&输入组合的数量较少,选择使用注解进行参数化。

测试场景

步骤1) 启动浏览器并转到google.com

步骤2) 输入搜索关键字

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

步骤3) 验证输入的值是否与我们的测试数据提供的值相同

步骤4) 重复2&3,直到输入所有数值

下面是一个示例,说明如何在没有参数的情况下执行此操作

 package parameters;
import org.testng.annotations.Test;
import org.testng.AssertJUnit;
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;
public class NoParameterWithTestNGXML {
    String driverPath = "C:\\geckodriver.exe";
    WebDriver driver;
    @Test
    public void testNoParameter() throws InterruptedException{
        String author = "itxiaonv";
        String searchKey = "india";
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver= new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://google.com");
        WebElement searchText = driver.findElement(By.name("q"));
        //Searching text in google text box
        searchText.sendKeys(searchKey);
        System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
        System.out.println("Thread will sleep now");
        Thread.sleep(3000) ;
        System.out.println("Value in Google Search Box = "+searchText.getAttribute("value") +" ::: Value given by input = "+searchKey);
        //verifying the value in google search box
        AssertJUnit.assertTrue(searchText.getAttribute("value").equalsIgnoreCase(searchKey));
    }
}
 

想象一下,当对3个输入组合执行此操作时,代码将变得多么复杂,现在,让使用TestNG将其参数化。为此,需要

  • 创建将存储参数的XML文件
  • 在测试中,添加注释@Parameters
TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

以下是完整的代码TestNG.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestSuite" thread-count="3" >
 <parameter name="author" value="itxiaonv" />
 <parameter name="searchKey" value="India" />
 <test name="testGuru">
 <parameter name="searchKey" value="UK" />
  <classes>
   <class name="parameters.ParameterWithTestNGXML"></class>
  </classes>
 </test> 
</suite>
 

ParameterWithTestNGXML.java文件

 package parameters;
import org.testng.AssertJUnit;
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.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterWithTestNGXML {
    String driverPath = "C:\\geckodriver.exe";
    WebDriver driver;
    @Test
    @Parameters({"author","searchKey"})
    public void testParameterWithXML( @Optional("Abc") String author,String searchKey) throws InterruptedException{
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://google.com");
        WebElement searchText = driver.findElement(By.name("q"));
        //Searching text in google text box
        searchText.sendKeys(searchKey);
        System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
        System.out.println("Thread will sleep now");
        Thread.sleep(3000) ;
        System.out.println("Value in Google Search Box = "+searchText.getAttribute("value") +" ::: Value given by input = "+searchKey);
        //verifying the value in google search box
        AssertJUnit.assertTrue(searchText.getAttribute("value").equalsIgnoreCase(searchKey));
    }
}
 

要运行脚本,选择XML文件并作为TestNG套件运行。右键单击.xml文件- >运行方式-> TestNG (注:套件)

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

现在,可以在两个级别定义参数

  1. 套件级别-TestNG XML文件的<Suite>标记内的参数将是套件级别参数。
  2. 测试级别–测试XML文件的<Test>标记内的参数将是测试级别参数。

下面是带有套件级别参数的相同测试

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

注: 如果参数名称在套件级别和测试级别相同,则测试级别参数将优先于套件级别。因此,在这种情况下,该测试级别内的所有类将共享被覆盖的参数,而测试级别外的其他类将共享套件级别参数。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

故障排除

第1 不能将testng.xml中的参数值类型转换为相应测试方法的参数,这将引发错误。

考虑以下示例

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

在相应的测试方法中,它需要一个整数值,所以我们在这里会得到一个异常。

第2 @参数在testing.xml中没有相应值

可以通过添加 @可选 注解 在测试方法中的相应参数中。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

第3期 : 希望使用Testng.xml测试同一参数的多个值

答案很简单,这是做不到的!可以有多个不同的参数如果要为一个参数使用多个值,使用DataProviders

TestNG中的数据提供程序

TestNG中的数据提供程序 是用户需要传递复杂参数时使用的方法。需要从Java创建复杂参数,如复杂对象、来自PROPE的对象该方法由@DataProvider注释,并返回一个对象数组。

使用数据提供程序的参数

@Parameters注释很简单 ,但是要测试多组数据,我们需要使用数据提供程序。

要使用我们的测试框架填写数千个Web表单,我们需要一种不同的方法,可以在单个执行流程中提供非常大的数据集。 这种数据驱动的概念是通过以下方式实现的 @DataProvider TestNG中的注解。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

它只有一个 属性“name” 。如果不指定name属性,则DataProvider的名称将与相应的方法名称相同。 数据提供程序返回 二维Java对象 对于测试方法和测试方法,将在M*N类型的对象数组中调用M次。例如,如果DataProvider返回2*3个对象的数组,则对应的测试用例将被调用2次,每次调用3个参数。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

完整示例

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium
 package parameters;
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.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ParameterByDataprovider {
    WebDriver driver;
    String driverPath = "C:\\geckodriver.exe";
    @BeforeTest
    public void setup() {
        //Create firefox driver object
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://google.com");
    }
    / Test case to verify google search box
     * @param author
     * @param searchKey
     * @throws InterruptedException
     */
    @Test(dataProvider="SearchProvider")
    public void testMethod(String author,String searchKey) throws InterruptedException{
        {
            WebElement searchText = driver.findElement(By.name("q"));
            //search value in google searchbox
            searchText.sendKeys(searchKey);
            System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
            Thread.sleep(3000) ;
            String testValue = searchText.getAttribute("value");
            System.out.println(testValue +"::::"+searchKey);
            searchText.clear();
            //Verify if the value in google search box is correct
            Assert.assertTrue(testValue.equalsIgnoreCase(searchKey));
        }
    }
    /
     * @return Object[][] where first column contains 'author'
     * and second column contains 'searchKey'
     */
    @DataProvider(name="SearchProvider")
    public Object[][] getDataFromDataprovider() {
        return new Object[][] {
            { "ITXiaonv", "India" },
            { "Krishna", "UK" },
            { "Bhupesh", "USA" }
        };
    }
}
 

从不同的类调用DataProvider

默认情况下,DataProvider驻留在测试方法所在的类或其基类中。要将其放入其他类中,我们需要将数据提供程序方法设置为静电,而在测试方法中,我们需要添加一个属性 dataProviderClass 在@Test注释里面 。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

代码示例

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

TestClass ParameterDataProviderWithClassLevel.java

 package parameters;
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.BeforeTest;
import org.testng.annotations.Test;
public class ParameterDataproviderWithClassLevel {
    WebDriver driver;
    String driverPath = "C:\\geckodriver.exe";
    @BeforeTest
    public void setup() {
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        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 google text box
        searchText.sendKeys(searchKey);
        System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
        Thread.sleep(3000) ;
        //get text from search box
        String testValue = searchText.getAttribute("value");
        System.out.println(testValue +"::::"+searchKey);
        searchText.clear();
        //verify if search box has 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[][] {
            { "ITXiaonv", "India" },
            { "Krishna", "UK" },
            { "Bhupesh", "USA" }
        };
    }
}
 

数据提供程序中的参数类型

DataProvider方法支持两种类型的参数。

方法 -对于不同的测试方法,如果DataProvider的行为相同的 ,使用方法参数。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

在下面的示例中,

  • 我们检查方法名称是否为testMethodA。
  • 如果是,则返回一组值
  • 否则返回另一组值
 package parameters;
import java.lang.reflect.Method;
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.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ParameterByMethodInDataprovider {
    WebDriver driver;
    String driverPath = "C:\\geckodriver.exe";
    @BeforeTest
    public void setup() {
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://google.com");
    }
    @Test(dataProvider="SearchProvider")
    public void testMethodA(String author,String searchKey) throws InterruptedException{
        WebElement searchText = driver.findElement(By.name("q"));
        //Search text in search box
        searchText.sendKeys(searchKey);
        //Print author and search string
        System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
        Thread.sleep(3000) ;
        String testValue = searchText.getAttribute("value");
        System.out.println(testValue +"::::"+searchKey);
        searchText.clear();
        //Verify if google text box is showing correct value
        Assert.assertTrue(testValue.equalsIgnoreCase(searchKey));
    }
    @Test(dataProvider="SearchProvider")
    public void testMethodB(String searchKey) throws InterruptedException{
        {
            WebElement searchText = driver.findElement(By.name("q"));
            //Search text in search box
            searchText.sendKeys(searchKey);
            //Print only search string
            System.out.println("Welcome ->Unknown user Your search key is->"+searchKey);
            Thread.sleep(3000) ;
            String testValue = searchText.getAttribute("value");
            System.out.println(testValue +"::::"+searchKey);
            searchText.clear();
            //Verify if google text box is showing correct value
            Assert.assertTrue(testValue.equalsIgnoreCase(searchKey));
        }
    }
    /
     * Here DataProvider returning value on the basis of test method name
     * @param m
     * @return
     /
    @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" }
            };
        }
    }
}
 

这是输出

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

ITestContext -它可以用于基于组为测试用例创建不同的参数。

在现实生活中,可以使用ITestContext根据测试方法、主机和测试配置来改变参数值。

TestNG: Parameterization using XML & DataProvider in Selenium
TestNG: Parameterization using XML & DataProvider in Selenium

在下面的代码示例中

  • 我们有A组和B组两个组
  • 每种测试方法都分配给一个组
  • 如果groups的值为A,则返回特定的数据集
  • 如果groups的值为B,则返回另一个数据集
 package parameters;
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.ITestContext;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ParameterByITestContextInDataprovider {
    WebDriver driver;
    String driverPath = "C:\\geckodriver.exe";
    @BeforeTest(groups= {"A","B"})
    public void setup() {
        System.setProperty("webdriver.gecko.driver", driverPath);
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://google.com");
    }
 
    @Test(dataProvider="SearchProvider",groups="A")
    public void testMethodA(String author,String searchKey) throws InterruptedException{
        {
            //search google textbox
            WebElement searchText = driver.findElement(By.name("q"));
            //search a value on it
            searchText.sendKeys(searchKey);
            System.out.println("Welcome ->"+author+" Your search key is->"+searchKey);
            Thread.sleep(3000) ;
            String testValue = searchText.getAttribute("value");
            System.out.println(testValue +"::::"+searchKey);
            searchText.clear();
            //verify correct value in searchbox
            Assert.assertTrue(testValue.equalsIgnoreCase(searchKey));
        }
    }
 
    @Test(dataProvider="SearchProvider",groups="B")
    public void testMethodB(String searchKey) throws InterruptedException{
        {
            //find google search box
            WebElement searchText = driver.findElement(By.name("q"));
            //search a value on it
            searchText.sendKeys(searchKey);
            System.out.println("Welcome ->Unknown user Your search key is->"+searchKey);
            Thread.sleep(3000) ;
            String testValue = searchText.getAttribute("value");
            System.out.println(testValue +"::::"+searchKey);
            searchText.clear();
            //verify correct value in searchbox
            Assert.assertTrue(testValue.equalsIgnoreCase(searchKey));
        }
    }
 
    /
     * Here the DAtaProvider will provide Object array on the basis on ITestContext
     * @param c
     * @return
     */
    @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类,它将首先调用dataProvider,后者无法获取组信息,因为组不可用。使用以下XML调用测试

 <!DOCTYPE suite SYSTEM "http://beust.com/testng/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>
 

总结 :

  • 参数化是创建数据驱动测试的必要方法
  • TestNG支持两种参数化,使用 @Parameter+TestNG.xml 或者 @DataProvider
  • @Parameter+TestNG.xml 里面参数可以放在套件级别和测试级别。如果 两个地方声明了相同的参数名称;测试级别参数将优先于套件级别参数。

  • 使用@Parameter+TestNG.xml一次只能设置一个值,但@DataProvider返回 对象的二维阵列 。
  • 如果DataProvider出现在与测试方法驻留的类不同的类中, 数据提供程序 应该是 静态法 。
  • DataProvider支持两个参数方法和ITestContext。

IT赶路人

专注IT知识分享