Exercice 1 : Présentation

Le but de ces exercices est de réaliser le test d'une application complète dont le but est de présenter les résultats des match de pro A

L'application permet de :

  • Récupérer les résultats et les statistiques des derniers matchs joués via le web service de la LNB
  • Calculer un certain nombre de statistiques sur les joueurs et les match
  • Afficher les statistiques des match dans une ihm développée en Swing

Les sources de l'application dont disponnibles sur gitlab :

git clone git@gitlab.com:julien-gauchet/tests-unitaires-exercices.git

Vous pouvez également les télécharger ici : Sources tests unitaires


Tests de la couche services

Un service fr.julien.formation.basket.services.CalculStatistiquesService permet de calculer :

  • Le nombre de points d'un joueur au cours d'un match
  • L'évaluation d'un joueur : points + rebonds + passes décisives + interceptions + contres + tirs réussis - tirs ratés - ballons perdus

Le but de l'exercice et de :

  1. Déterminer quelles méthodes et quelles classes doivent être testées pour le service et les classes métier utilisées
  2. Réaliser les tests et corriger les erreurs éventuelles détectées
  3. Se poser des questions sur la qualité du jeu de tests

Les classes à tester sont :

  • CalculStatistiquesService : de facon évidente
  • Joueur : pour la méthode equals()
  • Equipe : pour la méthode equals()
package fr.julien.formation.basket.services.statistiques;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class CalculStatistiqueServiceTest {
		@Test
		public void testerCalculScore() {
			Joueur kyle = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
			BilanJoueur bilan = new BilanJoueur(kyle, 1, 1, 7, 6, 7, 2, 3, 5, 2, 1, 1, 2);
			Assertions.assertEquals(19, CalculStatistiquesService.getInstance().calculerScore(bilan));
			Assertions.assertEquals(20, CalculStatistiquesService.getInstance().calculerEvaluation(bilan));
		}
}
package fr.julien.formation.basket.model;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class EquipeTest {
	
	@Test
	public void testerEquals() {
		Equipe e1 = new Equipe("Orléans");
		Equipe e2 = new Equipe("Orléans");
		Equipe e3 = new Equipe("ASVEL");
		Assertions.assertEquals(true, e1.equals(e2));
		Assertions.assertEquals(false, e1.equals(e3));
	}
}
package fr.julien.formation.basket.model;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class JoueurTest {

	@Test
	public void testerEquals() {
		Joueur kyle = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
		Joueur kyle2 = new Joueur("MCALARNEY", "Kyle", new Equipe("OLB"));
		Joueur kyle3 = new Joueur("MCALARNEY", "Kyle", new Equipe("Monaco"));
		Joueur kyle4 = new Joueur("MCALARNEY", "Autre", new Equipe("OLB"));
		Joueur cellus = new Joueur("SOMMERVILLE", "Marcellus", new Equipe("OLB"));
		Joueur cellus2 = new Joueur("SOMMERVILLE", "Kyle", new Equipe("OLB"));
		Assertions.assertEquals(true, kyle.equals(kyle2));
		Assertions.assertEquals(false, kyle.equals(kyle3));
		Assertions.assertEquals(false, kyle.equals(kyle4));
		Assertions.assertEquals(false, kyle.equals(cellus));
		Assertions.assertEquals(false, kyle.equals(cellus2));
	}
}

Le jeu de test est de qualité si :

  • La suppression d'un Assert a forcément un impact négatif sur la couverture du code : nous n'avons donc pas deux assert qui vérifient la même condition. Dans le cas contraire, nous avons un jeu de test trop lourd.
  • Les méthodes que nous avons ciblé sont globalement bien couvertes : en particulier les méthodes equals() dans lesquelles beaucoup de if s'enchainent : il faudrait couvrir au moins l'ensemble des cas non triviaux (un objet est null)
  • Aucune méthode get ou set n'a été testée, ni les constructeurs. Ces méthodes fonctionnent forcément. Une erreur classique est d'appeler un setter quelconque setValeur("valeur") et de faire un Assert.assertEquals("valeur", getValeur()) ce test ne peut pas échouer il n'apporte que de la complexité superfue

Test des daos

Le test de le couche DAO est plus complexe, il demande de faire appel à une base de données. Nous pouvons pour cela utiliser un schéma dédié de notre base, mais dans le cas présent, nous allons travailler sur une base h2

Le but de cet exercice est d'utiliser une base de données h2 pour tester les daos :

  • fr.julien.formation.basket.dao.BilansDao qui permet d'accéder à la table contenant les bilans des match
  • fr.julien.formation.basket.dao.MatchDao qui permet d'accéder à la table contenant les match
Diagramme de la base de données

Avec DBUnit

La création des fichiers suivants est nécéssaire

  • Un fichier src/test/resources/init_database_test.sql qui contient les instructions permettant de créer la base de données de test (script commun à tous les tests)
  • Un fichier src/test/resources/datasets/[NomTest].xml par classe de test qui contient les instructions permettant d'initialiser la base pour un test particulier
  • Un fichier src/test/resources/datasets/[NomTest]Resultat.xml par classe de test qui contient les tables que nous attendons en sortie
-- src/test/resources/init_database_test.sql
DROP TABLE IF EXISTS bilans CASCADE;
DROP TABLE IF EXISTS joueurs CASCADE;
DROP TABLE IF EXISTS equipes CASCADE;
DROP TABLE IF EXISTS matchs CASCADE;

CREATE TABLE matchs (
	id INT PRIMARY KEY
);

CREATE TABLE equipes (
	id INT PRIMARY KEY,
	nom VARCHAR
);

CREATE TABLE joueurs (
	id INT PRIMARY KEY,
	nom VARCHAR,
	prenom VARCHAR,
	id_equipe INT REFERENCES equipes(id)
);

