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á.