[Java] Exemple de cas de test JUnit 4

Je ne connais pas @Rule

Êtes-vous en train d'écrire JUnit? Tu écris. J'écris aussi. J'ai beaucoup de projets pour les bureaux du gouvernement, mais l'environnement des bureaux du gouvernement, des finances et d'autres projets qui travaillent dur est généralement vieux! Il y a toujours Java 6 et ainsi de suite. …… À partir de 2019, même des projets complètement nouveaux sont généralement réalisés avec Java 1.6 + Spring 1.x, je pense donc que c'est un vrai projet pour les agences gouvernementales et les entreprises célèbres (autres que les sociétés informatiques): joie: Quand je l'ai touché pour la première fois, c'était toujours JUnit3, mais maintenant JUnit4 est le courant dominant. Je n'ai pas vu JUnit 5 en entreprise (projets d'entreprises) car je ne prends pas la peine de changer le cadre de test dans le projet existant.

Mais je ne suis toujours pas habitué à JUnit 4 ... C'est pourquoi j'ai noté les modèles que j'écris souvent sur l'annotation @Rule que j'écris en recherchant le code des gens à chaque fois. En tant qu'objet, cela ressemble à ceci.

--Accumuler sans s'arrêter lorsqu'une erreur d'assertion se produit (Error Collector)

Lors de l'utilisation de PowerMock