CREATE TABLE bilans (
	id_match INT,
	id_joueur INT REFERENCES joueurs(id),
	lancer_francs INT,
	lancer_francs_reussis INT,
	deux_points INT,
	deux_points_reussis INT,
	trois_points INT,
	trois_points_reussis INT,
	rebonds INT,
	fautes INT,
	passes_decisives INT,
	ballons_perdus INT,
	interceptions INT,
	contres INT
);
<!-- BilansDaoTest.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<equipes id="1" nom="Orléans" />
	<equipes id="2" nom="Limoges" />
	
	<joueurs id="201" nom="CAMARA" prenom="Ousmane" id_equipe="2" />
	<joueurs id="202" nom="JONES" prenom="Joseph" id_equipe="2" />
	<joueurs id="203" nom="PREPELIC" prenom="Klemen" id_equipe="2" />
	<joueurs id="204" nom="WOJCIECHOWSKI" prenom="Mathieu" id_equipe="2" />
	<joueurs id="205" nom="WOOD" prenom="Dashaun" id_equipe="2" />
	<joueurs id="206" nom="DELAGE" prenom="Benjamin" id_equipe="2" />
	<joueurs id="207" nom="DUPORT" prenom="Romain" id_equipe="2" />
	<joueurs id="208" nom="FAIR" prenom="C.J" id_equipe="2" />
	<joueurs id="209" nom="MUNANGA" prenom="Shekinah" id_equipe="2" />
	<joueurs id="210" nom="RANDLE" prenom="Jerome" id_equipe="2" />
	<joueurs id="211" nom="ZERBO" prenom="Fréjus" id_equipe="2" />
	<joueurs id="101" nom="DOWNS" prenom="Micah" id_equipe="1" />
	<joueurs id="102" nom="LOUBAKI" prenom="Luc" id_equipe="1" />
	<joueurs id="103" nom="MILOSEVIC" prenom="Nemanja" id_equipe="1" />
	<joueurs id="104" nom="McALARNEY" prenom="Kyle" id_equipe="1" />
	<joueurs id="105" nom="OLASENI" prenom="Gabe" id_equipe="1" />
	<joueurs id="106" nom="JOSEPH" prenom="Georgi" id_equipe="1" />
	<joueurs id="107" nom="MENDY" prenom="Antoine" id_equipe="1" />
	<joueurs id="108" nom="PRINCE" prenom="John" id_equipe="1" />
	<joueurs id="109" nom="SOMMERVILLE" prenom="Marcellus" id_equipe="1" />
	<joueurs id="110" nom="SYLLA" prenom="Abdel Kader" id_equipe="1" />
	<joueurs id="111" nom="VINCENT" prenom="Thomas" id_equipe="1" />
	
	<matchs id="34" />
	
	<bilans id_match="34" id_joueur="201" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="6" deux_points="14" trois_points_reussis="0" trois_points="0" rebonds="8" fautes="3" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="202" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="2" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="203" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="0" deux_points="3"  trois_points_reussis="3" trois_points="9" rebonds="1" fautes="4" passes_decisives="5"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="204" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="2" trois_points="2" rebonds="8" fautes="4" passes_decisives="2"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="205" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="4"  trois_points_reussis="1" trois_points="7" rebonds="2" fautes="3" passes_decisives="2"  ballons_perdus="3" interceptions="3" contres="0" />
	<bilans id_match="34" id_joueur="206" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="207" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="3"  trois_points_reussis="1" trois_points="3" rebonds="2" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="208" lancer_francs_reussis="2" lancer_francs="4" deux_points_reussis="3" deux_points="4"  trois_points_reussis="0" trois_points="3" rebonds="5" fautes="1" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="1" />
	<bilans id_match="34" id_joueur="209" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="3"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="0"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="210" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="4" deux_points="7"  trois_points_reussis="2" trois_points="4" rebonds="1" fautes="0" passes_decisives="3"  ballons_perdus="4" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="211" lancer_francs_reussis="3" lancer_francs="4" deux_points_reussis="1" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="1" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="101" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="2" deux_points="2"  trois_points_reussis="3" trois_points="5" rebonds="5" fautes="0" passes_decisives="4"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="102" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="103" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="2"  trois_points_reussis="1" trois_points="2" rebonds="1" fautes="1" passes_decisives="1"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="104" lancer_francs_reussis="3" lancer_francs="3" deux_points_reussis="0" deux_points="2"  trois_points_reussis="1" trois_points="4" rebonds="3" fautes="1" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="105" lancer_francs_reussis="2" lancer_francs="2" deux_points_reussis="4" deux_points="10" trois_points_reussis="0" trois_points="0" rebonds="6" fautes="2" passes_decisives="2"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="106" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="107" lancer_francs_reussis="1" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="2" trois_points="7" rebonds="3" fautes="0" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="108" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="7" deux_points="8"  trois_points_reussis="1" trois_points="2" rebonds="5" fautes="2" passes_decisives="10" ballons_perdus="2" interceptions="4" contres="0" />
	<bilans id_match="34" id_joueur="109" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="4" deux_points="6"  trois_points_reussis="0" trois_points="1" rebonds="3" fautes="3" passes_decisives="3"  ballons_perdus="2" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="110" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="0" trois_points="0" rebonds="5" fautes="2" passes_decisives="4"  ballons_perdus="2" interceptions="2" contres="0" />
	<bilans id_match="34" id_joueur="111" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="1" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />

</dataset>
<!-- BilansDaoTestResultat.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<bilans id_match="34" id_joueur="201" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="6" deux_points="14" trois_points_reussis="0" trois_points="0" rebonds="8" fautes="3" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="202" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="2" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="203" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="0" deux_points="3"  trois_points_reussis="3" trois_points="9" rebonds="1" fautes="4" passes_decisives="5"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="204" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="2" trois_points="2" rebonds="8" fautes="4" passes_decisives="2"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="205" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="4"  trois_points_reussis="1" trois_points="7" rebonds="2" fautes="3" passes_decisives="2"  ballons_perdus="3" interceptions="3" contres="0" />
	<bilans id_match="34" id_joueur="206" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="0"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="207" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="3"  trois_points_reussis="1" trois_points="3" rebonds="2" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="208" lancer_francs_reussis="2" lancer_francs="4" deux_points_reussis="3" deux_points="4"  trois_points_reussis="0" trois_points="3" rebonds="5" fautes="1" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="1" />
	<bilans id_match="34" id_joueur="209" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="3"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="0"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="210" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="4" deux_points="7"  trois_points_reussis="2" trois_points="4" rebonds="1" fautes="0" passes_decisives="3"  ballons_perdus="4" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="211" lancer_francs_reussis="3" lancer_francs="4" deux_points_reussis="1" deux_points="3"  trois_points_reussis="0" trois_points="0" rebonds="1" fautes="0" passes_decisives="0"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="101" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="2" deux_points="2"  trois_points_reussis="3" trois_points="5" rebonds="5" fautes="0" passes_decisives="4"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="102" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="0" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="0" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="103" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="2" deux_points="2"  trois_points_reussis="1" trois_points="2" rebonds="1" fautes="1" passes_decisives="1"  ballons_perdus="0" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="104" lancer_francs_reussis="3" lancer_francs="3" deux_points_reussis="0" deux_points="2"  trois_points_reussis="1" trois_points="4" rebonds="3" fautes="1" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="105" lancer_francs_reussis="2" lancer_francs="2" deux_points_reussis="4" deux_points="10" trois_points_reussis="0" trois_points="0" rebonds="6" fautes="2" passes_decisives="2"  ballons_perdus="0" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="106" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="1" trois_points="1" rebonds="3" fautes="2" passes_decisives="1"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="107" lancer_francs_reussis="1" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="2" trois_points="7" rebonds="3" fautes="0" passes_decisives="2"  ballons_perdus="1" interceptions="1" contres="0" />
	<bilans id_match="34" id_joueur="108" lancer_francs_reussis="1" lancer_francs="2" deux_points_reussis="7" deux_points="8"  trois_points_reussis="1" trois_points="2" rebonds="5" fautes="2" passes_decisives="10" ballons_perdus="2" interceptions="4" contres="0" />
	<bilans id_match="34" id_joueur="109" lancer_francs_reussis="4" lancer_francs="4" deux_points_reussis="4" deux_points="6"  trois_points_reussis="0" trois_points="1" rebonds="3" fautes="3" passes_decisives="3"  ballons_perdus="2" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="110" lancer_francs_reussis="0" lancer_francs="1" deux_points_reussis="5" deux_points="7"  trois_points_reussis="0" trois_points="0" rebonds="5" fautes="2" passes_decisives="4"  ballons_perdus="2" interceptions="2" contres="0" />
	<bilans id_match="34" id_joueur="111" lancer_francs_reussis="0" lancer_francs="0" deux_points_reussis="1" deux_points="1"  trois_points_reussis="0" trois_points="0" rebonds="0" fautes="1" passes_decisives="0"  ballons_perdus="1" interceptions="0" contres="0" />
	<bilans id_match="34" id_joueur="0" lancer_francs_reussis="2" lancer_francs="1" deux_points_reussis="4" deux_points="3"  trois_points_reussis="6" trois_points="5" rebonds="7" fautes="8" passes_decisives="9"  ballons_perdus="10" interceptions="11" contres="12" />
