Provedor de dados e TestNG XML: Parametrização em Selenium(Exemplo)
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
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
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
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)
Agora, os parâmetros podem ser definidos em 2 níveis
- Nível Suite – Os parâmetros dentro do etiqueta de TestNG O arquivo XML será um parâmetro de nível de suíte.
- 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
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.
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
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.
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.
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.
Exemplo Completo
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.
Exemplo de Código
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.
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
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.
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.