Je l'ai un peu mentionné dans [Supplément 2](#Supplement 2), mais la compatibilité entre PowerMock et @Rule n'est pas très bonne. PowerMockRule de PowerMock ne peut pas être utilisé, reconnaissance que la classe est @RunWith annotation (@RunWith (PowerMockRunner.class)). Ensuite, si vous obtenez une erreur d'exécution non d'erreur de compilation oui (lié à PowerMock, ou l'objet avec @Rule devient nul ou ne fonctionne pas bien), vous devez abandonner @Rule ou PowerMock. Cela peut être résolu en fonction de la combinaison de versions, mais comme l'entreprise est une version fixe, les essais et erreurs sont impossibles, je suis donc désolé de ne pas avoir atteint la bonne réponse. En outre, si vous vous moquez du constructeur avec PowerMock, il y a un problème en ce que la couverture ne peut pas être obtenue avec EclEmma. (Cela peut être résolu en fonction de la combinaison de versions)

Exemple de code

Cible de test

Sample.java


public class Sample {
	public static boolean isEmpty(String value) {
		return (value == null || "".equals(value)) ? true : false;
	}

	public static int parseInt(String value) throws Exception {
		try {
			return Integer.parseInt(value);
		} catch (NumberFormatException e) {
			throw new Exception("Échec de la conversion", e);
		}
	}
}

Code de test

Si le réglage ou l'assertion fictive est compliqué, la méthode est coupée pour chaque cas, mais dans le cas de test de la méthode d'utilité statique à usage général, plusieurs cas sont exécutés par une méthode de test de cette manière. Lorsque l'argument est une carte, la méthode privée avec une chaîne séparée par / comme argument est coupée et convertie en carte avant de passer. Un groupe qui coupe souvent les méthodes privées même dans les classes de test.

SampleTest.java


import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.text.DecimalFormat;
import java.text.MessageFormat;

import org.hamcrest.core.IsInstanceOf;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.hamcrest.Matcher;

public class SampleTest {
	//Accumulation d'erreurs d'assertion
	@Rule
	public ErrorCollector errs = new ErrorCollector();
	//Obtenir le nom de la méthode de test
	@Rule
	public TestName name = new TestName();
	//Paramètre de contenu d'assertion d'exception
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	//Sortie du message de début / fin
	@Rule
	public TestWatcher watcher = new TestWatcher() {
		@Override
		protected void starting(final Description desc) {
			System.out.println(MessageFormat.format("Test start. : {0}", desc));
		}

		@Override
		protected void succeeded(final Description desc) {
			System.out.println(MessageFormat.format("Test succeeded. : {0}", desc));
		}

		@Override
		protected void failed(final Throwable e, final Description desc) {
			System.err.println(MessageFormat.format("Test failed. : {0} \r\n*** Exception : {1}.", desc, e.getMessage()));
		}

		@Override
		protected void finished(final Description desc) {
			System.out.println(MessageFormat.format("Test Finished. : {0}", desc));
		}
	};

	@Test
	public void test_isEmpty() {
		String[][] args = new String[][]{
			new String[]{null, "true"},
			new String[]{"", "true"},
			new String[]{"ABC", "false"},
		};

		int i = 1;
		for (String[] arg : args) {
			//Affirmer une erreur
  			this.errs.checkThat(this.getAssertMsg(i++), 
  					Sample.isEmpty(arg[0]), is(Boolean.valueOf(arg[1])));
		}
	}

	@Test
	public void test_parseInt_Système anormal() throws Exception {
		//Affirmer une exception levée
		this.thrown.expect(Exception.class);
		this.thrown.expectMessage("Échec de la conversion");
		this.thrown.expectCause(IsInstanceOf.<Throwable>instanceOf(NumberFormatException.class));

		Sample.parseInt("AAA");
	}

	private String getAssertMsg(int idx) {
		//Obtenir le nom de la méthode de test
		return this.name.getMethodName() + " : " + new DecimalFormat("000").format(idx);
	}
}

ErrorCollector Si une erreur d'assertion se produit dans l'assertion à l'ancienne ○○, la méthode de test s'arrête là. Dans le cas d'une méthode de test qui répète l'exécution du test et l'assertion comme test_isEmpty () dans la source ci-dessus, si une erreur d'assertion se produit dans le premier cas, les résultats du deuxième cas et des suivants ne géreront pas la première erreur d'assertion. Je ne peux pas confirmer. En utilisant ErrorCollector, l'erreur d'assertion qui s'est produite sur le chemin est stockée et le traitement suivant est effectué. Vous pouvez voir les erreurs d'assert stockées dans le champ de suivi des pannes en sélectionnant la méthode de test dans la vue Eclipse JUnit.

TestName Utilisation recommandée en combinaison avec Error Collector. Par exemple, passez un message au premier argument de checkThat pour qu'il soit plus facile de comprendre où l'erreur d'assertion s'est produite. Dans la source ci-dessus, il est utilisé dans getAssertMsg (int idx). Voir [Supplément 1](#Supplement 1) pour un exemple d'obtention d'un nom de méthode de test qui n'utilise pas TestName.

ExpectedException L'assertion d'exception peut être écrite sous la forme @Test (attendu = Exception.class), mais cela ne valide que le type d'exception levé. Les messages et les exceptions de cause ne peuvent pas être vérifiés ... J'avais donc l'habitude de l'écrire dans try ~ catch, mais si vous pouvez utiliser @Rule, vous pouvez l'écrire plus rapidement. Dans la source ci-dessus, seul le type est vérifié pour l'exception de cause, mais vous pouvez également vérifier le message en même temps avec le sentiment suivant.

thrown.expectCause(allOf(
	instanceOf(NumberFormatException.class),
	hasProperty("message", is("Contenu du message"))));

Cependant, si ExpectedException.expectCause est une ancienne version, elle ne se compilera pas et vous aurez du mal, donc dans un tel cas, il vaut mieux abandonner et écrire avec try ~ catch. Quelqu'un qui reste coincé dans un projet existant sans mettre à jour la bibliothèque ... Si c'est JUnit 4.12 ou une version ultérieure, je pense que c'est OK pour écrire l'exemple. Cela n'a pas fonctionné avec 4.10 ...

TestWatcher Celui qui peut être utilisé avec Junit 4.11 ou version ultérieure. Vous pouvez écrire le processus à appeler avant l'exécution du test, lorsque les conditions préalables ne sont pas remplies, lorsque le test réussit, lorsque le test échoue et après la fin du test. Lorsque le prérequis n'est pas satisfait, il n'est pas écrit dans la source ci-dessus, mais il est «ignoré (AssumptionViolatedException, Description)». Je ne l'ai jamais utilisé. Dans la source ci-dessus, le journal est sorti sur la console, mais bien sûr, vous pouvez utiliser l'enregistreur pour sortir non seulement la console mais aussi comme vous le souhaitez. Il n'est pas décidé que ce soit pour la sortie du journal en premier lieu, alors je me demande si je peux utiliser ceci au lieu de @Before ou @After.

En ce qui concerne l'ordre d'exécution combiné avec @BeforeClass, @Before, @After, @AfterClass, il y avait un article qui a publié le résultat de la vérification, veuillez donc voir ci-dessous. Ordre d'exécution JUnit4 - journalumezucolor Avec cet ordre d'exécution, je pense personnellement que le traitement spécifié par TestWatcher concerne la sortie du journal. Par exemple, si vous devez supprimer un fichier à chaque fois que vous exécutez une méthode de test, écrivez-le avec @Before ...


Exemple d'exécution

Dans Eclipse, les cas où une erreur d'assertion se produit sont affichés ensemble dans la trace d'échec de la vue JUnit. C'est un résultat supposé qui provoque une erreur d'assertion, et le résultat exécuté à partir de la console ressemble à ceci. Au fait, lorsque vous l'exécutez à partir de la console, cela ressemble à ceci. J'ai mis le jar JUnit dans lib. java -cp ./;./lib/*; org.junit.runner.JUnitCore SampleTest

JUnit version 4.12
.Test start. : test_parseInt_Système anormal(SampleTest)
Test succeeded. : test_parseInt_Système anormal(SampleTest)
Test Finished. : test_parseInt_Système anormal(SampleTest)
.Test start. : test_isEmpty(SampleTest)
Test failed. : test_isEmpty(SampleTest)
*** Exception : There were 2 errors:
  java.lang.AssertionError(test_isEmpty : 002
Expected: is <true>
     but: was <false>)
  java.lang.AssertionError(test_isEmpty : 003
Expected: is <false>
     but: was <true>).
Test Finished. : test_isEmpty(SampleTest)
EE
Time: 0.043
There were 2 failures:
1) test_isEmpty(SampleTest)
java.lang.AssertionError: test_isEmpty : 002
Expected: is <true>
     but: was <false>
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
        at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
        at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
        at SampleTest.test_isEmpty(SampleTest.java:64)
~ Omis ~
2) test_isEmpty(SampleTest)
java.lang.AssertionError: test_isEmpty : 003
Expected: is <false>
     but: was <true>
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
        at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
        at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
        at SampleTest.test_isEmpty(SampleTest.java:64)
~ Omis ~

FAILURES!!!
Tests run: 2,  Failures: 2

Supplément 1

Le nom de la méthode de test peut également être obtenu à partir de la trace de pile. Il est tard. C'est une méthode connue depuis longtemps. Puisque getStackTrace [2] est la profondeur de la trace de la pile, il peut être nécessaire d'ajuster si la hiérarchie pour appeler la méthode de test dans JUnit n'est pas constante.

private String createAssertMsg(int idx) {
	return Thread.currentThread().getStackTrace[2].getMethodName() + " : " + new DecimalFormat("000").format(idx);
}

Supplément 2

Si vous écrivez @RunWith (PowerMockRunner.class) autour de @Rule pour utiliser PowerMock, vous ne pourrez peut-être pas l'utiliser. Ce n'est pas complètement inutile, TestName et ErrorCollector peuvent ou non fonctionner, mais pourquoi ... Au fait, j'ai pu utiliser les deux ci-dessus lorsque je voulais combiner la DI de Spring et l'annotation de classe était comme ça. Eh bien, l'exception ExpectedException de validation d'exception ne fonctionnait pas non plus dans ce cas, alors je l'ai écrite avec try ~ catch ...

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@PowerMockIgnore("javax.crypto.*")
public class SampleTest {

`@PowerMockIgnore (" javax.crypto. * ") ʻEst compatible avec ClassCastException, ce qui ne se produit normalement pas lors de l'utilisation de javax.crypto.Cipher avec une combinaison de Powermock et Spring. C'est un substitut à un mémorandum, alors prenez note.

Si vous utilisez PowerMock, vous ne pourrez peut-être pas exécuter uniquement une méthode de test spécifique, donc si cela se produit, ajoutez @ Ignore au lieu de @ Test, sauf pour la méthode de test que vous souhaitez vérifier. PowerMock augmente ce que vous pouvez faire, mais cela augmente également ce que vous ne pouvez pas faire, alors parfois je pense que c'est un peu na ... …… Mais c'est formidable de pouvoir se moquer de méthodes statiques… lorsque vous voulez provoquer une erreur avec l'API standard appelée dans la cible de test…

J'aimerais également écrire sur Rule Chain.

Recommended Posts

[Java] Exemple de cas de test JUnit 4
[Java] Tester des méthodes privées avec JUnit
Jugement des nombres premiers Java
Présentation du test Java automatisé avec JUnit 5 + Gradle
[Java] Comment tester s'il est nul dans JUnit
[CircleCI 2.0] [Java] [Maven] [JUnit] Agréger les résultats des tests JUnit avec CircleCI 2.0
Présentation des tests Java automatisés avec JUnit 5 + Apache Maven
Exemple d'utilisation de Java Enum
Lancement du test JUnit essayez quelque chose
Mémo simple de JUnit de java
Échantillon de bibliothèque de tests unitaires Java
Exemple de cycle de vie de servlet Java
Créer un cas de test
Faites un test unitaire avec Junit.
Obtenez le nom du scénario de test dans la classe de test JUnit
Tester l'API Web avec junit
Tester les méthodes privées dans JUnit
Programme de jugement des nombres premiers le plus rapide C # Java C ++
Collection de méthodes de code de test Java
Test de compétence Java 2018 pour les nouveaux arrivants - Principes de base-
Tester les méthodes privées dans JUnit
[JUnit] Tester l'exception levée
J'ai étudié Randoop, un générateur de classe de test JUnit pour Java.
[Java] Je souhaite tester l'entrée standard et la sortie standard avec JUnit
Implémenter un test piloté par table dans Java 14
Java Unit Test Library-Artery-ArValidator valide les objets
Exemple d'encodage et de décodage en Java
Jugement de la date actuelle de la bibliothèque de tests unitaires Java
Le test de paramétrage JUnit 5 est super pratique
Contenu du test de l'examen Java SE Bronze
Présentation des conseils Java de GreenMail à Junit5
Sortie du rapport de test JUnit dans Maven
Équivalence bibliothèque de tests unitaires Java-Artery / JUnit4-Array
Contrôleur de cadre de test Spring avec Junit