Execução de teste condicional do JUnit 5 com anotações

Execução de teste condicional do JUnit 5 com anotações

1. Visão geral

Neste tutorial, vamos dar uma olhada emconditional test execution with annotations in JUnit 5.

Essas anotações são do pacoteJUnit Jupiter library’scondition e nos permitem especificar diferentes tipos de condições sob as quais nossos testes devem ou não ser executados.

2. Condições do sistema operacional

Às vezes, precisamos mudar nossos cenários de teste dependendo dos sistemas operacionais (SO) em que estão sendo executados. Nesses casos, a anotação@EnabledOnOs é útil.

O uso de@EnabledOnOs é simples - só precisamos fornecer um valor para o tipo de sistema operacional. Além disso, ele também aceita um argumento de matriz para quando queremos direcionar vários sistemas operacionais.

Por exemplo, digamos que queremos permitir que um teste seja executado apenas no Windows e MacOS:

@Test
@EnabledOnOs({OS.WINDOWS, OS.MAC})
public void shouldRunBothWindowsAndMac() {
    //...
}

Agora, em contraste com@EnabledOnOs, existe@DisabledOnOs. Como o nome indica, ele desativa os testes de acordo com o argumento de tipo do SO:

@Test
@DisabledOnOs(OS.LINUX)
public void shouldNotRunAtLinux() {
    //...
}

3. Condições do Java Runtime Environment

Também podemos direcionar nossos testes para execução em versões específicas deJRE usando as anotações@EnableOnJree@DisableOnJre. Essas anotações também aceitam uma matriz para ativar ou desativar várias versões do Java:

@Test
@EnabledOnJre({JRE.JAVA_10, JRE.JAVA_11})
public void shouldOnlyRunOnJava10And11() {
    //...
}

Além disso, se quisermos desabilitar nossos testes em execução com versões Java diferentes de 8, 9, 10 e 11, podemos usar a propriedadeJRE.OTHERenum:

@Test
@DisabledOnJre(JRE.OTHER)
public void thisTestOnlyRunsWithUpToDateJREs() {
    // this test will only run on Java 8, 9, 10, and 11.
}

4. Condições de propriedade do sistema

Agora, se quisermos habilitar nossos testes com base nas propriedades do sistema JVM, podemos usar a anotação @EnabledIfSystemProperty.

Para usá-lo, devemos fornecer os argumentosnamedematches. O argumentonamed é usado para especificar uma propriedade de sistema exata. Omatches é usado para definir o padrão do valor da propriedade com uma expressão regular.

Por exemplo, digamos que queremos permitir que um teste seja executado apenas quando o nome do fornecedor da máquina virtual começar com "Oracle":

@Test
@EnabledIfSystemProperty(named = "java.vm.vendor", matches = "Oracle.*")
public void onlyIfVendorNameStartsWithOracle() {
    //...
}

Da mesma forma, temos o@DisabledIfSystemProperty para desativar os testes com base nas propriedades do sistema JVM. Para demonstrar essa anotação, vamos dar uma olhada em um exemplo:

@Test
@DisabledIfSystemProperty(named = "file.separator", matches = "[/]")
public void disabledIfFileSeperatorIsSlash() {
    //...
}

5. Condições variáveis ​​de ambiente

Também podemos especificar condições de variáveis ​​de ambiente para nossos testes com anotações@EnabledIfEnvironmentVariablee@DisabledIfEnvironmentVariable.

E, assim como as anotações parasystem property conditions, essas anotações levam dois argumentos -namedematches — para especificar o nome da variável de ambiente e a expressão regular para corresponder aos valores da variável de ambiente:

@Test
@EnabledIfEnvironmentVariable(named = "GDMSESSION", matches = "ubuntu")
public void onlyRunOnUbuntuServer() {
    //...
}

@Test
@DisabledIfEnvironmentVariable(named = "LC_TIME", matches = ".*UTF-8.")
public void shouldNotRunWhenTimeIsNotUTF8() {
    //...
}

Além disso, podemos consultar um de nossos outros tutoriais paralearn more about system properties and system environment variables.

6. Condições baseadas em script

Além disso, o JUnit 5 Jupiter nos dá a capacidade de decidir as condições de execução do nosso teste, escrevendo scripts nas anotações@EnabledIfe@DisabledIf.

