[JAVA] [Pour les super débutants] Super introduction à DBUnit

introduction

Cette fois, c'est un grand succès dans le développement de programmes! Présentation de l'utilisation de "DBUnit", un framework qui peut être utilisé dans les tests unitaires.

DBUnit est l'un des frameworks de test utilisés en Java, mais d'après le sentiment que j'ai étudié, il semblait que les articles étaient vieux et qu'il y avait peu de sites Web qui étaient complètement suffisants, c'était donc un rappel de l'auteur. , Je vais le résumer ici pour le partager avec ceux qui liront cet article.

Il y a de nombreuses personnes aimables qui ont publié les documents sur le Web à titre de référence, mais orz

1. Qu'est-ce que DBUnit?

Comme mentionné précédemment, DBUnit est l'un des frameworks de test de programme Java. Lorsque vous entendez le framework de test de mots, vous pouvez imaginer XUnit. Étant donné que la cible de cette fois est un programme implémenté en Java, JUnit est souvent utilisé, mais DBUnit est également utilisé avec JUnit.

Dans JUnit, vous pouvez vérifier la valeur de retour de la méthode traitée dans le programme et le paramètre passé, mais dans DBUnit, vous pouvez vérifier la valeur mise à jour dans le DB. De plus, les données de test peuvent être chargées dans le DB avant le début du test.

Il semble qu'il y ait beaucoup de gens qui ne connaissent pas l'existence elle-même, mais si vous pouvez la maîtriser, le test unitaire (ci-après, UT) sera beaucoup "plus facile et plus précis", donc si vous êtes intéressé, veuillez lire cet article jusqu'au bout. ..

2. Créez un projet de test

Commencez par créer un projet de test à utiliser pour tester DBUnit. Tester le framework de test semble un peu étrange, mais je m'en fiche.

J'ai déjà étudié Maven et maintenant je pousse Maven, donc ce projet de test sera construit avec Maven et Eclipse.

Pour la construction du projet Maven, je vous serais reconnaissant de bien vouloir vous référer à l'article ici que j'ai écrit plus tôt. Modifiez le nom et la configuration du projet à votre guise. Cette fois, je l'ai nommé "dbunit-test" et j'ai ajouté les bibliothèques suivantes en tant que dépendances.

Décrivez l'arborescence du projet et les paramètres de pom.xml.

Arborescence du projet


Racine du projet
├─src
│  ├─main
│  │  ├─java
│  │  │  └─test
│  │  │      └─main
│  │  │              TestMain.java
│  │  │
│  │  └─resources
│  │
│  └─test
│      ├─java
│      │  └─test
│      │      └─main
│      │              TestMainTest.java
│      │
│      └─resources
│              logback.xml
│
├─target
│  ├─classes
│  │  │  logback.xml
│  │  │
│  │  └─test
│  │      └─main
│  │              TestMain.class
│  │
│  └─test-classes
│      │  logback.xml
│      │
│      └─test
│          └─main
│                  TestMainTest.class
│
├─data
│      Before.xml		---Données de préparation
│      After.xml		---Données de vérification des résultats
└─pom.xml

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>dbunit.test</groupId>
  <artifactId>dbunit-test</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <!--Paramètres de code de caractère et de version Java-->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <!--Paramètres de l'enregistreur-->
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <!--
Étant donné qu'Oracle est cette fois utilisé pour la base de données, le pilote JDBC utilisé est celui d'Oracle.
Le pilote JDBC d'Oracle ne se trouve pas dans le référentiel central de Maven, utilisez donc celui installé dans votre référentiel local.
Pas directement lié à DBUnit, mais comment installer la bibliothèque dans un référentiel local
Enfin, je vais le décrire comme une référence.
      -->
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc7</artifactId>
      <version>11.2.0</version>
    </dependency>

    <!--Bibliothèque utilisée pour les tests-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.dbunit</groupId>
      <artifactId>dbunit</artifactId>
      <!--Dernière au moment de la rédaction de l'article-->
      <version>2.5.3</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.6.1</version>
        <configuration>
          <source>${java.version}</source>
          <target>${java.version}</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Cet article utilise Maven, mais vous n'êtes pas obligé d'être Maven tant que vous ajoutez JUnit et DBUnit à votre chemin de génération. JUnit peut être un plug-in Eclipse, modifiez donc les paramètres du projet à votre guise.

