Salta el contingut
 

Exemple: Proves unitàries de pedra, paper i tisores

Joan Puigcerver Ibáñez

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Proves unitàries

Les proves unitàries són una tècnica de verificació de programari que s'utilitza per assegurar que cada part (unitat) del programa funciona correctament. Aquesta tècnica es basa a dividir el programa en parts més xicotetes i escriure proves per a cadascuna.

Això és útil perquè, quan es fan canvis en un programa, és més fàcil determinar què ha fallat si es poden comprovar les parts individuals. A més, ajuda a detectar errors més ràpidament i a evitar introduir-ne de nous durant el manteniment del programa.

Java té diverses ferramentes per escriure i executar proves, com JUnit.

Creació de proves

ud4.methods

En aquest exemple es creen proves unitàries per comprovar que el programa DebugRockPaperScissors funciona correctament.

Per poder provar aquest codi, s'ha creat una nova versió del programa que incorpora el mètode int guanya(String jugador1, String jugador2), que determina qui ha guanyat la partida:

RockPaperScissorsError.java
package ud4.methods;

import java.util.Locale;
import java.util.Scanner;

public class RockPaperScissorsError {

    /**
     * Determina quin jugador ha guanyat la partida de pedra paper i tisores.
     * <p>
     * Aquest mètode retorna 0 si hi ha hagut un empat, 1 si el jugador1 ha guanyat la partida,
     * i 2 si el jugador2 ha guanyat.
     *
     * @param jugador1 Jugada del jugador1 (pedra, paper o tisores)
     * @param jugador2 Jugada del jugador1 (pedra, paper o tisores)
     * @return 0 si hi ha un empat; 1 si guanya jugador1; 2 si guanya jugador 2.
     */
    public static int guanya(String jugador1, String jugador2){
        if(jugador1.equals(jugador2))
            return 0;
        else if (jugador1.equals("paper")) {
            return jugador2.equals("pedra") ? 2 : 1;
        } else if (jugador1.equals("pedra")) {
            return jugador2.equals("paper") ? 1 : 2;
        } else {
            return jugador2.equals("paper") ? 1 : 2;
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in).useLocale(Locale.US);
        System.out.print("Introdueix l'elecció del jugador 2 (pedra/paper/tisores): ");
        String p1 = in.nextLine();
        System.out.print("Introdueix l'elecció del jugador 2 (pedra/paper/tisores): ");
        String p2 = in.nextLine();

        int guanyador = guanya(p1, p2);
        if (guanyador == 0)
            System.out.println("Empat");
        else
            System.out.printf("Guanya el jugador %d\n", guanyador);
    }
}

Per comprovar si el mètode està ben implementat, se segueixen aquests passos:

  1. Situa't sobre el nom de la classe RockPaperScissors, prem Alt+Ins i selecciona Test.

    També pots prémer Alt+Enter o fer clic amb el botó dret i seleccionar Show Context Actions. Des del menú, selecciona Create Test (Figura 1).

    Crear una prova des del menú contextual

    Figura 1. Crear una prova des del menú contextual.

  2. Selecciona en el diàleg els mètodes que vols provar i prem OK (Figura 2).

    Configuració de la prova

    Figura 2. Configuració de la prova.

  3. L'acció anterior crea un fitxer nou en src/test/java, la carpeta on es guarden les proves del projecte (Figura 3). El fitxer nou es troba en la mateixa estructura de paquets que el codi font: ud4.methods.

    Fitxer de prova creat

    Figura 3. Fitxer de prova creat.

  4. Dissenya les proves per comprovar si el mètode guanya() funciona correctament en tots els casos:

    Jugador 1 Jugador 2 Resultat
    Pedra Pedra Empat
    Pedra Paper Jugador 2 guanya
    Pedra Tisores Jugador 1 guanya
    Paper Pedra Jugador 1 guanya
    Paper Paper Empat
    Paper Tisores Jugador 2 guanya
    Tisores Pedra Jugador 2 guanya
    Tisores Paper Jugador 1 guanya
    Tisores Tisores Empat
  5. Modifica el fitxer de proves per incloure els casos anteriors. Les proves s'han organitzat en classes internes @Nested per millorar-ne l'organització.

    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);
            }
        }
    }
    

Execució de les proves

Una vegada implementades les proves, cal executar-les per comprovar si el mètode int guanya(String jugador1, String jugador2) funciona correctament. Per executar-les, fes clic en el botó Run (Figura 4).

Execució de les proves

Figura 4. Execució de les proves.

Una vegada executades, es poden consultar els resultats (Figura 5).

Resultats de les proves

Figura 5. Resultats de les proves.

S'observen els resultats de cada prova per separat. En aquest cas, algunes proves han fallat i, per tant, caldrà revisar els errors i corregir el codi.

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