Provedor de dados e TestNG XML: Parametrização em Selenium(Exemplo)

À medida que criamos software, sempre desejamos que ele funcione de maneira diferente com um conjunto diferente de dados. Quando se trata de Ensaios o mesmo software, não podemos ser injustos ao testá-lo com apenas um conjunto de dados. Aqui, novamente, precisamos verificar se nosso sistema está aceitando todos os conjuntos de combinações que se espera que suportem. Para isso, precisamos parametrizar nossos scripts de teste. Aí vem a parametrização na imagem.

Parametrização em Selenium

Parametrização em Selenium é um processo para parametrizar os scripts de teste para passar vários dados para a aplicação em tempo de execução. É uma estratégia de execução que executa automaticamente casos de teste várias vezes usando valores diferentes. O conceito alcançado pela parametrização dos scripts de teste é denominado Teste baseado em dados.

Tipo de Parametrização em TestNG-

Para deixar a parametrização mais clara, examinaremos as opções de parametrização em um dos frameworks mais populares para Selenium Driver da Web – TestNG.

Tem dois caminhos pelo qual podemos obter parametrização em TestNG

  1. Com a ajuda de parâmetros anotação e TestNG XML arquivo.

    Tipo de parametrização em TestNG

  2. Com a ajuda de DataProvider anotação.

    Tipo de parametrização em TestNG

Tipo de parametrização em TestNG

Os parâmetros de Testng.xml podem ser de suíte ou de teste

O parâmetro do DataProvider pode usar Method e ITestContext como parâmetro.

Vamos estudá-los em detalhes –

Anotação de parâmetros em TestNG

Anotação de parâmetros em TestNG é um método usado para passar valores para os métodos de teste como argumentos usando o arquivo .xml. Pode ser necessário que os usuários passem os valores para os métodos de teste durante o tempo de execução. O método de anotação @Parameters pode ser usado em qualquer método que tenha a anotação @Test, @Before, @After ou @Factory.

Anotação de parâmetros com Testng.xml

Selecione a parametrização usando anotações quando quiser lidar com a complexidade e o número de combinações de entrada for menor.

Vamos ver como isso funciona

Cenário de Teste

Etapa 1) Inicie o navegador e acesse Google.com

Etapa 2) Insira uma palavra-chave de pesquisa

Anotação de parâmetros com Testng.Xml

Etapa 3) Verifique se o valor inserido é o mesmo fornecido pelos nossos dados de teste

Etapa 4) Repita 2 e 3 até que todos os valores sejam inseridos

Autor do teste Chave de pesquisa
Guru99 Índia
Krishna ESTADOS UNIDOS
Bhupesh China

Aqui está um exemplo de como fazer isso SEM parâmetros

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 = "guru99";
        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));
}
}

Um estudo, o exemplo acima. Imagine quão complexo o código se tornará quando fizermos isso para 3 combinações de entrada

Agora, vamos parametrizar isso usando TestNG

Para fazer isso, você precisará

  • Crie um arquivo XML que armazenará os parâmetros
  • No teste, adicione a anotação @Parameters

Anotação de parâmetros com Testng.Xml

Aqui está o código completo

Nível de teste 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="Guru99" />
<parameter name="searchKey" value="India" />
<test name="testGuru">
<parameter name="searchKey" value="UK" />
<classes>
<class name="parameters.ParameterWithTestNGXML">
</class>
</classes>
</test>
</suite>

ParâmetroComTestNGArquivo XML.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));

}
}

Instruções para executar o script, selecionar o arquivo XML e executar como Test NG Suite

Clique com o botão direito no arquivo .xml -> Executar como -> Teste Suíte (Nota: Suíte)

ParâmetroComTestNGArquivo XML.java

Agora, os parâmetros podem ser definidos em 2 níveis

  1. Nível Suite – Os parâmetros dentro do etiqueta de TestNG O arquivo XML será um parâmetro de nível de suíte.
  2. Nível de teste — Os parâmetros dentro do tag do arquivo XML de teste será um parâmetro de nível de teste.

Aqui está o mesmo teste com parâmetros de nível de suíte

ParâmetroComTestNGArquivo XML.java

OBSERVAÇÃO: Caso o nome do parâmetro seja o mesmo no nível do conjunto e no nível de teste, o parâmetro do nível de teste terá preferência sobre o nível do conjunto. Portanto, nesse caso, todas as classes dentro desse nível de teste compartilharão o parâmetro substituído, e outras classes que estão fora do nível de teste compartilharão o parâmetro de nível de suíte.

ParâmetroComTestNGArquivo XML.java

guia de solução de problemas

Edição nº 1 O valor do parâmetro em testng.xml não pode ser convertido para o parâmetro do método de teste correspondente, pois gerará um erro.

Considere o seguinte exemplo

Solução de problemas

Aqui, o atributo 'autor' é igual a 'Guru99' que é uma string e no método de teste correspondente espera um valor inteiro, então obteremos uma exceção aqui.

Edição nº 2 Seus @Parameters não possuem um valor correspondente em testing.xml.

