Salta el contingut
 

Exemple: Proves unitàries d'un cotxe

Autor: Joan Puigcerver Ibáñez

Correu electrònic: j.puigcerveribanez@edu.gva.es

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Proves unitàries d'un cotxe

Objectius

Mostrar com realitzar proves unitàries d'objectes a Java.

Implementació de la classe Car

ud4.examples.objects

S'ha realitzat una implementació de la classe Car, que representa un cotxe i la seua velocitat.

classDiagram
    class Car {
        - «get» plate: String
        - «get» speed: int
        - «get» kilometers: double
        + Car(plate: String)
        + Car(plate: String, kilometers: double)
        + accelerate(): void
        + accelerate(speed: int): void
        + drive(): void
        + drive(int seconds): void
    }
Constructors
  • Car(String plate): Crea un cotxe amb la matrícula especificada. Els quilòmetres recorreguts s'inicialitzen a 0.
  • Car(String plate, double kilometers): Crea un cotxe amb la matrícula i els quilòmetres recorreguts especificats.
Mètodes
  • accelerate(): Incrementa la velocitat del cotxe en 5 km/h.
  • accelerate(int speed): Incrementa la velocitat del cotxe en la quantitat especificada.
  • drive(): Incrementa els quilòmetres recorreguts pel cotxe durant 1 segon, segons a la seua velocitat actual.
  • drive(int seconds): Incrementa els quilòmetres recorreguts pel cotxe durant la quantitat de segons especificada, segons a la seua velocitat actual.
Car.java
package ud4.examples.objects;

/**
 * Classe que representa un cotxe.
 * @author Joan Puigcerver
 * @version 1.2 2024-01-05
 */
public class Car {
    /**
     * Matrícula del cotxe
     */
    private final String plate;
    /**
     * Velocitat del cotxe en km/h
     */
    private int speed;
    /**
     * Distància total recorreguda pel cotxe en km
     */
    private double kilometers;

    /**
     * Crea un cotxe a partir de la matrícula i els
     * kilòmetres totals recorreguts. La velocitat inicial és 0 km/h.
     * @param plate Matrícula del cotxe
     * @param kilometers Kilòmetres recorreguts
     */
    public Car(String plate, int kilometers){
        this.plate = plate;
        this.kilometers = kilometers;
        this.speed = 0;
    }

    /**
     * Crea un cotxe a partir de la matrícula
     * Els kilòmetres totals recorreguts inicials és 0 i la velocitat inicial és 0 km/h.
     * @param plate Matrícula del cotxe
     */
    public Car(String plate){
        this(plate, 0);
    }

    /**
     * Obté la matrícula del cotxe
     * @return Matrícula del cotxe
     */
    public String getPlate() {
        return plate;
    }

    /**
     * Obté la velocitat actual del cotxe
     * @return Velocitat del cotxe
     */
    public int getVelocity() {
        return speed;
    }

    /**
     * Obté els kilòmetres totals recorreguts pel cotxe
     * @return Kilòmetres recorreguts
     */
    public double getKilometers() {
        return kilometers;
    }

    /**
     * Accelera el cotxe en la velocitat especificada
     * @param speed Velocitat que accelerarà el cotxe
     */
    public void accelerate(int speed){
        this.speed += speed;
    }

    /**
     * Accelera el cotxe en 5 km/h
     */
    public void accelerate(){
        accelerate(5);
    }

    /**
     * Condueix el cotxe durant els segons especificats.
     * Aquest mètode actualitza els kilòmetres recorreguts tenint en compte
     * la velocitat actual.
     */
    public void drive(int seconds){
        this.kilometers += (double) speed * seconds / 3600.0;
    }

    /**
     * Condueix el cotxe durant un minut.
     * Aquest mètode actualitza els kilòmetres recorreguts tenint en compte
     * la velocitat actual.
     * @see Car#drive()
     */
    public void drive(){
        drive(1);
    }

    /**
     * Retorna una representació de l'objecte en format String
     * @return Representació del cotxe
     */
    @Override
    public String toString() {
        return String.format("Car %s: {speed=%d km/h, kilometers=%.2f km", plate, speed, kilometers);
    }
}

Proves unitàries

S'han realitzat proves unitàries de la classe Car a la classe CarTest, on s'han seguit els següents criteris:

  • S'han agrupat les proves relacionades amb cada mètode o constructor utilitzant classes internes @Nested.

  • S'ha inicialitzat un objecte diferent per a cada prova perquè cada prova siga independent de les altres.

    Per simplificar aquesta inicialització, s'ha creat un mètode setup() que s'executa abans de cada prova amb l'anotació @BeforeEach.

CarTest.java
package ud4.examples.objects;

import org.junit.jupiter.api.*;

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

class CarTest {

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

            assertEquals("0000 BBB", car.getPlate());
            assertEquals(0, car.getKilometers());
        }

        @Test
        @DisplayName("Crea un cotxe amb matrícula i quilòmetres")
        void testPlateAndKilometers() {
            Car car = new Car("0000 BBB", 100);
            assertEquals("0000 BBB", car.getPlate());
            assertEquals(100, car.getKilometers());
        }
    }

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

        @BeforeEach
        void setup() {
            car = new Car("0000 BBB");
        }

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

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

            assertEquals(expected, actual);
        }

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

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

            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.getVelocity();

            assertEquals(expected, actual);
        }
    }

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

        @BeforeEach
        void setup() {
            car = new Car("0000 BBB");
        }

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

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

            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.getVelocity();

            assertEquals(expected, actual);
        }
    }
}

Ampliació

  • Implementa les proves dels mètodes drive() i drive(int seconds) a la classe CarTest.
  • Implementa i prova els mètodes decelerate() i decelerate(int speed) a la classe Car