3. Construisez une table de test

Construisez une table de test à implémenter dans le programme de test. Cette fois, nous utiliserons la base de données et l'utilisateur SCOTT traditionnel qui sont automatiquement générés lors de l'installation d'Oracle. Le tableau utilisé est également le tableau EMP, qui est familier dans les manuels. Si vous avez créé la valeur par défaut avec l'installation d'Oracle, elle est créée automatiquement depuis le début, mais écrivez le DDL de la table.

Tableau EMP DDL


CREATE TABLE SCOTT.EMP (
  ID            NUMBER        NOT NULL,
  NAME          VARCHAR2(255) NOT NULL,
  AGE           NUMBER        NOT NULL,
  SALARY        NUMBER,
  JOB_TYPE      VARCHAR2(20),
  HIREDATE      TIMESTAMP(6),
  DEPARTMENT_ID NUMBER
);

Nous allons construire la table, mais cette fois, nous voulons charger les données de test en tant que DBUnit, alors laissez la table vide.

4. Mise en œuvre du programme de test

Maintenant que vous avez construit le squelette du projet, implémentez le programme de test. C'est juste un exemple, donc c'est un programme qui met à jour uniquement les enregistrements dans une table.

4.1. Mise en œuvre du programme testé

L'exemple de programme à tester est "TestMain.java". Le programme de test utilise Logback, mais c'est un bonus donc vous n'avez pas besoin de l'utiliser. Si vous utilisez logback, vous pouvez voir le journal de débogage de DBUnit, ce qui est très pratique.

TestMain.java


package test.main;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *Une classe avec main pour les tests DBUnit.
 * @author tarosa0001
 */
public class TestMain {
  /**Enregistreur*/
  private static Logger logger = LoggerFactory.getLogger(TestMain.class);

  /**SQL à exécuter*/
  private static final String SQL
      = " update "
      + " 		EMP "
      + " 	set "
      + "		name = 'tiger' "
      + " 	where "
      + " 		id = 1";

  /**
   * @param args
   */
  public static void main(String[] args) {
    logger.info("Commencer le traitement");

    // ---------------------------------
    //Mettre à jour la base de données
    // ---------------------------------

    try(Connection conn = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:ORCL", "scott", "tiger");
        PreparedStatement stmt = conn.prepareStatement(SQL);
        ) {
      conn.setAutoCommit(false);
      int i = stmt.executeUpdate();

      //Afficher le nombre de traitements
      logger.info("Nombre de dossiers traités:[" + i + "]");

      conn.commit();
    } catch(Exception e) {
      logger.error("Erreur", e);
    }

    logger.info("Sortie de traitement");
  }
}

4.2. Implémentation de la source de test JUnit + DBUnit

De là, c'est la production. Implémentez une source de test à l'aide de JUnit et DBUnit. La cible d'implémentation est "TestMainTest.class". Décrit le contenu du programme de test. Ici, les données de test sont chargées dans le prétraitement et les données de résultat sont vérifiées par la méthode de test, mais le contenu de chaque donnée sera décrit ultérieurement.

TestMainTest.class


package test.main;

import static org.junit.Assert.*;

import java.io.File;

