Salta el contingut
 

Exemple: Proves unitàries parametritzades

Joan Puigcerver Ibáñez

j.puigcerveribanez@edu.gva.es

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Proves unitàries parametritzades

En aquest exemple veurem com podem fer ús de les proves parametritzades per tal de simplificar el codi i evitar repetir codi innecessàriament.

Proves parametritzades de mètodes estàtics

A l' Exemple: Proves unitàries de pedra, paper i tisores hem vist com fer proves unitàries per al joc de pedra, paper i tisores, on s'han creat una sèrie de proves per comprovar que el joc funciona correctament per a tots els casos possibles.

Podeu observar que l'estructura de les proves és pràcticament la mateixa per a totes les proves, canviant únicament els valors de les variables.

RockPaperScissorsTest.java
package ud4.methods;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class RockPaperScissorsTest {
    @Nested
    class Empats {
        @Test
        @DisplayName("Tisores VS Tisores")
        void tisoresVsTisores_shouldReturn0(){
            // Arrange
            String j1 = "tisores";
            String j2 = "tisores";
            int expected = 0;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Pedra VS Pedra")
        void pedraVsPedra_shouldReturn0(){
            // Arrange
            String j1 = "pedra";
            String j2 = "pedra";
            int expected = 0;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Paper VS Paper")
        void paperVsPaper_shouldReturn0(){
            // Arrange
            String j1 = "paper";
            String j2 = "paper";
            int expected = 0;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }
    }

    @Nested
    class Jugador1 {
        @Test
        @DisplayName("Pedra VS Tisores")
        void pedraVsTisores_shouldReturn1(){
            // Arrange
            String j1 = "pedra";
            String j2 = "tisores";
            int expected = 1;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Paper VS Pedra")
        void paperVsPedra_shouldReturn1(){
            // Arrange
            String j1 = "paper";
            String j2 = "pedra";
            int expected = 1;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Tisores VS Paper")
        void tisoresVsPaper_shouldReturn1(){
            // Arrange
            String j1 = "tisores";
            String j2 = "paper";
            int expected = 1;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }
    }

    @Nested
    class Jugador2 {
        @Test
        @DisplayName("Pedra VS Paper")
        void pedraVsPaper_shouldReturn2(){
            // Arrange
            String j1 = "pedra";
            String j2 = "paper";
            int expected = 2;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Paper VS Tisores")
        void paperVsTisores_shouldReturn2(){
            // Arrange
            String j1 = "paper";
            String j2 = "tisores";
            int expected = 2;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Tisores VS Pedra")
        void tisoresVsPedra_shouldReturn2(){
            // Arrange
            String j1 = "tisores";
            String j2 = "pedra";
            int expected = 2;

            // Act
            int actual = RockPaperScissors.guanya(j1, j2);

            // Assert
            assertEquals(expected, actual);
        }
    }
}

Vegem com podem simplificar la codificació de les proves unitàries amb proves parametritzades.

RockPaperScissorsParametizedTest.java
package ud4.methods;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

class DebugRockPaperScissorsParametizedTest {
    @ParameterizedTest(name="\"{0}\" vs \"{1}\" should be {2}")
    @DisplayName("RockPaperScissors::guanya(j1, j2)")
    @CsvSource({
            "pedra,pedra,0",
            "pedra,paper,2",
            "pedra,tisores,1",
            "paper,pedra,1",
            "paper,paper,0",
            "paper,tisores,2",
            "tisores,pedra,2",
            "tisores,paper,1",
            "tisores,tisores,0",
    })
    void testGuanya(String j1, String j2, int expected) {
        int actual = DebugRockPaperScissors.guanya(j1, j2);

        assertEquals(expected, actual);
    }
}

Proves parametritzades d'objectes

A l' Exemple: Proves unitàries d'un cotxe hem vist com fer proves unitàries per a la classe Car, on s'han creat una sèrie de proves per comprovar que la classe funciona correctament en diferents escenaris.

CarTest.java
package ud4.objects;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CarTest {
    public static final String PLATE = "0000 BBB";

    @Nested
    @DisplayName("Constructor tests")
    class Constructor {
        @Test
        @DisplayName("Crea un cotxe amb matrícula")
        void testPlate() {
            Car car = new Car(PLATE);

            assertAll(
                () -> assertEquals(PLATE, car.getPlate()),
                () -> assertEquals(0, car.getKilometers())
            );
        }

        @Test
        @DisplayName("Crea un cotxe amb matrícula i quilòmetres")
        void testPlateAndKilometers() {
            Car car = new Car(PLATE, 100);

            assertAll(
                () -> assertEquals(PLATE, car.getPlate()),
                () -> assertEquals(100, car.getKilometers())
            );
        }
    }

    @Nested
    @DisplayName("Car::accelerate(int speed) tests")
    class AccelerateWithSpeed {
        private Car car;

        @BeforeEach
        void setup() {
            car = new Car(PLATE);
        }

        @Test
        @DisplayName("Car::accelerate(1) increments speed by 1")
        void singleAccelerate() {
            int expected = 1;

            car.accelerate(1);
            int actual = car.getSpeed();

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Car::accelerate(5) increments speed by 5")
        void multipleAccelerate() {
            int expected = 5;

            car.accelerate(5);
            int actual = car.getSpeed();

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Car::accelerate() multiples times increments speed")
        void multipleAccelerateCalls() {
            int expected = 3;

            car.accelerate(1);
            car.accelerate(2);
            int actual = car.getSpeed();

            assertEquals(expected, actual);
        }
    }

    @Nested
    @DisplayName("Car::accelerate() tests")
    class AccelerateWithoutSpeed {
        private Car car;

        @BeforeEach
        void setup() {
            car = new Car(PLATE);
        }

        @Test
        @DisplayName("Car::accelerate() increments speed by 5")
        void accelerate() {
            int expected = 5;

            car.accelerate();
            int actual = car.getSpeed();

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("Car::accelerate() multiples times increments speed")
        void multipleAccelerateCalls() {
            int expected = 15;

            car.accelerate();
            car.accelerate();
            car.accelerate();
            int actual = car.getSpeed();

            assertEquals(expected, actual);
        }
    }
}

En aquest cas, podríem parametritzar les proves del mètode Car::accelerate().

@DisplayName("Car::accelerate()")
@ParameterizedTest(name = "{0}x accelerate() should result in speed {1}")
@CsvSource({
    "0, 0",
    "1, 5",
    "3, 15",
})
void accelerateTest(int times, int expectedSpeed) {
    Car car = new Car("1234ABC");

    for (int i = 0; i < times; i++) {
        car.accelerate();
    }

    assertEquals(expectedSpeed, car.getSpeed());
}
📌 Aquest document pot quedar desactualitzat després d’imprimir-lo. Pots consultar la versió més recent a la pàgina web.
🌿 Abans d’imprimir aquest document, considera si és realment necessari. Redueix el consum de paper i ajuda a protegir el nostre entorn.