Você conhece testes parametrizados?
É um comportamento comum refatorar o código principal da aplicação para deixar mais legível durante o desenvolvimento do software. Mas e códigos de testes você tem o mesmo cuidado?
Neste artigo, eu quero mostrar uma forma de escrever testes reduzindo o número de linhas e assim sendo mais produtivo fazendo o uso de testes parametrizados.
Os exemplos a seguir serão com Junit5. Para o funcionamento adequado é necessário a instalar a depêndencia junit-jupiter-params.
Criei um simples código onde o objetivo é apenas executar operações matemáticas com dois números.
public class Calculator {
   private int x;
   private int y;
   private String operation;
   public Calculator (int x, int y, String operation) {
       this.x = x;
       this.y = y;
       this.operation = operation;
   }
   public int calculate() {
       switch (this.operation) {
           case "add":
               return x + y;
           case "subtract":
               return x - y;
           case "multiply":
               return x * y;
           case "divide":
               return x / y;
           default:
               return 0;
       }
   }
}
O exemplo acima não tem mistério. Recebe x, y e de acordo com a operação o resultado será retornado. Se a operação é de desconhecida, o resutado será zero.
Testar o código sem testes parametrizados geraria pelo menos cinco métodos e um monte de linhas como estas:
public class CalculatorTest {
   @Test
   void mustTestAddition() {
       // given
       Calculator calculator = new Calculator(10, 2, "add");
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, 12;
   }
   @Test
   void mustTestSubtraction() {
       // given
       Calculator calculator = new Calculator(10, 2, "subtract");
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, 8);
   }
   @Test
   void mustTestMultiplication() {
       // given
       Calculator calculator = new Calculator(10, 2, "multiply");
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, 20);
   }
   @Test
   void mustTestDivision() {
       // given
       Calculator calculator = new Calculator(10, 2, "divide");
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, 5);
   }
   @Test
   void mustTestInvalidOperation() {
       // given
       Calculator calculator = new Calculator(10, 2, "any");
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, 0);
   }
}
Resumindo seria um teste para cada operação. Agora veja como fica quando usamos testes parametrizados.
public class CalculatorTest {
   
   @ParameterizedTest
   @CsvSource({
       "10,2,add,12",
       "10,2,subtract,8",
       "10,2,multiply,20",
       "10,2,divide,5",
       "10,2,any,0"
   })
   void mustTestCalculatorOperations(int x, int y, String operation, int expectedResult) {
       // given
       Calculator calculator = new Calculator(x, y, operation);
       // when
       int result = calculator.calculate();
       // then
       Assertions.assertEquals(result, expectedResult);
   }
}
É só adicionar a anotação @ParameterizedTest, definir os cenários dentro de @CsvSource seguindo a sequência de parâmetros que está declarada no método.


Apesar de ser um texto simples, eu acho que o objetivo foi cumprido. Mas os testes parametrizados tem várias formas de serem executados. Se você quiser se aprofundar mais, eu realmente recomendo o Guia de testes automatizados no Junit5.
Testes parametrizados
    
        Java
    
        Junit
    
    
Discussion and feedback