Essas anotações aceitam três argumentos:

  • value - contém o script real a ser executado.

  • engine (opcional) - especifica o mecanismo de script a ser usado; o padrão éOracle Nashorn.

  • reason (opcional) - para fins de registro, especifica a mensagem que o JUnit deve imprimir se nosso teste falhar.

Então, vamos ver um exemplo simples onde especificamos apenas um script de uma linha, sem argumentos adicionais na anotação:

@Test
@EnabledIf("'FR' == systemProperty.get('user.country')")
public void onlyFrenchPeopleWillRunThisMethod() {
    //...
}

Além disso, o uso de@DisabledIf é exatamente o mesmo:

@Test
@DisabledIf("java.lang.System.getProperty('os.name').toLowerCase().contains('mac')")
public void shouldNotRunOnMacOS() {
    //...
}

Além disso,we can write multi-line scripts with the value argument.

Vamos escrever um breve exemplo para verificar o nome do mês antes de executar o teste.

Definiremos uma frase parareason com marcadores de posição suportados:

  • {annotation} - a string para representar a instância da anotação.

  • {script} - o texto do script que avaliou dentro do argumento do valor.

  • {result} - a string para representar o valor de retorno do script avaliado.

Para esta instância, teremos um script de várias linhas no argumentovalue e valores paraengineereason:

@Test
@EnabledIf(value = {
    "load('nashorn:mozilla_compat.js')",
    "importPackage(java.time)",
    "",
    "var thisMonth = LocalDate.now().getMonth().name()",
    "var february = Month.FEBRUARY.name()",
    "thisMonth.equals(february)"
},
    engine = "nashorn",
    reason = "On {annotation}, with script: {script}, result is: {result}")
public void onlyRunsInFebruary() {
    //...
}

We can use several script bindings ao escrever nossos scripts:

  • systemEnvironment - para acessar as variáveis ​​de ambiente do sistema.

  • systemProperty - para acessar variáveis ​​de propriedade do sistema.

  • junitConfigurationParameter - para acessar os parâmetros de configuração. __

  • junitDisplayName - teste ou nome de exibição do contêiner.

  • junitTags - para acessar tags no teste ou contêiner.

  • anotherUniqueId - para obter o id único do teste ou contêiner. __

Finalmente, vejamos outro exemplo para verhow to use scripts with bindings:

@Test
@DisabledIf("systemEnvironment.get('XPC_SERVICE_NAME') != null" +
        "&& systemEnvironment.get('XPC_SERVICE_NAME').contains('intellij')")
public void notValidForIntelliJ() {
    //this method will not run on intelliJ
}

Além disso, consulte um de nossos outros tutoriais paralearn more about @EnabledIf and @DisabledIf annotations.

7. Criando anotações condicionais personalizadas

Um recurso muito poderoso que acompanha o JUnit 5 é a capacidade de criar anotações personalizadas. We can define custom conditional annotations by using a combination of existing conditional annotations.

Por exemplo, suponha que desejamos definir todos os nossos testes para executar para tipos específicos de SO com versões específicas do JRE. Podemos escrever uma anotação personalizada para isso:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Test
@DisabledOnOs({OS.WINDOWS, OS.SOLARIS, OS.OTHER})
@EnabledOnJre({JRE.JAVA_9, JRE.JAVA_10, JRE.JAVA_11})
@interface ThisTestWillOnlyRunAtLinuxAndMacWithJava9Or10Or11 {
}

@ThisTestWillOnlyRunAtLinuxAndMacWithJava9Or10Or11
public void someSuperTestMethodHere() {
    // this method will run with Java9, 10, 11 and Linux or macOS.
}

Além disso, podemosuse script-based annotations to create a custom annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@DisabledIf("Math.random() >= 0.5")
@interface CoinToss {
}

@RepeatedTest(2)
@CoinToss
public void gamble() {
    // this method run run roughly 50% of the time
}

8. Conclusão

Neste tutorial, aprendemos sobre a execução condicional de testes com anotações no JUnit 5. Além disso, passamos por alguns exemplos de seus usos.

Em seguida, mostramos como criar anotações condicionais personalizadas.

Para saber mais sobre este tópico, podemos consultarJUnit’s own documentation about conditional test execution with annotations.

Como de costume, todo o código de exemplo pode ser encontrado em nossoGitHub project.