Você pode resolver esta situação adicionando @opcional anotação no parâmetro correspondente no método de teste.

Solução de problemas

Edição nº 3: Você deseja testar vários valores do mesmo parâmetro usando Testng.xml

A resposta simples é que isso não pode ser feito! Você pode ter vários parâmetros diferentes, mas cada parâmetro só pode ter um único valor. Isso ajuda a evitar a codificação de valores no script. Isso torna o código reutilizável. Pense nisso como arquivos de configuração para o seu script. Se você quiser usar vários valores para um parâmetro, use DataProviders

Provedor de dados em TestNG

Provedor de dados em TestNG é um método usado quando um usuário precisa passar parâmetros complexos. Parâmetros complexos precisam ser criados a partir de Java como objetos complexos, objetos de arquivos de propriedade ou de um banco de dados podem ser passados ​​pelo método data provider. O método é anotado por @DataProvider e retorna um array de objetos.

Parâmetros usando Dataprovider

A anotação @Parameters é fácil, mas para testar com vários conjuntos de dados, precisamos usar o Data Provider.

Para preencher milhares de formulários web usando nossa estrutura de testes, precisamos de uma metodologia diferente que possa nos fornecer um conjunto de dados muito grande em um único fluxo de execução.

Este conceito baseado em dados é alcançado por @DataProvider anotação em TestNG.

Parâmetros usando Dataprovider

Tem apenas um Nome do Atributo'. Se você não especificar o atributo name, o nome do DataProvider será igual ao nome do método correspondente.

Devoluções do provedor de dados um objeto JAVA bidimensional ao método de teste e ao método de teste, invocará M vezes em um tipo M*N de matriz de objetos. Por exemplo, se o DataProvider retornar uma matriz de 2*3 objetos, o caso de teste correspondente será invocado 2 vezes com 3 parâmetros de cada vez.

Parâmetros usando Dataprovider

Exemplo Completo

Parâmetros usando Dataprovider

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[][] 
    	{
            { "Guru99", "India" },
            { "Krishna", "UK" },
            { "Bhupesh", "USA" }
        };

    }

}

Invoque DataProvider de classe diferente

Por padrão, DataProvider reside na mesma classe onde está o método de teste ou em sua classe base. Para colocá-lo em alguma outra classe, precisamos tornar o método do provedor de dados estático e no método de teste precisamos adicionar um atributo classeProvider de dados in @Teste anotação.

Invocar DataProvider de classe diferente

Exemplo de Código

Invocar DataProvider de classe diferente

TestClass ParâmetroDataproviderWithClassLevel.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[][] {
                { "Guru99", "India" },
                { "Krishna", "UK" },
                { "Bhupesh", "USA" }
            };  
}}

Tipos de parâmetros no Dataprovider

Existem dois tipos de parâmetros suportados pelo método DataProvider.

Forma- Se o MESMO DataProvider deve se comportar de maneira diferente com métodos de teste diferentes, use o parâmetro Method.

Tipos de parâmetros no provedor de dados

No exemplo a seguir,

  • Verificamos se o nome do método é testMethodA.
  • Se sim, retorne um conjunto de valores
  • Caso contrário, retorne outro conjunto de valores
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" }
            };}       
    }
}

Aqui está o resultado

Tipos de parâmetros no provedor de dados

ITestContext– Pode ser usado para criar diferentes parâmetros para casos de teste baseados em grupos.

Na vida real, você pode usar ITestContext para variar os valores dos parâmetros com base nos métodos de teste, hosts e configurações do teste.

Tipos de parâmetros no provedor de dados

No exemplo de código a seguir

  • Temos 2 grupos A e B
  • Cada método de teste é atribuído a um grupo
  • Se o valor do grupo for A, um conjunto de dados específico será retornado
  • Se o valor do grupo for B, outro conjunto de dados será retornado
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;		
	}
}

Nota: Se você executar diretamente sua classe testng, ela primeiro chamará o dataprovider que não pode obter informações de grupos porque os grupos não estão disponíveis. Mas em vez disso, se você chamar essa classe via testng.xml, ela terá informações de grupos disponíveis com ITestContext. Use o seguinte XML para chamar o teste

<!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>

Resumo

  • Parametrização é necessário criar Teste baseado em dados.
  • TestNG suporta dois tipos de parametrização, usando @Parâmetro+TestNG.xml e usando@DataProvider
  • In @Parâmetro+TestNG.xml os parâmetros podem ser colocados no nível de suíte e no nível de teste. Se

    O mesmo nome de parâmetro é declarado em ambos os locais; O parâmetro de nível de teste terá preferência sobre o parâmetro de nível de terno.

  • usando @Parâmetro+TestNG.xml apenas um valor pode ser definido por vez, mas @DataProvider retorna uma matriz 2D de objeto.
  • Se DataProvider estiver presente em uma classe diferente, então a classe onde reside o método de teste,DataProvider deveria estar método estático.
  • Existem dois parâmetros suportados por DataProvider e guarante que os mesmos estão Forma e ITestContext.