Introdução ao TestNG

Introdução ao TestNG

*1. Visão geral *

Neste artigo, apresentaremos a estrutura de teste TestNG.

Vamos nos concentrar em: configuração da estrutura, elaboração de caso e configuração simples de teste, execução de teste, geração de relatórios de teste e execução de teste simultânea.

===* 2. Configuração *

Vamos começar adicionando a dependência do Maven em nosso arquivo pom.xml:

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.11</version>
    <scope>test</scope>
</dependency>

A versão mais recente pode ser encontrada no Maven repository .

Ao usar o Eclipse, o plug-in TestNG pode ser baixado e instalado no Eclipse Marketplace.

===* 3. Escrevendo um caso de teste *

Para escrever um teste usando TestNG, basta fazer anotações no método de teste com a anotação org.testng.annotations.Test:

@Test
public void givenNumber_whenEven_thenTrue() {
    assertTrue(number % 2 == 0);
}

===* 4. Configurações de teste *

Ao escrever casos de teste, geralmente precisamos executar algumas instruções de configuração ou inicialização antes das execuções de teste e também alguma limpeza após a conclusão dos testes. O TestNG fornece vários recursos de inicialização e limpeza nos níveis de método, classe, grupo e suíte:

@BeforeClass
public void setup() {
    number = 12;
}

@AfterClass
public void tearDown() {
    number = 0;
}

O método setup () _ anotado com as anotações _ @ BeforeClass será invocado antes da execução de qualquer método dessa classe de teste e _tearDown () _ após a execução de todos os métodos da classe de teste.

Da mesma forma, podemos usar as anotações _ @ BeforeMethod, @AfterMethod, @ Before/AfterGroup, @ Before/AfterTest_ e _ @ Before/AfterSuite_ para qualquer configuração nos níveis de método, grupo, teste e suíte.

===* 5. Execução de teste *

Podemos executar os casos de teste com o comando “test” do Maven, ele executará todos os casos de teste anotados com _ @ Test_ colocando-os em um conjunto de testes padrão. Também podemos executar casos de teste a partir dos arquivos XML do conjunto de testes TestNG, usando os _https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.maven.plugins%22% 20AND% 20a% 3A% 22maven-surefire-plugin% 22 [maven-surefire-plugin]: _

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <suiteXmlFiles>
            <suiteXmlFile>
               src\test\resources\test_suite.xml
            </suiteXmlFile>
        </suiteXmlFiles>
    </configuration>
</plugin>

Observe que, se tivermos vários arquivos XML, cobrindo todos os casos de teste, podemos adicionar todos eles na tag suiteXmlFiles:

<suiteXmlFiles>
    <suiteXmlFile>
      src/test/resources/parametrized_test.xml
    </suiteXmlFile>
    <suiteXmlFile>
      src/test/resources/registration_test.xml
    </suiteXmlFile>
</suiteXmlFiles>

Para executar o teste autônomo, precisamos ter a biblioteca TestNG no caminho de classe e a classe de teste compilada junto com o arquivo de configuração XML:

java org.testng.TestNG test_suite.xml

===* 6. Testes de agrupamento *

Os testes podem ser executados em grupos; por exemplo, dos 50 casos de teste, 15 podem ser agrupados e executados, deixando os outros como estão.

No TestNG, os testes de agrupamento nos conjuntos são feitos usando o arquivo XML:

<suite name="suite">
    <test name="test suite">
        <classes>
            <class name="com..RegistrationTest"/>
            <class name="com..SignInTest"/>
        </classes>
    </test>
</suite>

Observe que agora as duas classes de teste RegistrationTest, SignInTest pertencem ao mesmo conjunto e, uma vez executado, os casos de teste nessa classe serão executados.

Além dos conjuntos de testes, também podemos criar grupos de testes no TestNG, onde os métodos das classes de teste são agrupados. Para fazer isso, adicione o parâmetro groups na anotação _ @ Test_:

@Test(groups = "regression")
public void givenNegativeNumber_sumLessthanZero_thenCorrect() {
    int sum = numbers.stream().reduce(0, Integer::sum);

    assertTrue(sum < 0);
}

Vamos usar um XML para executar os grupos:

<test name="test groups">
    <groups>
        <run>
            <include name="regression"/>
        </run>
    </groups>
    <classes>
        <class
          name="com..SummationServiceTest"/>
    </classes>
</test>

Isso executará o método de teste marcado com o grupo regression, _ na classe _SummationServiceTest.

===* 7. Testes parametrizados *

Testes de unidade parametrizados são usados ​​para testar o mesmo código sob várias condições. Com a ajuda de testes de unidade parametrizados, podemos configurar um método de teste que obtém dados de alguma fonte de dados. A idéia principal é tornar o método de teste de unidade reutilizável e testar com um conjunto diferente de entradas.

No TestNG, podemos parametrizar testes usando a anotação @Parameter ou _ @ DataProvider_. Enquanto estiver usando o arquivo XML, anote o método de teste com @_Parameter: _

@Test
@Parameters({"value", "isEven"})
public void
  givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) {

    assertEquals(isEven, value % 2 == 0);
}

E forneça os dados usando o arquivo XML:

