C'est ma première Qiita.
Taste of JUnit 5 au KANJAVA PARTY 2017 !!! tenu le 24 juin 2017 / junit5falsewei-jian) a été annoncé sous le titre. La version au moment de l'annonce était M4, mais il y a quelques changements dans M5, donc je vais vous suivre.
Cependant, puisque nous décrivons principalement JUnit Jupiter ici, veuillez vous référer au [Guide de l'utilisateur JUnit5] original (http://junit.org/junit5/docs/current/user-guide/) pour d'autres informations. Veuillez vous y référer.
Il est compatible avec Jigsaw. Jigsaw n'est pas très familier avec cela, alors je vais l'éviter.
@ ParameterizedTest
s'applique désormais uniquement aux méthodes de testC'est un peu déroutant. Écrivez le code.
Dans JUnit5M4, comme il y a un argument au moment du rappel de méthode de setup1, j'essaye d'appliquer le paramètre de @ ParameterrizedTest
, mais cela échoue car les types ne correspondent pas. Au lieu de cela, j'ai pu recevoir les paramètres de ParameterizedTest avec la méthode de rappel du cycle de vie comme setup2.
Dans JUnit5M5, le paramètre de @ ParameterizedTest
n'est plus appliqué à la méthode de rappel du cycle de vie, donc une erreur se produira lorsque setup2 est rappelé.
Cette correction vise à éviter des problèmes étranges lorsque @ ParameterizedTest
et normal @ Test
sont mélangés dans une classe de test.
ParameterizedNGTest.java
public class ParameterizedNGTest {
@BeforeEach
void setUp1(TestInfo info) {
}
@BeforeEach
void setUp2(String p1, String p2) {
System.out.println(p1 + p2);
}
@ParameterizedTest
@CsvSource({ "x, 1", "y, 2","z, 3" })
void testIt(String input, String expected) {
}
}
Soyez prudent lors de l'acquisition avec Maven ou Gradle.
Si la classe ne change pas, le nom de la classe est omis.
Ancienne API | Nouvelle API | Remarques |
---|---|---|
ParameterResolver#supports() | supportsParameter() | |
ParameterResolver#resolve() | resolveParameter() | |
ContainerExecutionCondition#evaluate() | ExecutionCondition#evaluateExecutionCondition() | ContainerExecutionCondition est aboli |
TestExecutionCondition#evaluate() | ExecutionCondition#evaluateExecutionCondition() | TestExecutionCondition est aboli |
TestExtensionContext#getTestException() | ExtensionContext#getExecutionException() | TestExtensionContext est aboli |
TestExtensionContext#getTestInstance() | ExtensionContext#getTestInstance() | TestExtensionContext est supprimé. La valeur de retour est également Object-> Optional<Object>Changer pour |
TestTemplateInvocationContextProvider#supports() | supportsTestTemplate() | |
TestTemplateInvocationContextProvider#resolve() | provideTestTemplateInvocationContexts() | |
ArgumentsProvider#arguments() | provideArguments() | |
ObjectArrayArguments#create() | Arguments#of() | ObjectArrayArguments obsolète |
@MethodSource#names |
value |
@ TestInstance
L'annotation @ TestInstance
est une annotation qui contrôle le cycle de vie d'une classe de test.
Jusqu'à présent, JUnit a matérialisé une classe de test à chaque fois qu'une méthode de test est exécutée.
TestInstancePerMethodTest.java
@RunWith(JUnitPlatform.class)
public class TestInstancePerMethodTest {
private int i = 0;
@Test
void test1(){System.out.println(i++);}
@Test
void test2(){System.out.println(i++);}
}
Résultat d'exécution.
0
0
Si vous donnez @ TestInstance
(et spécifiez Lifecycle.PER_CLASS), la classe de test ne sera matérialisée qu'une seule fois et le résultat sera différent.
TestInstancePerClassTest.java
@RunWith(JUnitPlatform.class)
@TestInstance(Lifecycle.PER_CLASS)
public class TestInstancePerClassTest {
private int i = 0;
@Test
void test1(){System.out.println(i++);}
@Test
void test2(){System.out.println(i++);}
}
Résultat d'exécution.
0
1
Accorder @ TestInstance
réduira le coût d'exécution de la classe de test, mais sachez que le processus d'initialisation doit être effectué dans @ BeforeEach
, pas au moment de l'initialisation.
Dans le même temps, il convient de noter que @ BeforeAll
et @ AfterAll
doivent être spécifiés d'une manière qui correspond à la matérialisation de la classe de test, ce qui rend l'histoire un peu compliquée.
En d'autres termes, dans le cas de la spécification de PER_CLASS, une erreur d'exécution se produira à moins que «@ BeforeAll» ou «@ AfterAll» ne soit annoté pour la méthode dynamique au lieu de la méthode statique.
De plus, si vous utilisez @ TestInstance
et @ Nested
ensemble, vous pourrez écrire @ BeforeAll
et @ AfterAll
même pour les classes de test imbriquées, il est donc préférable de les utiliser correctement. C'est possible.
Au fait, si vous utilisez @ TestInstance
, l'ordre des rappels du cycle de vie changera.
CallBackOrderTest.java Le résultat de sortie quand est exécuté tel quel est comme indiqué dans ①, mais quand @ TestInstance
est annoté, il est comme indiqué dans ②.
Je pense que c'est un problème, mais si vous y réfléchissez normalement, c'est le résultat.
①.
ExecutionCondition:false
beforeAll
postProcessTestInstance
ExecutionCondition:true
beforeEach
beforeTestExecution
foo
handleTestExecutionException
afterTestExecution
afterEach
afterAll
②.
postProcessTestInstance
ExecutionCondition:false
beforeAll
ExecutionCondition:true
beforeEach
beforeTestExecution
foo
handleTestExecutionException
afterTestExecution
afterEach
afterAll
Jusqu'à JUnit5M4, si une exception se produisait dans chaque exécutable sans assertAll, les exécutables suivants n'étaient pas évalués et le test était traité comme une erreur, mais après M5, des exceptions autres que des exceptions de liste noire se produisaient. Mais l'évaluation n'est plus interrompue. Les résultats d'exécution de M4 et M5 avec le code suivant sont indiqués ci-dessous.
AssertAllInExceptionTest.java
@RunWith(JUnitPlatform.class)
public class AssertAllInExceptionTest {
@Test
void thrownNullPointerException() {
assertAll(
() -> {throw new NullPointerException();},
() -> assertEquals(2, 3)
);
}
}
Résultat d'exécution de M4 | Résultat d'exécution de M5 |
---|---|
Vous pouvez voir que M4 est évalué comme une erreur, M5 est évalué comme un échec et le deuxième exécutable est évalué.
Plus tard, j'ai utilisé le mot «exception de la liste noire» plus tôt, mais il y a une question qui dit «qu'est-ce que c'est!». Dans le Guide de l'utilisateur, le mot «exception sur liste noire» a été mentionné dans la partie de l'annonce du changement de spécification d'assertAll et un endroit plus tard dans la Release Note de M2.
If the exception is a blacklisted exception such as an OutOfMemoryError, however, it will be rethrown.
La réponse à la question "Qu'est-ce que tel que (etc.) !! Qu'y a-t-il d'autre !!" n'était pas dans le guide de l'utilisateur mais dans le code.
[BlacklistedExceptions.java](https://github.com/junit-team/junit5/blob/r5.0.0-M4/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ Autant que je puisse voir le code appelé BlacklistedExceptions.java), il semble qu'il ne s'agisse actuellement que d'OutOfMemoryError.
@ TestTemplate
a été écritIl semble que ce soit de JUnit5M4, mais je l'ai oublié car il n'était pas écrit dans le guide de l'utilisateur. Il y avait une description dans le guide de l'utilisateur de JUnit5M5, donc j'écrirai un aperçu ici.
Je pense que «@ TestTemplate», comme «@ ParameterizedTest», sert à séparer le code de test et les données de test.
J'ai découvert en lisant le code, mais comme @ ParameterizedTest
est une annotation qui annote @ TestTemplate
, je pense que @ TestTemplate
ne devrait pas être un problème si vous n'êtes pas insatisfait de @ ParameterizedTest
. Je vais.
Ce qui suit est une version légèrement modifiée de la traduction automatique du Guide de l'utilisateur.
3.14. Test Templates
La méthode @ TestTemplate
est un modèle pour les cas de test, pas pour les cas de test réguliers.
Par conséquent, il est conçu pour être appelé plusieurs fois, en fonction du nombre de contextes d'appel renvoyés par le fournisseur inscrit.
Par conséquent, «@ TestTemplate» doit être utilisé avec une extension qui implémente TestTemplateInvocationContextProvider.
L'appel d'une méthode de modèle de test se comporte comme une exécution de méthode @ Test
normale et prend entièrement en charge les mêmes rappels et extensions de cycle de vie.
Pour des exemples d'utilisation, consultez Fourniture de contextes d'appel pour les modèles de test.
5.8. Providing Invocation Contexts for Test Templates
La méthode @ TestTemplate
ne peut être exécutée que si au moins un TestTemplateInvocationContextProvider est inscrit.
Chacun de ces fournisseurs fournit un flux d'instances TestTemplateInvocationContext.
Chaque contexte peut spécifier un nom d'affichage personnalisé et une liste d'extensions supplémentaires à utiliser uniquement lors du prochain appel à la méthode @ TestTemplate
.
L'exemple suivant décrit un modèle de test et montre comment inscrire et implémenter un TestTemplateInvocationContextProvider.
@TestTemplate
@ExtendWith(MyTestTemplateInvocationContextProvider.class)
void testTemplate(String parameter) {
assertEquals(3, parameter.length());
}
static class MyTestTemplateInvocationContextProvider implements TestTemplateInvocationContextProvider {
@Override
public boolean supportsTestTemplate(ExtensionContext context) {
return true;
}
@Override
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
return Stream.of(invocationContext("foo"), invocationContext("bar"));
}
private TestTemplateInvocationContext invocationContext(String parameter) {
return new TestTemplateInvocationContext() {
@Override
public String getDisplayName(int invocationIndex) {
return parameter;
}
@Override
public List<Extension> getAdditionalExtensions() {
return Collections.singletonList(new ParameterResolver() {
@Override
public boolean supportsParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) {
return parameterContext.getParameter().getType().equals(String.class);
}
@Override
public Object resolveParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) {
return parameter;
}
});
}
};
}
}
Dans cet exemple, le modèle de test est appelé deux fois. Le nom d'affichage de l'appel sera "foo" et "bar" spécifié dans le contexte de l'appel. Chaque appel enregistre un ParameterResolver personnalisé qui est utilisé pour résoudre les paramètres de méthode. Le résultat lors de l'utilisation de ConsoleLauncher est:
└─ testTemplate(String) ✔
├─ foo ✔
└─ bar ✔
L'API d'extension TestTemplateInvocationContextProvider vous permet principalement de préparer des instances de classe de test séparément avec différents contextes, par exemple, des paramètres différents, ou de créer plusieurs fois sans changer le contexte. Tests en - Principalement utilisé pour implémenter divers tests qui reposent sur des appels répétés à des méthodes similaires.
@ ParameterizedTest
accepte un tableau comme argumentPeut-être en réponse à ce problème, si vous essayez simplement de générer un objet tableau en Java, [Ljava.lang.String; @ 7c29daf3
Je pense que j'ai corrigé le fait que je ne pouvais pas voir le contenu.
Cependant, je n'ai pas pu le vérifier car je ne pouvais pas écrire un petit code pouvant être comparé entre M4 et M5. Excusez-moi.
@ EnumSource
a changéDans M4, les noms de @ EnumSource
spécifiaient le nom Enum à acquérir, mais avec l'ajout de la propriété appelée mode dans M5, la signification des informations passées aux noms peut être modifiée. C'était.
Mode | Signification des noms |
---|---|
INCLUDE | Valeur par défaut. S'applique uniquement au nom Enum spécifié dans les noms |
EXCLUDE | S'applique uniquement aux noms Enum non spécifiés dans les noms |
MATCH_ALL | S'applique uniquement aux noms Enum qui correspondent à toutes les expressions régulières spécifiées dans les noms |
MATCH_ANY | S'applique uniquement aux noms Enum qui correspondent à l'une des expressions régulières spécifiées dans les noms |
(Solo) Je ne veux pas trop l'utiliser w
@ MethodSource
a changéSpécifier DoubleStream, IntStream ou LongStream comme valeur de retour de la méthode spécifiée par @ MethodSource
ne provoque plus d'erreur.
@ TestFactory
a changé@ TestFactory
prend désormais en charge tous les conteneurs dynamiques imbriqués. Pour plus de détails, voir Dynamic Container et le résumé DynamicNode. Voir junit5 / docs / current / api / org / junit / jupiter / api / DynamicNode.html).
C'est ça. Un exemple est également joint au guide de l'utilisateur.
@TestFactory
Stream<DynamicNode> dynamicTestsWithContainers() {
return Stream.of("A", "B", "C")
.map(input -> dynamicContainer("Container " + input, Stream.of(
dynamicTest("not null", () -> assertNotNull(input)),
dynamicContainer("properties", Stream.of(
dynamicTest("length > 0", () -> assertTrue(input.length() > 0)),
dynamicTest("not empty", () -> assertFalse(input.isEmpty()))
))
)));
}
En regardant cela, je suis devenu en quelque sorte capable de voir comment utiliser Dynamic Test. DynamicTest est-il un mécanisme qui facilite la traduction des tests écrits par un DSL externe en un ensemble structuré de code de test afin qu'il puisse être signalé correctement?
@ BeforeAll
.À proprement parler, cela semble être une exception qui s'est produite dans la méthode annotant @ BeforeAll
ou la méthode d'implémentation de l'interface BeforeAllCallback.
Je n'étais pas au courant, mais cela signifie que je ne pouvais pas le faire avec M4. Je l'ai recherché, mais dans M4, l'argument pour AfterAllCallback # afterAll était ContainerExtensionContext, et il n'y avait pas d'API pour obtenir l'exception qui s'est produite. À partir de M5, ContainerExtensionContext a été intégré dans ExtensionContedxt, afin qu'il puisse être capturé.
Dans la même théorie, les exceptions levées par @ BeforeEach
peuvent être interceptées par l'interface d'implémentation AfterEachCallback. (Disponible sur M4)
Ouais, je ne suis pas sûr.
Extensions may now share state across top-level test classes by using the Store of the newly introduced engine-level ExtensionContext.
Cependant, il y a trop peu d'explications sur le Store ...
Seulement ceux qui sont différents / nouveaux de l'époque du document M4, mais ils sont comme suit.
Ancienne maturité | Nouvelle maturité | |
---|---|---|
@TestInstance |
- | Non décrit |
@TestTemplate |
- | Experimental |
Assertions#assertAll | Maintained | Experimental |
Assumptions#assumingThat | Maintained | Experimental |
DynamicContainer | - | Experimental |
DynamicNode | - | Experimental |
ExecutionCondition | - | Experimental |
TestTemplateInvocationContextProvider | - | Experimental |
TestTemplateInvocationContext | - | Experimental |
Fondamentalement, il n'y a que des omissions ou des ajouts, et cela peut ne pas changer pour chaque jalon.
En regardant les notes de publication du Guide de l'utilisateur, les principaux changements autres que le chapitre 7 sont les suivants.
Je n'ai pas eu beaucoup d'occasions d'annoncer récemment, donc je ferai de mon mieux pour JUnit 5. Nous espérons vous tenir au courant des changements, au moins jusqu'à la sortie officielle.
La prochaine étape est M6, mais à partir du 14 juillet 2017, sa sortie est prévue le 16 juillet 2017 et la progression semble être de 42%, elle sera donc probablement retardée w
Recommended Posts