Provedor de dados em TestNG: Selenium Exemplo de parametrização
⚡ Resumo Inteligente
Parametrização em Selenium Executa repetidamente um único método de teste em diferentes conjuntos de dados, transformando um script em cobertura orientada por dados. TestNG Oferece dois mecanismos para isso: a anotação @Parameters, com suporte do testng.xml, e a anotação @DataProvider, que retorna uma matriz de objetos bidimensional.

Ao criarmos software, sempre queremos que ele funcione corretamente com diferentes conjuntos de dados. Quando se trata de ensaio Para esse software, verificar um único conjunto de dados não é suficiente. Precisamos verificar se o sistema aceita todas as combinações que se espera que ele suporte. Para isso, precisamos parametrizar nossos scripts de teste. É aí que entra a parametrização.
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 tornar a parametrização mais clara, vamos analisar as opções de parametrização em uma das estruturas mais populares para Selenium WebDriver — TestNG.
Tem dois caminhos pelo qual podemos obter parametrização em TestNG:
- Com a ajuda do Anotação de parâmetros e TestNG XML arquivo.
- Com a ajuda do DataProvider anotação.
O diagrama acima resume a divisão: parâmetros do testng.xml podem ser declarados no nível da suíte ou do teste, enquanto um parâmetro de um DataProvider pode aceitar Method e ITestContext como argumento próprio. Vamos estudá-los em detalhe.
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, utilizando um arquivo .xml. Os usuários podem precisar passar os valores para os métodos de teste durante a execução. O método de anotação @Parameters pode ser usado em qualquer método que possua as anotações @Test, @Before, @After ou @Factory.
Anotação de parâmetros com Testng.xml
Selecione a parametrização usando anotações quando não quiser lidar com a complexidade e o número de combinações de entrada for pequeno.
Vamos ver como isso funciona.
Cenário de Teste
Passo 1) Abra o navegador e acesse Google.com
Passo 2) Digite uma palavra-chave de pesquisa
Passo 3) Verifique se o valor inserido é o mesmo que o valor fornecido pelos nossos dados de teste.
Passo 4) Repita os passos 2 e 3 até que todos os valores sejam inseridos.
| Autor do teste | Chave de pesquisa |
|---|---|
| Guru99 | India |
| Krishna | USA |
| 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.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 Nota de 4: Três linhas na versão original deste exemplo não compilam mais ou estão obsoletas na versão atual. Selenium Lançamentos. System.setProperty("webdriver.gecko.driver", …) é desnecessário de Selenium 4.6 em diante porque Selenium O gerenciador resolve o binário do driver automaticamente. implicitlyWait(10, TimeUnit.SECONDS) A sobrecarga foi removida em Selenium 4 e substituído por implicitlyWait(Duration.ofSeconds(10)). getAttribute() foi descontinuado em Selenium 4.27, portanto, ler uma caixa de texto usa getDomProperty("value")Todos os exemplos abaixo aplicam as mesmas três correções.
Analise o exemplo acima e imagine a complexidade que o código adquire ao ser repetido para três combinações de entrada.
Agora vamos parametrizá-lo usando TestNGPara isso, você precisa:
- 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 "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>
ParâmetroComTestNGArquivo 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)); } }
Para executar o script, selecione o arquivo XML e execute-o como um comando. TestNG diante.
Clique com o botão direito do mouse no arquivo .xml -> Executar como -> TestNG Suíte (Nota: Suíte)
Os parâmetros podem ser definidos em dois níveis:
- Nível da suíte — os parâmetros dentro do
<suite>etiqueta do TestNG Os arquivos XML contêm parâmetros de nível de suíte. - Nível de teste — os parâmetros dentro do
<test>etiqueta do TestNG Os arquivos XML contêm parâmetros de nível de teste.
Aqui está o mesmo teste com parâmetros de nível de suíte:
OBSERVAÇÃO: Se o nome do parâmetro for o mesmo no nível da suíte e no nível do teste, o parâmetro do nível do teste terá preferência sobre o do nível da suíte. Nesse caso, todas as classes dentro desse nível de teste compartilharão o parâmetro sobrescrito, e as classes fora desse nível de teste continuarão a usar o parâmetro do nível da suíte.
guia de solução de problemas
Edição nº 1: Um valor de parâmetro no arquivo testng.xml que não pode ser convertido para o tipo do parâmetro do método de teste correspondente gera um erro.
Considere o seguinte exemplo:
Aqui, o atributo 'autor' é igual a 'Guru99', que é uma String, enquanto o método de teste correspondente espera um valor inteiro, então uma exceção é lançada.
Edição nº 2: Seus parâmetros @Parameters não possuem um valor correspondente em testng.xml.
Você pode resolver isso adicionando o @Anotação opcional ao parâmetro correspondente no método de teste.
Edição nº 3: Você deseja testar vários valores do mesmo parâmetro usando o arquivo testng.xml.
A resposta simples é que isso não é possível. Você pode ter vários parâmetros diferentes, mas cada parâmetro só pode armazenar um único valor. Isso impede a inserção de valores fixos no script e mantém o código reutilizável — pense nisso como um arquivo de configuração para o seu script. Se você precisar de vários valores para um parâmetro, use um DataProvider.
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 — Objetos complexos, objetos de arquivos de propriedades ou objetos de um banco de dados podem ser passados pelo método do provedor de dados. O método é anotado com @DataProvider e retorna uma matriz de objetos.
Parâmetros usando Dataprovider
A anotação @Parameters é fácil, mas para testar com vários conjuntos de dados precisamos usar um provedor de dados.
Para preencher milhares de formulários web usando nossa estrutura de testes, precisamos de uma metodologia diferente que possa fornecer um conjunto de dados muito grande em um único fluxo de execução.
Esse conceito orientado por dados é alcançado por meio de @DataProvider anotação em TestNG.
Tem apenas um atributo, 'nome'Se você não especificar o atributo `name`, o nome do `DataProvider` será o mesmo que o nome do método correspondente.
Um provedor de dados retorna uma bidimensional Java objeto para o método de teste, e o método de teste é invocado M vezes para uma matriz de objetos M×N. Por exemplo, se o DataProvider retornar uma matriz de objetos 2×3, o caso de teste correspondente será invocado 2 vezes com 3 parâmetros cada vez.
Exemplo Completo
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" } }; } }
Invoque DataProvider de classe diferente
Por padrão, um DataProvider reside na mesma classe que o método de teste ou em sua classe base. Para colocá-lo em outra classe, faça com que o método do provedor de dados seja definido como `DataProvider`. estático e adicione o atributo classeProvider de dados ao @Teste anotação.
Code Exemplo
TestClass ParâmetroDataproviderWithClassLevel.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" } }; } }
Tipos de parâmetros no Dataprovider
Existem dois tipos de parâmetros suportados pelo método DataProvider.
Forma — se o mesmo O DataProvider deve se comportar de maneira diferente para diferentes métodos de teste; utilize o parâmetro Method.
No exemplo a seguir:
- Verificamos se o nome do método é testMethodA.
- Em caso afirmativo, retorne um conjunto de valores.
- Caso contrário, retorne outro conjunto de valores.
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" } }; } } }
Aqui está o resultado:
ITestContext — isso pode ser usado para criar parâmetros diferentes para casos de teste com base em grupos.
Na prática, você pode usar o ITestContext para variar os valores dos parâmetros com base nos métodos de teste, hosts ou configurações de 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 será retornado.
- Se o valor do grupo for B, outro conjunto de dados será retornado.
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; } }
Observação: Se você executar o TestNG Ao chamar a classe diretamente, ela primeiro invoca o provedor de dados, e o provedor não consegue ler as informações do grupo porque os grupos ainda não estão disponíveis. Chamar a classe através do arquivo testng.xml torna as informações do grupo disponíveis por meio do ITestContext. Use o seguinte XML para executar o teste:
<!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>
Ambos os mecanismos já foram abordados, então a questão prática é qual deles utilizar.
@Parameters vs @DataProvider: Qual usar?
As duas abordagens não são intercambiáveis. A decisão depende de quantas combinações de valores um teste precisa e de onde esses valores se originam.
| Critério | @Parâmetros + testng.xml | @DataProvider |
|---|---|---|
| Valores por parâmetro | Exatamente um | Linhas ilimitadas |
| Fonte de dados | Texto estático no arquivo XML | Java código, Excel, CSV, banco de dados, API |
| Tipos suportados | Valores convertidos de String para String | Qualquer Java objeto |
| Invocações de teste | Uma vez por configuração | Uma vez por linha de dados |
| Alterar dados requer | Editando o arquivo XML | Editar o código-fonte geralmente não exige recompilação. |
| Melhor adequado para | Valores de ambiente e configuração, como navegador, URLcredenciais | Testes orientados por dados em diversas combinações de entrada. |
Na prática, a maioria dos conjuntos de dados usa ambos: `@Parameters` carrega as configurações de ambiente que permanecem constantes durante a execução, e `@DataProvider` fornece os dados de negócios variáveis. Quando o conjunto de dados ultrapassa a capacidade de um array fixo, o próximo passo é lê-lo de uma planilha.
Como ler dados de teste de um arquivo Excel usando o DataProvider
Arrays codificados param de escalar quando os testadores que não escrevem Java É necessário manter os dados. Mover as linhas para uma planilha separa os dados de teste da lógica de teste, o que é a forma prática de testes baseados em dadosO Apache POI lê a planilha e o DataProvider converte cada linha em uma invocação de teste.
- Adicione a dependência. Incluir
org.apache.poi:poi-ooxmlno seu Maven ou Gradle construir. OooxmlO artefato lida com o formato .xlsx; simplespoiLê apenas arquivos .xls antigos. - Crie a planilha. Coloque a linha de cabeçalho na linha 0 e um caso de teste por linha abaixo dela, com uma coluna para cada argumento do método de teste.
- Leia a planilha e armazene-a em uma matriz. Dimensiona o objeto Object[][] com base na contagem de linhas e células para que novas linhas sejam selecionadas sem alterações no código.
- Devolva-o ao fornecedor. A assinatura do método de teste permanece exatamente a mesma de antes.
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; } }
💡 Dica: Ligar getStringCellValue() Apenas em células formatadas como texto. Uma célula numérica gera um erro. IllegalStateException, que é a falha mais comum quando uma planilha contém IDs ou valores. Use um DataFormatter para ler cada tipo de célula como uma string ou ativar a opção cell.getCellType() e converter explicitamente.
Com os dados externalizados, adicionar mais cem casos de teste torna-se uma simples edição de planilha em vez de uma alteração de código, e o mesmo provedor pode alimentar diversas classes de teste através do sistema. dataProviderClass atributo mostrado anteriormente.
