import org.dbunit.Assertion;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * [Classe d'essai]<br>
 *Test à l'aide de JUnit et DBUnit.<br>
 * <br>
 * @author tarosa0001
 */
public class TestMainTest {
  /**Enregistreur*/
  private Logger logger = LoggerFactory.getLogger(TestMain.class);

  /**Testeur DBUnit*/
  private static IDatabaseTester databaseTester;

  /**
   * [Prétraitement]<br>
   *Préparez les données avancées dans DB.<br>
   * <br>
   * @throws java.lang.Exception
   */
  @Before
  public void setUp() throws Exception {
    logger.info("Lancer le prétraitement");

    // --------------------------------------
    //INSÉRER des données de préparation
    // --------------------------------------
    //Spécifiez le schéma pour INSERT des données de préparation
    databaseTester = new JdbcDatabaseTester("oracle.jdbc.driver.OracleDriver",
        "jdbc:oracle:thin:@localhost:1521:ORCL", "scott", "tiger", "scott");

    // --------------------------------------
    //Entrée de données de test
    // --------------------------------------
    IDataSet dataSet = new FlatXmlDataSetBuilder().build(new File("./data/Before.xml"));
    databaseTester.setDataSet(dataSet);
    //Préparer les données de préparation en SUPPRIMER → INSÉRER
    databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
        databaseTester.onSetup();

    logger.info("Pré-traitement terminé");
  }

  /**
   * [Post-traitement]<br>
   *Effectuer un post-traitement post-test.<br>
   *Nettoyez l'unité DB.<br>
   * <br>
   * @throws java.lang.Exception
   */
  @After
  public void tearDown() throws Exception {
    databaseTester.setTearDownOperation(DatabaseOperation.NONE);
    databaseTester.onTearDown();
  }

  /**
   * [tester]<br>
   *Utilisez DBUnit pour vérifier le résultat de la mise à jour de la base de données.<br>
   */
  @Test
  public void test() {
    logger.info("JUnit +Commencez les tests avec DBUnit.");

    TestMain.main(null);

    try {
      // ----------------------------------
      //Contrôle des données après la mise à jour avec DBUnit
      // ----------------------------------
      IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File("./data/After.xml"));
      ITable expectedTable = expectedDataSet.getTable("EMP");

      IDataSet databaseDataSet = databaseTester.getConnection().createDataSet();
      ITable actualTable = databaseDataSet.getTable("EMP");

      //L'assertion du temps échoue presque certainement, alors excluez-la de la vérification
      ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(
          expectedTable, new String[]{"HIREDATE"});
      ITable filteredActualTable;
      filteredActualTable = DefaultColumnFilter.excludedColumnsTable(
          actualTable, new String[]{"HIREDATE"});

      // ---------------------------------------------------------------
      //Utilisez l'assertion DBUnit au lieu de JUnit pour valider les résultats de la mise à jour
      // ---------------------------------------------------------------
      Assertion.assertEquals(filteredExpectedTable, filteredActualTable);
    } catch (Exception e) {
      logger.error("Erreur", e);
      fail("Le test a échoué avec une erreur inattendue.");
    }

    logger.info("JUnit +Commencez les tests avec DBUnit.");
  }
}

4.3. Chargement des données de préparation Utilisez DBUnit pour charger des données pré-préparées. Les données préparatoires et les données de vérification des résultats utilisent le XML.

Je déteste XML, donc je veux essentiellement créer quelque chose comme ça dans Excel ou CSV, mais en CSV, vous ne pouvez définir qu'un fichier et une table, et dans Excel, le nom de la feuille est pour le nom de la table. Les données de test DBUnit utilisent XML car il existe des facteurs incommodes tels que le manque de longueur.

Décrit le contenu XML des données de préparation et les données de vérification des résultats. Les données de préparation sont "Before.xml" et les données de vérification du résultat sont "After.xml".

Before.xml


<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <!--
Les données numériques sont également incluses dans XML pour les ensembles de données""Entourez de
Les dates de type DATE et TIMESTAMP sont "-Précisez en vous connectant
  -->
  <EMP
      ID="1"
      NAME="scott"
      AGE="22"
      SALARY="200000"
      JOB_TYPE="employee"
      HIREDATE="2017-01-01 12:34:56"
      DEPARTMENT_ID="1"
  />
</dataset>

After.xml


<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <!--
La date n'est pas sujette à vérification, mais je la listerai pour le moment.
Entrez une date différente pour vérifier qu'elle a été filtrée.
  -->
  <EMP
      ID="1"
      NAME="tiger"
      AGE="22"
      SALARY="200000"
      JOB_TYPE="employee"
      HIREDATE="2017-12-31 24:12:36"
      DEPARTMENT_ID="1"
  />
</dataset>

