3.16. Dynamic Tests

The standard @Test annotation in JUnit Jupiter described in Annotations is very similar to the @Test annotation in JUnit 4. Both describe methods that implement test cases. These test cases are static in the sense that they are fully specified at compile time, and their behavior cannot be changed by anything happening at runtime. Assumptions provide a basic form of dynamic behavior but are intentionally rather limited in their expressiveness.

In addition to these standard tests a completely new kind of test programming model has been introduced in JUnit Jupiter. This new kind of test is a dynamic test which is generated at runtime by a factory method that is annotated with @TestFactory.

In contrast to @Test methods, a @TestFactory method is not itself a test case but rather a factory for test cases. Thus, a dynamic test is the product of a factory. Technically speaking, a @TestFactory method must return a StreamCollectionIterableIterator, or array of DynamicNode instances. Instantiable subclasses of DynamicNode are DynamicContainer and DynamicTestDynamicContainer instances are composed of a display name and a list of dynamic child nodes, enabling the creation of arbitrarily nested hierarchies of dynamic nodes. DynamicTest instances will be executed lazily, enabling dynamic and even non-deterministic generation of test cases.

Any Stream returned by a @TestFactory will be properly closed by calling stream.close(), making it safe to use a resource such as Files.lines().

As with @Test methods, @TestFactory methods must not be private or static and may optionally declare parameters to be resolved by ParameterResolvers.

DynamicTest is a test case generated at runtime. It is composed of a display name and an ExecutableExecutable is a @FunctionalInterface which means that the implementations of dynamic tests can be provided as lambda expressions or method references.

Dynamic Test Lifecycle
The execution lifecycle of a dynamic test is quite different than it is for a standard @Test case. Specifically, there are no lifecycle callbacks for individual dynamic tests. This means that @BeforeEach and @AfterEach methods and their corresponding extension callbacks are executed for the @TestFactorymethod but not for each dynamic test. In other words, if you access fields from the test instance within a lambda expression for a dynamic test, those fields will not be reset by callback methods or extensions between the execution of individual dynamic tests generated by the same @TestFactory method.

As of JUnit Jupiter 5.3.2, dynamic tests must always be created by factory methods; however, this might be complemented by a registration facility in a later release.

Dynamic tests are currently an experimental feature. Consult the table in Experimental APIs for details.




3.16. 다이나믹 테스트들


Annotations 에 설명 된 JUnit Jupiter의 표준 @Test annotation은 JUnit 4의 @Test annotation과 매우 유사합니다. 둘 다 테스트 케이스를 구현하는 메소드를 설명합니다. 이 테스트 케이스들은 컴파일 타임에 완전히 지정된다는 점에서 정적이며 런타임시 발생하는 모든 사항에 의해 그 동작이 변경 될 수 없습니다. Assumptions 은 동적 행동의 기본 형태를 제공하지만 표현의 한계가있다.


이러한 표준 테스트 외에도 완전히 새로운 종류의 테스트 프로그래밍 모델이 JUnit Jupiter에 도입되었습니다. 이 새로운 종류의 테스트는 @TestFactory 로 주석 처리 된 팩토리 메서드에 의해 런타임에 생성되는 동적 테스트입니다. @TestFactory 메소드는 @Test 메소드와는 달리 테스트 케이스가 아니라 테스트 케이스의 팩토리입니다. 따라서 동적 테스트는 팩토리의 제품입니다. 기술적으로 말해서 @TestFactory 메소드는 Stream, Collection, Iterable, Iterator 또는 DynamicNode 인스턴스의 배열을 반환해야합니다. DynamicNode 의 인스턴스화 가능한 서브 클래스는 DynamicContainer DynamicTest 입니다. DynamicContainer 인스턴스는 표시 이름과 동적 하위 노드 목록으로 구성되어 임의로 중첩 된 동적 노드 계층을 만들 수 있습니다. DynamicTest 인스턴스가 느리게 실행되므로 동적이고, 비 결정적인 테스트 케이스 생성이 가능합니다.


@TestFactory 에 의해 리턴 된 모든 스트림은 stream.close() 를 호출하여 적절히 닫히게되므로 Files.lines() 와 같은 리소스를 사용하는 것이 안전합니다.


@Test 메서드와 마찬가지로 @TestFactory 메서드는 private 또는 static이 아니어야하며 ParameterResolvers에서 확인할 매개 변수를 선택적으로 선언 할 수 있습니다.


DynamicTest는 런타임에 생성되는 테스트 케이스입니다. 그것은 표시 이름과 Executable로 구성됩니다. Executable@FunctionalInterface입니다. 즉, 동적 테스트의 구현을 람다 식 또는 메서드 참조로 제공 할 수 있습니다.


JUnit Jupiter 5.3.2에서 동적 테스트는 항상 팩토리 메소드로 작성해야합니다. 그러나 이것은 이후 릴리스의 등록 기능으로 보완 될 수 있습니다.





+ Recent posts