Executores de teste personalizados do JUnit 4

Executores de teste personalizados do JUnit 4

1. Visão geral

Neste artigo rápido, vamos nos concentrar em como executar testes JUnit usando executores de teste personalizados.

Simplificando, para especificar o runner personalizado, precisaremos usar a anotação@RunWith.

2. Preparação

Vamos começar adicionando a dependênciaJUnit padrão em nossopom.xml:


  junit
  junit
  4.12

3. Implementando um Custom Runner

No exemplo a seguir, mostraremos como escrever nosso próprioRunner personalizado - e executá-lo usando @RunWith.

A JUnit Runner is a class that extends JUnit’s abstract Runner class and it is responsible for running JUnit tests, normalmente usando reflexão.

Aqui, estamos implementando métodos abstratos da classeRunner:

public class TestRunner extends Runner {

    private Class testClass;
    public TestRunner(Class testClass) {
        super();
        this.testClass = testClass;
    }

    @Override
    public Description getDescription() {
        return Description
          .createTestDescription(testClass, "My runner description");
    }

    @Override
    public void run(RunNotifier notifier) {
        System.out.println("running the tests from MyRunner: " + testClass);
        try {
            Object testObject = testClass.newInstance();
            for (Method method : testClass.getMethods()) {
                if (method.isAnnotationPresent(Test.class)) {
                    notifier.fireTestStarted(Description
                      .createTestDescription(testClass, method.getName()));
                    method.invoke(testObject);
                    notifier.fireTestFinished(Description
                      .createTestDescription(testClass, method.getName()));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

O métodogetDescription é herdado deDescribablee retorna umDescription que contém as informações que estão sendo exportadas posteriormente e podem ser usadas por várias ferramentas.

Na implementação derun, estamos invocando os métodos de teste de destino usando reflexão.

Definimos um construtor que leva um argumentoClass; este é um requisito do JUnit. Em tempo de execução, o JUnit passará a classe de teste de destino para esse construtor.

RunNotifier é usado para disparar eventos que contêm informações sobre o andamento do teste.

Vamos usar o runner em nossa classe de teste:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

@RunWith(TestRunner.class)
public class CalculatorTest {
    Calculator calculator = new Calculator();

    @Test
    public void testAddition() {
        Syste.out.println("in testAddition");
        assertEquals("addition", 8, calculator.add(5, 3));
    }
}

O resultado que obtemos:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.example.junit.CalculatorTest
running the tests from MyRunner: class com.example.junit.CalculatorTest
in testAddition
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

4. Corredores especializados

Em vez de estender a classeRunner de baixo nível, como fizemos no último exemplo,we can extend one of the specialized subclasses of Runner: ParentRunner or BlockJUnit4Runner.

A classe abstractParentRunner executa os testes de maneira hierárquica.

BlockJUnit4Runner é uma classe concreta e se preferirmos customizar certos métodos, provavelmente iremos estender esta classe.

Vejamos isso com um exemplo:

public class BlockingTestRunner extends BlockJUnit4ClassRunner {
    public BlockingTestRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected Statement methodInvoker(FrameworkMethod method, Object test) {
        System.out.println("invoking: " + method.getName());
        return super.methodInvoker(method, test);
    }
}

Anotar uma classe com@RunWith(JUnit4.class) sempre invocará o executor JUnit 4 padrão na versão atual do JUnit; esta classe é o alias do executor de classe JUnit 4 padrão atual:

@RunWith(JUnit4.class)
public class CalculatorTest {
    Calculator calculator = new Calculator();

    @Test
    public void testAddition() {
        assertEquals("addition", 8, calculator.add(5, 3));
    }
}

5. Conclusão

Os JUnit Runners são altamente adaptáveis ​​e permitem que o desenvolvedor altere o procedimento de execução do teste e todo o processo de teste.

Se quisermos apenas fazer pequenas alterações, é uma boa ideia dar uma olhada nos métodos protegidos do runnerBlockJUnit4Class.

Algumas implementações populares de corredores de terceiros para uso incluemSpringJUnit4ClassRunner, MockitoJUnitRunner, HierarchicalContextRunner,Cucumber Runnere muito mais.

A implementação de todos esses exemplos e trechos de código pode ser encontrada emGitHub project - este é um projeto Maven, portanto, deve ser fácil de importar e executar como está.