Dans ce qui précède, la date et l'heure du type DATE sont fixes, mais il est également possible de définir la date et l'heure actuelles comme SYSDATE. Dans ce cas, [ici](https://hondou.homedns.org/pukiwiki/pukiwiki.php?xUnit%20DbUnit%20%A4%C7%A1%A2%BD%E9%B4%FC%A5%C7% A1% BC% A5% BF% A4% CB% B8% BD% BA% DF% BB% FE% B9% EF% A4% F2% C0% DF% C4% EA% A4% B7% A4% BF% A4% Veuillez voir A4) pour référence.

5. Exécutez le programme de test

Maintenant que nous avons terminé le travail préparatoire, exécutons le programme de test. Cependant, puisque nous voulons voir les changements dans la base de données, enregistrons l'état avant l'exécution.

5.1. État de pré-exécution

La table de pré-exécution contient des enregistrements vides. Peu importe qu'il y ait un enregistrement, mais nous partirons de l'état où il est facile à comprendre.

■ État de la table avant exécution picture1.JPG

5.2. Exécutez le test

Maintenant, exécutons le test. Exécutez le projet construit en tant que test JUnit. Le résultat est le suivant, je pense qu'il s'est terminé normalement sans aucune erreur.

■ Résultat de l'exécution JUnit picture2.JPG

Vous pouvez maintenant créer et exécuter le test avec JUnit + DBUnit. Cette fois, nous n'avons préparé qu'une seule donnée de préparation et une seule donnée de résultat, mais si nous préparons plusieurs données et modifions le XML à lire pour chaque test, de nouvelles données seront automatiquement chargées pour chaque cas de test, et nous nous y attendions. Les résultats peuvent être vérifiés automatiquement.

6. Test de démontage

Jusqu'à présent, nous avons présenté comment effectuer des tests automatiques avec JUnit + DBUnit, mais qu'en est-il? Lorsqu'on leur demande si les tests automatisés sont bons, ce n'est pas le cas, mais il est assez compliqué de refaire le test encore et encore et d'obtenir les résultats des tests encore et encore, donc de nombreux tests peuvent être automatisés. Dans certains cas, ce sera un gros avantage.

Jusqu'à présent, nous avons seulement parlé d'exécuter DBUnit à la hâte, mais à partir de maintenant, nous décomposerons les tests d'exécution étape par étape. Plus précisément, nous le décomposerons en étapes suivantes, et à chaque étape, nous examinerons le comportement du programme et l'état de la base de données.

  1. Chargement des données de préparation préalable
  2. Statut dans le programme sous test
  3. Vérification des résultats des tests

Voyons maintenant comment le programme de test fonctionne lors de l'exécution du débogage sur Eclipse.

6.1. Chargement des données de préparation préalable

Commençons par vérifier le mouvement lors du chargement des données de préparation par DBUnit.

6.1.1. État de pré-exécution

La table a été vidée une fois.

■ État de la table avant exécution picture1.JPG

6.1.2. Immédiatement après la fin du prétraitement

Immédiatement après la fin du prétraitement, vous pouvez voir que les données lues à partir de Before.xml sont exactement incluses. Étant donné que le programme cible de test met à jour la base de données pendant le traitement, il s'agit d'un schéma directeur qui ne fonctionne pas bien s'il n'y a pas d'enregistrements, mais il fonctionne normalement car il démarre dans un état où aucun enregistrement n'est inséré dans ce prétraitement. est.

■ Étapes d'exécution du programme picture4.jpg

■ État de la base de données picture3.jpg

6.1.3. État pendant le programme de test

Voyons comment le programme de test fonctionne. Puisque l'enregistrement à mettre à jour est inséré dans le prétraitement, vous pouvez voir que UPDATE a fini de s'exécuter normalement et que l'état du DB a changé.

■ Avant d'exécuter UPDATE picture5.jpg

■ Après avoir exécuté UPDATE a4886ebe-6a13-abf8-1d56-8a5b4f694f3f.jpeg

■ État de la base de données après exécution picture7.jpg

6.1.4. Vérification des résultats des essais

Enfin, jetons un œil à la vérification des résultats des tests. Étant donné que l'état de la base de données est celui attendu, l'assertion de DBUnit n'échoue pas le test et le processus d'assertion est exécuté normalement. Le résultat final après l'exécution de l'assertion est comme décrit ci-dessus.

■ Avant d'exécuter l'assertion picture8.jpg

■ Après avoir exécuté l'assertion picture9.jpg

7. Enfin

Ceci est le dernier de ce long article. J'introduis DBunit depuis longtemps, mais qu'en est-il? DBUnit est un outil d'automatisation des tests unitaires, mais s'il est utilisé correctement, il peut être un outil utile pour charger des données de test autres que des tests unitaires.

Cependant, bien que cela soit pratique, cela demande beaucoup de temps et d'efforts, de sorte qu'il ne peut pas être utilisé tout le temps. Dans cet article, il n'y avait qu'une seule donnée de test, donc ce n'était pas trop de problèmes, mais si vous avez beaucoup de tables à préparer ou un programme qui traite beaucoup d'enregistrements à la fois, automatisons la vérification. Cependant, c'est beaucoup de travail car une énorme quantité de données de test doit être préparée.

Dans cet esprit, si vous l'utilisez bien, je ne serais pas si heureux.

8. Référence

Je décrirai la référence qui n'a pas été décrite directement dans cet article. En écrivant l'article, j'ai fait référence au site Web suivant. Merci aux responsables et aux auteurs pour la rédaction de l'article.

■ Comment installer la bibliothèque dans le référentiel local de Maven http://sinsengumi.net/blog/2012/12/maven%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%A7%E6%8F%90%E4%BE%9B%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%82%B5%E3%83%BC%E3%83%89%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3jar/

■ Avec DBUnit http://jyukutyo.hatenablog.com/entry/20060630/1151636345

Recommended Posts

[Pour les super débutants] Super introduction à DBUnit
[Pour les super débutants] Ant super introduction
[Pour les super débutants] Super introduction à Maven
[Pour les super débutants] Super introduction à Mirage SQL
[Pour les super débutants] Struts2 Super Primer - Édition 2018
[Pour les super super débutants] Qu'est-ce que l'orientation objet?
Super introduction de Ractor
Introduction du livre: Spring Boot Livre de référence recommandé pour les débutants!
[Pour les débutants] J'ai essayé d'utiliser DBUnit avec Eclipse
[Pour les super débutants] Comment utiliser l'autofocus: vrai
[Introduction à Java] Bases de l'arithmétique Java (pour les débutants)
Utilisons Java New FileIO! (Introduction, pour les débutants)
Introduction super facile Groovy
Introduction à Java pour les débutants Connaissance de base du langage Java ①
Comment utiliser GitHub pour les super débutants (développement d'équipe)
Exécution de débogage Java [pour les débutants Java]
[Java] Instruction de base pour les débutants
(Pour les débutants) [Rails] Installer Devise
Plus utilisable Enumerable pour les débutants
Java pour les débutants, masquage des données
Application Java pour les débutants: stream
Mémorandum d'arbre de bisection pour les débutants (1)
[Pour les débutants] Résumé du constructeur java
[Rails] Introduction de Rubocop par les débutants
Les débutants jouent à des jeux Janken en Java
Construction d'environnement avec Docker pour les débutants
Java pour les débutants, les expressions et les opérateurs 1
[Pour les débutants] Exécutez Selenium sur Java
Liens pour créer des applications Android (pour les débutants)
Java pour les débutants, les expressions et les opérateurs 2
[Folio LSP] Roughly Docker (pour les débutants)
Notes pour les débutants en développement d'applications Android
[Super Introduction] À propos des symboles dans Ruby
Cours orienté objet pour débutants envoyé par des débutants
Utiliser DBUnit pour le test Spring Boot
Démarrer heroku via heroku CLI (pour les débutants)
Introduction à la programmation pour les étudiants du Collège: Introduction
Méthode d'apprentissage recommandée pour les débutants en programmation
[Pour les débutants en Java] À propos de la gestion des exceptions
Classes et instances Java pour les débutants
(Pour les super débutants) Getter / setter et propriété pour penser en langage D