<suite name="My test suite">
    <test name="numbersXML">
        <parameter name="value" value="1"/>
        <parameter name="isEven" value="false"/>
        <classes>
            <class name=".com.ParametrizedTests"/>
        </classes>
    </test>
</suite>

O uso de dados do arquivo XML é útil, mas geralmente precisamos de dados mais complexos. A anotação _ @ DataProvider_ é usada para lidar com esses cenários, que podem ser usados ​​para mapear tipos de parâmetros complexos para métodos de teste.@DataProvider para tipos de dados primitivos:

@DataProvider(name = "numbers")
public static Object[][] evenNumbers() {
    return new Object[][]{{1, false}, {2, true}, {4, true}};
}

@Test(dataProvider = "numbers")
public void
  givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect(Integer number, boolean expected) {
    assertEquals(expected, number % 2 == 0);
}

@ DataProviderpara objetos:

@Test(dataProvider = "numbersObject")
public void
  givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect(EvenNumber number) {
    assertEquals(number.isEven(), number.getValue() % 2 == 0);
}

@DataProvider(name = "numbersObject")
public Object[][] parameterProvider() {
    return new Object[][]{{new EvenNumber(1, false)},
      {new EvenNumber(2, true)}, {new EvenNumber(4, true)}};
}

Usando isso, qualquer objeto que precise ser testado pode ser criado e usado no teste. Isso é útil principalmente para casos de teste de integração.

===* 8. Ignorando casos de teste *

Às vezes, queremos não executar um determinado caso de teste, temporariamente durante o processo de desenvolvimento. Isso pode ser feito adicionando enabled = false, _ na anotação @_Test:

@Test(enabled=false)
public void givenNumbers_sumEquals_thenCorrect() {
    int sum = numbers.stream.reduce(0, Integer::sum);
    assertEquals(6, sum);
}

===* 9. Testes dependentes *

Vamos considerar um cenário em que, se o caso de teste inicial falhar, todos os casos de teste subsequentes deverão ser executados e, em vez disso, marcados como ignorados. O TestNG fornece esse recurso com o parâmetro dependsOnMethods da anotação _ @ Test_:

@Test
public void givenEmail_ifValid_thenTrue() {
    boolean valid = email.contains("@");

    assertEquals(valid, true);
}

@Test(dependsOnMethods = {"givenEmail_ifValid_thenTrue"})
public void givenValidEmail_whenLoggedIn_thenTrue() {
    LOGGER.info("Email {} valid >> logging in", email);
}

Observe que, o caso de teste de login depende do caso de teste de validação de email. Portanto, se a validação do email falhar, o teste de login será ignorado.

===* 10. Execução de teste simultânea *

O TestNG permite que os testes sejam executados em paralelo ou no modo multithread, fornecendo assim uma maneira de testar esses trechos de código multithread.

Você pode configurar métodos, classes e suítes para execução em seus próprios encadeamentos, reduzindo o tempo total de execução.

====* 10.1 Classes e métodos em paralelo *

Para executar classes de teste em paralelo, mencione o atributo parallel na tag suite no arquivo de configuração XML, com o valor _classes: _

<suite name="suite" parallel="classes" thread-count="2">
    <test name="test suite">
        <classes>
        <class name=".com.RegistrationTest"/>
            <class name=".com.SignInTest"/>
        </classes>
    </test>
</suite>

Observe que, se tivermos várias tags test no arquivo XML, esses testes também poderão ser executados em paralelo, mencionando parallel = ”tests" . Também para executar métodos individuais em paralelo, mencione parallel = "methods" .

====* 10.2 Execução multithread do método de teste *

Digamos que precisamos testar o comportamento de um código ao executar em vários threads. TestNG permite executar um método de teste em vários threads:

public class MultiThreadedTests {

    @Test(threadPoolSize = 5, invocationCount = 10, timeOut = 1000)
    public void givenMethod_whenRunInThreads_thenCorrect() {
        int count = Thread.activeCount();

        assertTrue(count > 1);
    }
}

O threadPoolSize indica que o método será executado em n número de threads, conforme mencionado. InvocationCount e timeOut indicam que o teste será executado várias vezes e falhará no teste, se demorar mais tempo.

11. Teste funcional

O TestNG vem com recursos que também podem ser usados ​​para testes funcionais. Em conjunto com o Selenium, ele pode ser usado para testar as funcionalidades de um aplicativo Web ou para testar serviços da Web em HttpClient.

Mais detalhes sobre testes funcionais com Selenium e TestNG estão disponíveis no link:/java-selenium-with-junit-and-testng [aqui]. Também mais algumas coisas sobre testes de integração neste link:/integration-testing-a-rest-api [artigo].

12. Conclusão

Neste artigo, vimos rapidamente como configurar o TestNG e executar um caso de teste simples, gerar relatórios, execução simultânea de casos de teste e também um pouco sobre programação funcional. Para obter mais recursos, como testes dependentes, ignorando casos de teste, grupos e conjuntos de testes, consulte o link do artigo JUnit vs TestNG:/junit-vs-testng [aqui].

A implementação de todos os trechos de código pode ser encontrada em over no Github.