</dataset>
package fr.julien.formation.basket.dao.dbunit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;

import org.dbunit.Assertion;
import org.dbunit.assertion.comparer.value.ValueComparer;
import org.dbunit.assertion.comparer.value.ValueComparers;
import org.dbunit.assertion.comparer.value.builder.ColumnValueComparerMapBuilder;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.BilansDao;
import fr.julien.formation.basket.exception.BasketException;
import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class BilansDaoTest {
	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
			IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
			FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
			xmlDSBuilder.setCaseSensitiveTableNames(false);
			InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/BilansDaoTest.xml");
			IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
			DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, dataSet);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
   }

    @AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerSelection() {
		try {
			List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
			Assertions.assertEquals(22, bilans.size());
			Assertions.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancs());
			Assertions.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
			Assertions.assertEquals(14, bilans.get(0).getDeuxPoints());
			Assertions.assertEquals(0, bilans.get(0).getTroisPointsReussis());
			Assertions.assertEquals(0, bilans.get(0).getTroisPoints());
			Assertions.assertEquals(1, bilans.get(0).getPassesDecisives());
			Assertions.assertEquals(1, bilans.get(0).getBallonsPerdus());
			Assertions.assertEquals(3, bilans.get(0).getFautes());
			Assertions.assertEquals(8, bilans.get(0).getRebonds());
			Assertions.assertEquals(0, bilans.get(0).getInterceptions());
			Assertions.assertEquals(0, bilans.get(0).getContres());
		}
		catch (BasketException e) {
			e.printStackTrace();
			Assertions.fail();
		}
    }

	@Test
	public void testerInsertion() {
		try {
			try (Statement stmt = cnx.createStatement()) {
				stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
			}
			BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
			BilansDao.getInstance().inserer(cnx, b, 34);
			IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
			QueryDataSet partialDataSet = new QueryDataSet(dbUnitConnection);
			partialDataSet.addTable("bilans", "SELECT * FROM bilans");
			FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
			xmlDSBuilder.setCaseSensitiveTableNames(false);
			InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/BilansDaoTestResultat.xml");
			IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
			ITable tableAttendue = dataSet.getTable("bilans");
			Map<String, ValueComparer> columnValueComparers = new ColumnValueComparerMapBuilder().add("lancer_francs_reussis", ValueComparers.isActualEqualToExpected).add("lancer_francs", ValueComparers.isActualEqualToExpected).build();
			Assertion.assertWithValueComparer(tableAttendue, partialDataSet.getTable("bilans"), ValueComparers.isActualEqualToExpected, columnValueComparers);
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}
<!-- MatchsDaoTestResultat.xml -->
<?xml version="1.0" encoding="UTF-8"?>  
<dataset>  
	<matchs id="1" />
</dataset>
package fr.julien.formation.basket.dao.dbunit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;

import org.dbunit.Assertion;
import org.dbunit.assertion.comparer.value.ValueComparer;
import org.dbunit.assertion.comparer.value.ValueComparers;
import org.dbunit.assertion.comparer.value.builder.ColumnValueComparerMapBuilder;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.MatchDao;

public class MatchsDaoTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerInsertion() {
		try {
			MatchDao.getInstance().inserer(cnx, 1);
			try (Statement stmt = cnx.createStatement()) {
				IDatabaseConnection dbUnitConnection = new DatabaseConnection(cnx);
				QueryDataSet partialDataSet = new QueryDataSet(dbUnitConnection);
				partialDataSet.addTable("matchs", "SELECT * FROM matchs");
				FlatXmlDataSetBuilder xmlDSBuilder = new FlatXmlDataSetBuilder();
				xmlDSBuilder.setCaseSensitiveTableNames(false);
				InputStream inputStreamXML = new FileInputStream("src/test/resources/datasets/MatchsDaoTestResultat.xml");
				IDataSet dataSet = xmlDSBuilder.build(inputStreamXML);
				ITable tableAttendue = dataSet.getTable("matchs");
				Map<String, ValueComparer> columnValueComparers = new ColumnValueComparerMapBuilder().build();
				Assertion.assertWithValueComparer(tableAttendue, partialDataSet.getTable("matchs"), ValueComparers.isActualEqualToExpected, columnValueComparers);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Avec un script SQL

La création des fichiers suivants est nécéssaire

  • Un fichier src/test/resources/init_database_test.sql qui contient les instructions permettant de créer la base de données de test (script commun à tous les tests)
  • Un fichier src/test/resources/data/[NomTest].sql par classe de test qui contient les instructions permettant d'initialiser la base pour un test particulier
-- src/test/resources/init_database_test.sql
DROP TABLE IF EXISTS bilans CASCADE;
DROP TABLE IF EXISTS joueurs CASCADE;
DROP TABLE IF EXISTS equipes CASCADE;
DROP TABLE IF EXISTS matchs CASCADE;

CREATE TABLE matchs (
	id INT PRIMARY KEY
);

CREATE TABLE equipes (
	id INT PRIMARY KEY,
	nom VARCHAR
);

CREATE TABLE joueurs (
	id INT PRIMARY KEY,
	nom VARCHAR,
	prenom VARCHAR,
	id_equipe INT REFERENCES equipes(id)
);

CREATE TABLE bilans (
	id_match INT,
	id_joueur INT REFERENCES joueurs(id),
	lancer_francs INT,
	lancer_francs_reussis INT,
	deux_points INT,
	deux_points_reussis INT,
	trois_points INT,
	trois_points_reussis INT,
	rebonds INT,
	fautes INT,
	passes_decisives INT,
	ballons_perdus INT,
	interceptions INT,
	contres INT
);
-- Fichiers d'initialisation des tests (identiques pour les deux tests)
INSERT INTO equipes(id, nom) 
VALUES 
	(1, 'Orléans'), 
	(2, 'Limoges');
INSERT INTO joueurs (id, nom, prenom, id_equipe)
VALUES 
	(201, 'CAMARA', 'Ousmane', 2),
	(202, 'JONES', 'Joseph', 2),
	(203, 'PREPELIC', 'Klemen', 2),
	(204, 'WOJCIECHOWSKI', 'Mathieu', 2),
	(205, 'WOOD', 'Dashaun', 2),
	(206, 'DELAGE', 'Benjamin', 2),
	(207, 'DUPORT', 'Romain', 2),
	(208, 'FAIR', 'C.J', 2),
	(209, 'MUNANGA', 'Shekinah', 2),
	(210, 'RANDLE', 'Jerome', 2),
	(211, 'ZERBO', 'Fréjus', 2),
	(101, 'DOWNS', 'Micah', 1),
	(102, 'LOUBAKI', 'Luc', 1),
	(103, 'MILOSEVIC', 'Nemanja', 1),
	(104, 'McALARNEY', 'Kyle', 1),
	(105, 'OLASENI', 'Gabe', 1),
	(106, 'JOSEPH', 'Georgi', 1),
	(107, 'MENDY', 'Antoine', 1),
	(108, 'PRINCE', 'John', 1),
	(109, 'SOMMERVILLE', 'Marcellus', 1),
	(110, 'SYLLA', 'Abdel Kader', 1),
	(111, 'VINCENT', 'Thomas', 1);
	
INSERT INTO matchs(id) VALUES (34);

INSERT INTO bilans (id_match, id_joueur, lancer_francs_reussis, lancer_francs, deux_points_reussis, deux_points, trois_points_reussis, trois_points, rebonds, fautes, passes_decisives,ballons_perdus, interceptions, contres)
VALUES 
	(34, 201, 0, 0, 6, 14, 0, 0, 8, 3, 1, 1, 0, 0),
	(34, 202, 0, 1, 2, 3, 0, 0, 0, 2, 1, 1, 0, 0),
	(34, 203, 4, 4, 0, 3, 3, 9, 1, 4, 5, 1, 0, 0),
	(34, 204, 0, 0, 0, 0, 2, 2, 8, 4, 2, 1, 0, 0),
	(34, 205, 0, 0, 2, 4, 1, 7, 2, 3, 2, 3, 3, 0),
	(34, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
	(34, 207, 0, 0, 1, 3, 1, 3, 2, 0, 0, 0, 0, 0),
	(34, 208, 2, 4, 3, 4, 0, 3, 5, 1, 0, 0, 1, 1),
	(34, 209, 0, 0, 2, 3, 1, 1, 3, 2, 0, 1, 1, 0),
	(34, 210, 0, 0, 4, 7, 2, 4, 1, 0, 3, 4, 0, 0),
	(34, 211, 3, 4, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0),
	(34, 101, 1, 2, 2, 2, 3, 5, 5, 0, 4, 1, 0, 0),
	(34, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0),
	(34, 103, 0, 0, 2, 2, 1, 2, 1, 1, 1, 0, 0, 0),
	(34, 104, 3, 3, 0, 2, 1, 4, 3, 1, 2, 1, 1, 0),
	(34, 105, 2, 2, 4, 10, 0, 0, 6, 2, 2, 0, 1, 0),
	(34, 106, 0, 0, 1, 1, 1, 1, 3, 2, 1, 1, 1, 0),
	(34, 107, 1, 1, 5, 7, 2, 7, 3, 0, 2, 1, 1, 0),
	(34, 108, 1, 2, 7, 8, 1, 2, 5, 2, 10, 2, 4, 0),
	(34, 109, 4, 4, 4, 6, 0, 1, 3, 3, 3, 2, 0, 0),
	(34, 110, 0, 1, 5, 7, 0, 0, 5, 2, 4, 2, 2, 0),
	(34, 111, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0);
package fr.julien.formation.basket.dao.scripts;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.dao.BilansDao;
import fr.julien.formation.basket.exception.BasketException;
import fr.julien.formation.basket.model.BilanJoueur;
import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.model.Joueur;

public class BilansDaoTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/BilansDaoTest.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

 	@Test
	public void testerSelection() {
 		try {
			List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
			Assertions.assertEquals(22, bilans.size());
			Assertions.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
			Assertions.assertEquals(0, bilans.get(0).getLancerFrancs());
			Assertions.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
			Assertions.assertEquals(14, bilans.get(0).getDeuxPoints());
			Assertions.assertEquals(0, bilans.get(0).getTroisPointsReussis());
			Assertions.assertEquals(0, bilans.get(0).getTroisPoints());
			Assertions.assertEquals(1, bilans.get(0).getPassesDecisives());
			Assertions.assertEquals(1, bilans.get(0).getBallonsPerdus());
			Assertions.assertEquals(3, bilans.get(0).getFautes());
			Assertions.assertEquals(8, bilans.get(0).getRebonds());
			Assertions.assertEquals(0, bilans.get(0).getInterceptions());
			Assertions.assertEquals(0, bilans.get(0).getContres());
		}
		catch (BasketException e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}

	@Test
	public void testerInsertion() {
		try {
			try (Statement stmt = cnx.createStatement()) {
				stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
			}
			BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
			BilansDao.getInstance().inserer(cnx, b, 34);
			try (Statement stmt = cnx.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_joueur=0")) {
				Assertions.assertTrue(rs.next());
				Assertions.assertEquals(2, rs.getInt("lancer_francs_reussis"));
			}
		}
		catch (BasketException | SQLException e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}
public class BilansDaoTest {

    private Connection cnx;

    @Before
    public void setUp() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUser("sa");
        dataSource.setPassword("");
        try {
            cnx = dataSource.getConnection();
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/BilansDaoTest.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown() {
        try {
            cnx.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testerSelection() {
        try {
            List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, 34);
            Assert.assertEquals(22, bilans.size());
            Assert.assertEquals(new Joueur("CAMARA", "Ousmane", new Equipe("Limoges")), bilans.get(0).getJoueur());
            Assert.assertEquals(0, bilans.get(0).getLancerFrancsReussis());
            Assert.assertEquals(0, bilans.get(0).getLancerFrancs());
            Assert.assertEquals(6, bilans.get(0).getDeuxPointsReussis());
            Assert.assertEquals(14, bilans.get(0).getDeuxPoints());
            Assert.assertEquals(0, bilans.get(0).getTroisPointsReussis());
            Assert.assertEquals(0, bilans.get(0).getTroisPoints());
            Assert.assertEquals(1, bilans.get(0).getPassesDecisives());
            Assert.assertEquals(1, bilans.get(0).getBallonsPerdus());
            Assert.assertEquals(3, bilans.get(0).getFautes());
            Assert.assertEquals(8, bilans.get(0).getRebonds());
            Assert.assertEquals(0, bilans.get(0).getInterceptions());
            Assert.assertEquals(0, bilans.get(0).getContres());
        }
        catch (BasketException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerInsertion() {
        try {
            try (Statement stmt = cnx.createStatement()) {
                stmt.executeUpdate("INSERT INTO joueurs(id, nom, prenom, id_equipe) VALUES (0, 'Gauchet', 'Julien', 2)");
            }
            BilanJoueur b = new BilanJoueur(new Joueur("Gauchet", "Julien", new Equipe("Orléans")), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
            BilansDao.getInstance().inserer(cnx, b, 34);
            try (Statement stmt = cnx.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_joueur=0")) {
                Assert.assertTrue(rs.next());
                Assert.assertEquals(2, rs.getInt("lancer_francs_reussis"));
            }
        }
        catch (BasketException | SQLException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}

Création de mocks

Nous allons maintenant tester la classe fr.julien.formation.basket.services.MiseAJourMatchs qui fait appel à un web service non accessible hors production. Utilisez des mock pour réaliser le test de cette classe. Un refactoring est nécéssaire

Le web service fournit un résultat xml scructuré de la facon suivante :

<matchs journee="??">
	nomJoueur;prenomJoueur;nomEquipe;lancerFrancs;lancerFrancsReussis;deuxPoints;deuxPointsReussis;troisPoints;troisPointsReussis;rebonds;fautes;passesDecisives;ballonsPerdus;interceptions;contres
	nomJoueur;prenomJoueur;nomEquipe;lancerFrancs;lancerFrancsReussis;deuxPoints;deuxPointsReussis;troisPoints;troisPointsReussis;rebonds;fautes;passesDecisives;ballonsPerdus;interceptions;contres
</matchs>

Avec héritage

package fr.julien.formation.basket.services.matchs.heritage;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.services.lnb.AccesWebServiceLNB;
import fr.julien.formation.basket.services.matchs.MiseAJourMatchs;

public class MiseAJourMatchsTest {

	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testerMiseAJour() {
		try {
			AccesWebServiceLNB webService = new AccesWebServiceLNB() {
				@Override
				public String getReponse(String url, int journee) {
					StringBuilder sb = new StringBuilder();
					sb.append("<matchs journee=\"34\">");
					sb.append("SOMMERVILLE;Marcellus;Orléans;5;3;5;5;2;1;3;2;3;1;0;1");
					sb.append("</matchs>");
					return sb.toString();
				}
			};
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().mettreAJour(cnx, new Equipe("Orléans"), 33);
			try (Statement stmt = cnx.createStatement()) {
				try (ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_match=33")) {
					Assertions.assertTrue(rs.next());
					Assertions.assertEquals(5, rs.getInt("lancer_francs"));
					Assertions.assertEquals(3, rs.getInt("lancer_francs_reussis"));
					Assertions.assertEquals(5, rs.getInt("deux_points"));
					Assertions.assertEquals(5, rs.getInt("deux_points_reussis"));
					Assertions.assertEquals(2, rs.getInt("trois_points"));
					Assertions.assertEquals(1, rs.getInt("trois_points_reussis"));
					Assertions.assertEquals(3, rs.getInt("rebonds"));
					Assertions.assertEquals(2, rs.getInt("fautes"));
					Assertions.assertEquals(3, rs.getInt("passes_decisives"));
					Assertions.assertEquals(1, rs.getInt("ballons_perdus"));
					Assertions.assertEquals(0, rs.getInt("interceptions"));
					Assertions.assertEquals(1, rs.getInt("contres"));
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Avec l'utilisation de mockito

package fr.julien.formation.basket.services.matchs.easymock;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.easymock.EasyMock;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import fr.julien.formation.basket.model.Equipe;
import fr.julien.formation.basket.services.lnb.AccesWebServiceLNB;
import fr.julien.formation.basket.services.matchs.MiseAJourMatchs;

@DisplayName("Test des mises à jour avec Mockito")
public class MiseAJourMatchsTest {
	private Connection cnx;

	@BeforeEach
	public void setUp() {
		JdbcDataSource dataSource = new JdbcDataSource();
		dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
		dataSource.setUser("sa");
		dataSource.setPassword("");
		try {
			cnx = dataSource.getConnection();
			try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
				RunScript.execute(cnx, br);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@AfterEach
	public void tearDown() {
		try {
			cnx.close();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Test
	@DisplayName("Test global")
	public void testerMiseAJour() {
		try {
			AccesWebServiceLNB webService = EasyMock.createNiceMock(AccesWebServiceLNB.class);
			StringBuilder sb = new StringBuilder();
			sb.append("<matchs journee=\"34\">");
			sb.append("SOMMERVILLE;Marcellus;Orléans;5;3;5;5;2;1;3;2;3;1;0;1");
			sb.append("</matchs>");
			EasyMock.expect(webService.getReponse("http://www.lnb.fr/ws/journee/", 33)).andReturn(sb.toString());
			EasyMock.replay(webService);
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().setAccesWebServiceLNB(webService);
			MiseAJourMatchs.getInstance().mettreAJour(cnx, new Equipe("Orléans"), 33);
			try (Statement stmt = cnx.createStatement()) {
				try (ResultSet rs = stmt.executeQuery("SELECT * FROM bilans WHERE id_match=33")) {
					Assertions.assertTrue(rs.next());
					Assertions.assertEquals(5, rs.getInt("lancer_francs"));
					Assertions.assertEquals(3, rs.getInt("lancer_francs_reussis"));
					Assertions.assertEquals(5, rs.getInt("deux_points"));
					Assertions.assertEquals(5, rs.getInt("deux_points_reussis"));
					Assertions.assertEquals(2, rs.getInt("trois_points"));
					Assertions.assertEquals(1, rs.getInt("trois_points_reussis"));
					Assertions.assertEquals(3, rs.getInt("rebonds"));
					Assertions.assertEquals(2, rs.getInt("fautes"));
					Assertions.assertEquals(3, rs.getInt("passes_decisives"));
					Assertions.assertEquals(1, rs.getInt("ballons_perdus"));
					Assertions.assertEquals(0, rs.getInt("interceptions"));
					Assertions.assertEquals(1, rs.getInt("contres"));
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			Assertions.fail();
		}
	}
}

Que faire de l'ihm ?

Notre application contient une partie ihm : le test de l'ihm ne se fait pas grâce à des tests unitaires. Cependant, une partie du code de l'ihm peut être testée : a vous de l'identifier et de faire ce qu'il faut pour que cette partie soit désormais testable

public class TableauEquipe {

    private String nomEquipe;
    private List<List<String>> statistiques;

    public TableauEquipe() {
        this.statistiques = new ArrayList<>();
    }

    public TableauEquipe(String nomEquipe) {
        this.nomEquipe = nomEquipe;
        this.statistiques = new ArrayList<>();
    }

    /**
     * Méthode permettant d'accéder au nom de l'équipe
     * 
     * @return le nom de l'équipe
     */
    public String getNomEquipe() {
        return nomEquipe;
    }

    /**
     * Méthode permettant d'accéder aux statistiques
     * 
     * @return les statistiques
     */
    public List<List<String>> getStatistiques() {
        return statistiques;
    }

    public void setNomEquipe(String nomEquipe) {
        this.nomEquipe = nomEquipe;
    }

    public void setStatistiques(List<List<String>> statistiques) {
        this.statistiques = statistiques;
    }
}
public class TableauMatch {

    private TableauEquipe tableauEquipe1;
    private TableauEquipe tableauEquipe2;

    public TableauMatch(TableauEquipe tableauEquipe1, TableauEquipe tableauEquipe2) {
        super();
        this.tableauEquipe1 = tableauEquipe1;
        this.tableauEquipe2 = tableauEquipe2;
    }

    /**
     * Méthode permettant d'accéder au tableau de l'équipe 1
     * 
     * @return le tableau de l'équipe 1
     */
    public TableauEquipe getTableauEquipe1() {
        return tableauEquipe1;
    }

    /**
     * Méthode permettant d'accéder tableau de l'équipe 2
     * 
     * @return le tableau de l'équipe 2
     */
    public TableauEquipe getTableauEquipe2() {
        return tableauEquipe2;
    }
}
public class GenerationTableauMatch {

    private static GenerationTableauMatch instance = new GenerationTableauMatch();

    private GenerationTableauMatch() {
        super();
    }

    public TableauMatch genererTableauMatch(Connection cnx, int journee) throws BasketException {
        List<BilanJoueur> bilans = BilansDao.getInstance().getBilansByMatch(cnx, journee);
        String equipe1 = null;
        String equipe2 = null;
        TableauEquipe tableauEquipe1 = new TableauEquipe();
        TableauEquipe tableauEquipe2 = new TableauEquipe();
        for (BilanJoueur b : bilans) {
            if (equipe1 == null) {
                equipe1 = b.getJoueur().getEquipe().getNom();
                tableauEquipe1.setNomEquipe(equipe1);
            }
            else if (equipe2 == null && !b.getJoueur().getEquipe().getNom().equalsIgnoreCase(equipe1)) {
                equipe2 = b.getJoueur().getEquipe().getNom();
                tableauEquipe2.setNomEquipe(equipe2);
            }
            if (b.getJoueur().getEquipe().getNom().equals(equipe1)) {
                tableauEquipe1.getStatistiques().add(calculerScore(b));
            }
            else if (b.getJoueur().getEquipe().getNom().equals(equipe2)) {
                tableauEquipe2.getStatistiques().add(calculerScore(b));
            }
        }
        return new TableauMatch(tableauEquipe1, tableauEquipe2);
    }

    private List<String> calculerScore(BilanJoueur b) {
        List<String> stat = new ArrayList<>();
        int score = CalculStatistiquesService.getInstance().calculerScore(b);
        stat.add(b.getJoueur().toString());
        stat.add(String.valueOf(score));
        stat.add(b.getDeuxPointsReussis() + "/" + b.getDeuxPoints());
        stat.add(b.getTroisPointsReussis() + "/" + b.getTroisPoints());
        stat.add(b.getLancerFrancsReussis() + "/" + b.getLancerFrancs());
        stat.add(String.valueOf(b.getRebonds()));
        stat.add(String.valueOf(b.getPassesDecisives()));
        stat.add(String.valueOf(b.getFautes()));
        stat.add(String.valueOf(b.getInterceptions()));
        stat.add(String.valueOf(b.getBallonsPerdus()));
        stat.add(String.valueOf(b.getContres()));
        stat.add(String.valueOf(CalculStatistiquesService.getInstance().calculerEvaluation(b)));
        return stat;
    }

    public static GenerationTableauMatch getInstance() {
        return instance;
    }
}
INSERT INTO equipes(id, nom) 
VALUES 
	(1, 'Orléans'), 
	(2, 'Limoges');
INSERT INTO joueurs (id, nom, prenom, id_equipe)
VALUES 
	(201, 'CAMARA', 'Ousmane', 2),
	(202, 'JONES', 'Joseph', 2),
	(203, 'PREPELIC', 'Klemen', 2),
	(204, 'WOJCIECHOWSKI', 'Mathieu', 2),
	(205, 'WOOD', 'Dashaun', 2),
	(206, 'DELAGE', 'Benjamin', 2),
	(207, 'DUPORT', 'Romain', 2),
	(208, 'FAIR', 'C.J', 2),
	(209, 'MUNANGA', 'Shekinah', 2),
	(210, 'RANDLE', 'Jerome', 2),
	(211, 'ZERBO', 'Fréjus', 2),
	(101, 'DOWNS', 'Micah', 1),
	(102, 'LOUBAKI', 'Luc', 1),
	(103, 'MILOSEVIC', 'Nemanja', 1),
	(104, 'McALARNEY', 'Kyle', 1),
	(105, 'OLASENI', 'Gabe', 1),
	(106, 'JOSEPH', 'Georgi', 1),
	(107, 'MENDY', 'Antoine', 1),
	(108, 'PRINCE', 'John', 1),
	(109, 'SOMMERVILLE', 'Marcellus', 1),
	(110, 'SYLLA', 'Abdel Kader', 1),
	(111, 'VINCENT', 'Thomas', 1);
	
INSERT INTO matchs(id) VALUES (34);

INSERT INTO bilans (id_match, id_joueur, lancer_francs_reussis, lancer_francs, deux_points_reussis, deux_points, trois_points_reussis, trois_points, rebonds, fautes, passes_decisives,ballons_perdus, interceptions, contres)
VALUES 
	(34, 201, 0, 0, 6, 14, 0, 0, 8, 3, 1, 1, 0, 0),
	(34, 202, 0, 1, 2, 3, 0, 0, 0, 2, 1, 1, 0, 0),
	(34, 203, 4, 4, 0, 3, 3, 9, 1, 4, 5, 1, 0, 0),
	(34, 204, 0, 0, 0, 0, 2, 2, 8, 4, 2, 1, 0, 0),
	(34, 205, 0, 0, 2, 4, 1, 7, 2, 3, 2, 3, 3, 0),
	(34, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
	(34, 207, 0, 0, 1, 3, 1, 3, 2, 0, 0, 0, 0, 0),
	(34, 208, 2, 4, 3, 4, 0, 3, 5, 1, 0, 0, 1, 1),
	(34, 209, 0, 0, 2, 3, 1, 1, 3, 2, 0, 1, 1, 0),
	(34, 210, 0, 0, 4, 7, 2, 4, 1, 0, 3, 4, 0, 0),
	(34, 211, 3, 4, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0),
	(34, 101, 1, 2, 2, 2, 3, 5, 5, 0, 4, 1, 0, 0),
	(34, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0),
	(34, 103, 0, 0, 2, 2, 1, 2, 1, 1, 1, 0, 0, 0),
	(34, 104, 3, 3, 0, 2, 1, 4, 3, 1, 2, 1, 1, 0),
	(34, 105, 2, 2, 4, 10, 0, 0, 6, 2, 2, 0, 1, 0),
	(34, 106, 0, 0, 1, 1, 1, 1, 3, 2, 1, 1, 1, 0),
	(34, 107, 1, 1, 5, 7, 2, 7, 3, 0, 2, 1, 1, 0),
	(34, 108, 1, 2, 7, 8, 1, 2, 5, 2, 10, 2, 4, 0),
	(34, 109, 4, 4, 4, 6, 0, 1, 3, 3, 3, 2, 0, 0),
	(34, 110, 0, 1, 5, 7, 0, 0, 5, 2, 4, 2, 2, 0),
	(34, 111, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0);
public class GenerationTableauMatchTest {

    private Connection cnx;

    @Before
    public void setUp() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUser("sa");
        dataSource.setPassword("");
        try {
            cnx = dataSource.getConnection();
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_database_test.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/data/GenerationTableauMatchTest.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown() {
        try {
            cnx.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testerGenerationTableaux() {
        try {
            TableauMatch t = GenerationTableauMatch.getInstance().genererTableauMatch(cnx, 34);
            Assert.assertEquals(true, t.getTableauEquipe1() != null);
            Assert.assertEquals(true, t.getTableauEquipe2() != null);
            Assert.assertEquals("Limoges", t.getTableauEquipe1().getNomEquipe());
            Assert.assertEquals(11, t.getTableauEquipe1().getStatistiques().size());
            int cpt = 0;
            Assert.assertEquals("Ousmane CAMARA", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("12", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("6/14", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0/0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0/0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("8", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("1", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("3", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("1", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("0", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
            Assert.assertEquals("12", t.getTableauEquipe1().getStatistiques().get(0).get(cpt++));
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}

Bilan de l'exercice 1

Nous avons testé notre application de manière méticuleuse et sans trop en faire, malgré tout, le refactoring et l'adaptation de l'application à nos test a été une part importante du travail de test, sans doute l'étape la plus longue et complexe

Les sources de la solution sont disponnibles ici : projet basket : solution, le pom utilisé est le suivant : projet basket : solution

La couverture de test est de 55,7% ce qui est un bon score mais encore loin des 80% recommandés. La question la plus importante à se poser n'est pas "quel est ma couverture de test ?" mais "est-ce que je couvre une partie suffisante des fonctionnalités de l'application ?" et dans notre cas, nous ne pouvons pas réelement faire mieux sans tester des choses triviales ou sans dégrader la simplicité de nos tests

Couverture de test

Exercice 2 : Présentation

Le but de ces exercices est de réaliser le test d'une application Spring et de réaliser des modifications afin de se rendre compte de la pertinence des cas de tests mis en place.

L'application utilise des relevés géologiques faits dans le jura afin de comparer les concentrations en nickel et en cobalt du sol et d'afficher une régression linéaire sur ces deux variables

Les sources de l'application dont disponnibles sur gitlab :

git clone git@gitlab.com:julien-gauchet/tests-unitaires-exercices.git

Vous pouvez également les télécharger ici : Sources tests unitaires


Configuration des tests avec spring

Dans un premier temps, nous allons configurer le projet pour utiliser Spring test et une base H2

  • Créer une classe de config pemettant de récupérer un transactionManager pour les tests
  • Pour structurer les tests, créer deux classes abstraites contenant la config pour les tests
    • La première pour les tests simples (sans appel à la base de données)
    • La seconde initialise une base de données
<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
	</dependency>
	<dependency>
		<groupId>com.h2database</groupId>
		<artifactId>h2</artifactId>
	</dependency>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
		<version>5.4.21.Final</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.data</groupId>
		<artifactId>spring-data-jpa</artifactId>
		<version>2.3.4.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-dbcp2</artifactId>
		<version>2.8.0</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>5.2.9.RELEASE</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-simple</artifactId>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
@Profile("test")
@Configuration
@ComponentScan(basePackages = {"fr.julien.graphiques"})
@EnableJpaRepositories(basePackages = {"fr.julien.graphiques.dao.repository"})
public class ConfigTest {

    @Bean(destroyMethod = "close")
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        return dataSource;
    }

    /**
     * Interface entre EntityManagerFactory et Hibernate
     */
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setDatabase(Database.H2);
        return jpaVendorAdapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource());
        emf.setPersistenceUnitName("graphiques");
        emf.setPackagesToScan("fr.julien.graphiques.modele.entites");
        emf.setJpaVendorAdapter(jpaVendorAdapter());
        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.show_sql", true);
        emf.setJpaProperties(jpaProperties);
        return emf;
    }

    @Bean("transactionManager")
    @Primary
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }
}
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { ConfigTest.class })
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
public abstract class AbstractTest {
}
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {ConfigTest.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
public abstract class AbstractTestBdd {

    @Autowired
    private DataSource dataSource;
    protected Connection connection;

    @PostConstruct
    public void postConstruct() {
        try {
            connection = dataSource.getConnection();
            JdbcDataSource dataSource = new JdbcDataSource();
            dataSource.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
            dataSource.setUser("sa");
            dataSource.setPassword("");
            Connection cnx = dataSource.getConnection();
            try (InputStreamReader fr = new FileReader(new File("src/test/resources/init_db2.sql")); BufferedReader br = new BufferedReader(fr)) {
                RunScript.execute(cnx, br);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Création d'un test

Je ne propose pas de correction de cette partie, l'idée sera de construire votre propre jeu de test

Testez le plus efficacement possible les classes de ce projet


Modification du modèle de données

Dorénavant, nous allons utiliser le fichier init_db2.sql pour initialiser la base de données

Pour savoir si vos tests unitaires sont corrects, le but du jeu sera de corriger les tests et le programme et de voir si après cette correction, le programme se lance ou si le jeu de tests était insuffisant pour procéder au lancement

@Entity
@Table(name = "concentrations")
public class Concentration {

    @Id
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "id_releve")
    private Releve releve;
    @ManyToOne
    @JoinColumn(name = "id_minerai")
    private Minerai minerai;
    @Column(name = "valeur")
    private Double valeur;

    public Releve getReleve() {
        return releve;
    }

    public void setReleve(Releve releve) {
        this.releve = releve;
    }

    public Minerai getMinerai() {
        return minerai;
    }

    public void setMinerai(Minerai minerai) {
        this.minerai = minerai;
    }

    public Double getValeur() {
        return valeur;
    }

    public void setValeur(Double valeur) {
        this.valeur = valeur;
    }
}
@Entity
@Table(name = "minerais")
public class Minerai {

    @Id
    private String id;
    @Column(name = "libelle")
    private String libelle;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getLibelle() {
        return libelle;
    }

    public void setLibelle(String libelle) {
        this.libelle = libelle;
    }
}
@Entity
@Table(name = "releves")
public class Releve implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    private Integer id;
    @Column(name = "date_releve")
    private LocalDate date;
    @Column(name = "lieu")
    private String lieu;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public String getLieu() {
        return lieu;
    }

    public void setLieu(String lieu) {
        this.lieu = lieu;
    }
}
public interface ConcentrationsRepository extends JpaRepository<Concentration, Integer> {

    @Query("SELECT c FROM Concentration c WHERE c.minerai.id IN ('ni', 'co')")
    public List<Concentration> findStatistiques();
}
@Component
public class ReleveToNuagePointMapper {

    public NuagePoints releveToNuagePoint(List<Concentration> concentrations) {
        NuagePoints nuage = new NuagePoints(null, null);
        Map<Integer, Point> points = new HashMap<>();
        for (Concentration c : concentrations) {
            Point p = new Point();
            if (points.containsKey(c.getReleve().getId())) {
                p = points.get(c.getReleve().getId());
            }
            else {
                points.put(c.getReleve().getId(), p);
            }
            if (c.getMinerai().getId().equals("ni")) {
                p.setX(c.getValeur());
            }
            else {
                p.setY(c.getValeur());
            }
            points.remove(c.getReleve().getId());
            points.put(c.getReleve().getId(), p);
        }
        for (Point p : points.values()) {
            nuage.add(p);
        }
        return nuage;
    }
}
@Component
public class GenerationRegressionService {

    @Autowired
    private ConcentrationsRepository concentrationsRepository;
    @Autowired
    private ReleveToNuagePointMapper releveToNuagePointMapper;
    @Autowired
    private RegressionLineaireService regressionLineaireService;

    public ResultatRegression genererRegression() throws StatistiqueException {
        List<Concentration> c = concentrationsRepository.findStatistiques();
        NuagePoints nuage = releveToNuagePointMapper.releveToNuagePoint(c);
        ResultatRegression res = regressionLineaireService.calculer(nuage);
        res.setNuage(nuage);
        return res;
    }
}
@ActiveProfiles("test")
public class RegressionLineaireServiceTest extends AbstractTest {

    @Autowired
    private RegressionLineaireService regressionLineaireService;

    @Test
    public void testerMoyenne() {
        try {
            NuagePoints nuage = new NuagePoints(null, null);
            nuage.add(new Point(3, 3));
            nuage.add(new Point(4, 5));
            nuage.add(new Point(5, 5));
            nuage.add(new Point(6, 6));
            nuage.add(new Point(7, 5));
            nuage.add(new Point(8, 8));
            ResultatRegression res= regressionLineaireService.calculer(nuage);
            Assert.assertEquals(1.24d, res.getB0(), 0.1d);
            Assert.assertEquals(0.7d, res.getB1(), 0.1d);
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}
@ActiveProfiles("test")
public class StatistiquesServiceTest extends AbstractTest {

    @Autowired
    private StatistiquesService statistiquesService;

    @Test
    public void testerMoyenne() {
        Assert.assertEquals(5.7d, statistiquesService.moyenne(new Vecteur(3, 4, 5, 6, 7, 9)), 0.1d);
    }

    @Test
    public void testerSomme() {
        Assert.assertEquals(34d, statistiquesService.somme(new Vecteur(3, 4, 5, 6, 7, 9)), 0.1d);
    }

    @Test
    public void testerVariance() {
        Assert.assertEquals(3.89d, statistiquesService.variance(new Vecteur(3, 4, 5, 6, 7, 9)), 0.1d);
    }

    @Test
    public void testerCovariance() {
        try {
            Assert.assertEquals(4.5d, statistiquesService.covariance(new Vecteur(3, 4, 5, 6, 7, 9), new Vecteur(2, 4, 5, 9, 7, 9)), 0.1d);
        }
        catch (StatistiqueException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
    
    @Test
    public void testerCorrelation() {
        try {
            Assert.assertEquals(0.17d, statistiquesService.correlation(new Vecteur(3, 4, 5, 6, 7, 9), new Vecteur(2, 4, 5, 9, 7, 9)), 0.1d);
        }
        catch (StatistiqueException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}
@ActiveProfiles("test")
public class VecteursServiceTest extends AbstractTest {

    @Autowired
    private VecteursService vecteursService;

    @Test
    public void testerTransposition() {
        Vecteur v = new Vecteur(2, 3);
        v.add(2d);
        v.add(3d);
        Vecteur res = vecteursService.transposer(v);
        Assert.assertNotEquals(v.isColonne(), res.isColonne());
    }

    @Test
    public void testerAjout() {
        try {
            Vecteur res = vecteursService.ajouter(new Vecteur(2, 3), new Vecteur(1, 1));
            Assert.assertEquals(Double.valueOf(3), res.get(0));
            Assert.assertEquals(Double.valueOf(4), res.get(1));
        }
        catch (StatistiqueException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerMultiplier() {
        try {
            Vecteur res = vecteursService.multiplier(new Vecteur(2, 3), 2);
            Assert.assertEquals(Double.valueOf(4), res.get(0));
            Assert.assertEquals(Double.valueOf(6), res.get(1));
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerMin() {
        try {
            Assert.assertEquals(2d, vecteursService.min(new Vecteur(2, 3)), 0.1d);
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerMax() {
        try {
            Assert.assertEquals(3d, vecteursService.max(new Vecteur(2, 3)), 0.1d);
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void testerProduit() {
        try {
            Vecteur v2 = new Vecteur(2, 2);
            Vecteur v = new Vecteur(2, 3);
            v.setColonne(!v.isColonne());
            Double res = vecteursService.produit(v, v2);
            Assert.assertEquals(Double.valueOf(10), res);
        }
        catch (StatistiqueException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}
@ActiveProfiles("test")
public class GenerationRegressionServiceTest extends AbstractTestBdd {

    @Autowired
    private GenerationRegressionService generationRegressionService;

    @Test
    public void testerGenerationRegression() {
        try {
            ResultatRegression res = generationRegressionService.genererRegression();
            Assert.assertEquals(2.87d, res.getB0(), 0.1d);
        }
        catch (StatistiqueException e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}
@ActiveProfiles("test")
public class ReleveToNuagePointMapperTest extends AbstractTest {

    @Autowired
    private ReleveToNuagePointMapper releveToNuagePointMapper;

    @Test
    public void testerMapping() {
        List<Concentration> concentrations = new ArrayList<>();
        Releve r = new Releve();
        Minerai ni = new Minerai();
        ni.setId("ni");
        Minerai co = new Minerai();
        co.setId("co");
        r.setId(1);
        Concentration c1 = new Concentration();
        c1.setReleve(r);
        c1.setMinerai(ni);
        c1.setValeur(2d);
        Concentration c2 = new Concentration();
        c2.setReleve(r);
        c2.setMinerai(ni);
        c2.setValeur(3d);
        concentrations.add(c1);
        concentrations.add(c2);
        NuagePoints n = releveToNuagePointMapper.releveToNuagePoint(concentrations);
        Assert.assertEquals(1, n.getX().size());
    }
}
@ActiveProfiles("test")
public class ReleveRepositoryTest extends AbstractTestBdd {

    @Autowired
    private ConcentrationsRepository relevesRepository;

    @Test
    public void testerReleveRepository() {
        try {
            relevesRepository.findStatistiques();
        }
        catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}

Bilan de l'exercice 2

Il n'y a pas de solution miracle qui permette de tester entièrement et sans risque de régression les applications, il est cependant possible de réaliser un travail de test intéressant et utile.

Dans notre cas, la couverture de test est vraiment faible (22,7%), et pourtant, ces tests sont tout à fait utiles. Il ne faut pas à tout prix chercher la couverture de test, mais chercher leur utilité.

Couverture de test