blob: 1f3f468f86d5ba01fe200f57c795a00118f465a5 [file]
/*
* Copyright 2015-2022 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
import java.lang.reflect.Method;
import java.util.EmptyStackException;
import java.util.Stack;
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests;
import org.junit.platform.engine.TestDescriptor;
/**
* Check generated display names.
*
* @see DisplayName
* @see DisplayNameGenerator
* @see DisplayNameGeneration
* @since 5.4
*/
class DisplayNameGenerationTests extends AbstractJupiterTestEngineTests {
@Test
void standardGenerator() {
check(DefaultStyleTestCase.class, //
"CONTAINER: DisplayNameGenerationTests$DefaultStyleTestCase", //
"TEST: @DisplayName prevails", //
"TEST: test()", //
"TEST: test(TestInfo)", //
"TEST: testUsingCamelCaseStyle()", //
"TEST: testUsingCamelCase_and_also_UnderScores()", //
"TEST: testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact(TestInfo)", //
"TEST: test_with_underscores()" //
);
}
@Test
void simpleGenerator() {
check(SimpleStyleTestCase.class, //
"CONTAINER: DisplayNameGenerationTests$SimpleStyleTestCase", //
"TEST: @DisplayName prevails", //
"TEST: test", //
"TEST: test (TestInfo)", //
"TEST: testUsingCamelCaseStyle", //
"TEST: testUsingCamelCase_and_also_UnderScores", //
"TEST: testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact (TestInfo)", //
"TEST: test_with_underscores" //
);
}
@Test
void underscoreGenerator() {
var expectedDisplayNames = new String[] { //
"<replace me>", //
"TEST: @DisplayName prevails", //
"TEST: test", //
"TEST: test (TestInfo)", //
"TEST: test with underscores", //
"TEST: testUsingCamelCase and also UnderScores", //
"TEST: testUsingCamelCase and also UnderScores keepingParameterTypeNamesIntact (TestInfo)", //
"TEST: testUsingCamelCaseStyle" //
};
expectedDisplayNames[0] = "CONTAINER: DisplayNameGenerationTests$UnderscoreStyleTestCase";
check(UnderscoreStyleTestCase.class, expectedDisplayNames);
expectedDisplayNames[0] = "CONTAINER: DisplayNameGenerationTests$UnderscoreStyleInheritedFromSuperClassTestCase";
check(UnderscoreStyleInheritedFromSuperClassTestCase.class, expectedDisplayNames);
}
@Test
void indicativeSentencesGeneratorOnStaticNestedClass() {
check(IndicativeStyleTestCase.class, //
"CONTAINER: DisplayNameGenerationTests$IndicativeStyleTestCase", //
"TEST: @DisplayName prevails", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test (TestInfo)", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test with underscores", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCase and also UnderScores", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCase and also UnderScores keepingParameterTypeNamesIntact (TestInfo)", //
"TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCaseStyle" //
);
}
@Test
void indicativeSentencesGeneratorOnTopLevelClass() {
check(IndicativeSentencesTopLevelTestCase.class, //
"CONTAINER: IndicativeSentencesTopLevelTestCase", //
"CONTAINER: IndicativeSentencesTopLevelTestCase -> A year is a leap year", //
"TEST: IndicativeSentencesTopLevelTestCase -> A year is a leap year -> if it is divisible by 4 but not by 100" //
);
}
@Test
void indicativeSentencesGeneratorOnNestedClass() {
check(IndicativeSentencesNestedTestCase.class, //
"CONTAINER: IndicativeSentencesNestedTestCase", //
"CONTAINER: A year is a leap year", //
"TEST: A year is a leap year -> if it is divisible by 4 but not by 100" //
);
}
@Test
void noNameGenerator() {
check(NoNameStyleTestCase.class, //
"CONTAINER: nn", //
"TEST: @DisplayName prevails", //
"TEST: nn", //
"TEST: nn", //
"TEST: nn", //
"TEST: nn", //
"TEST: nn", //
"TEST: nn" //
);
}
@Test
void checkDisplayNameGeneratedForTestingAStackDemo() {
check(StackTestCase.class, //
"CONTAINER: A stack", //
"TEST: is instantiated using its noarg constructor", //
"CONTAINER: A new stack", //
"TEST: throws an EmptyStackException when peeked", //
"TEST: throws an EmptyStackException when popped", //
"TEST: is empty", //
"CONTAINER: After pushing an element to an empty stack", //
"TEST: peek returns that element without removing it from the stack", //
"TEST: pop returns that element and leaves an empty stack", //
"TEST: the stack is no longer empty" //
);
}
@Test
void checkDisplayNameGeneratedForIndicativeGeneratorTestCase() {
check(IndicativeGeneratorTestCase.class, //
"CONTAINER: A stack", //
"TEST: A stack, is instantiated with new constructor", //
"CONTAINER: A stack, when new", //
"TEST: A stack, when new, throws EmptyStackException when peeked", //
"CONTAINER: A stack, when new, after pushing an element to an empty stack", //
"TEST: A stack, when new, after pushing an element to an empty stack, is no longer empty" //
);
}
@Test
void checkDisplayNameGeneratedForIndicativeGeneratorWithCustomSeparatorTestCase() {
check(IndicativeGeneratorWithCustomSeparatorTestCase.class, //
"CONTAINER: A stack", //
"TEST: A stack >> is instantiated with new constructor", //
"CONTAINER: A stack >> when new", //
"TEST: A stack >> when new >> throws EmptyStackException when peeked", //
"CONTAINER: A stack >> when new >> after pushing an element to an empty stack", //
"TEST: A stack >> when new >> after pushing an element to an empty stack >> is no longer empty" //
);
}
@Test
void displayNameGenerationInheritance() {
check(DisplayNameGenerationInheritanceTestCase.InnerNestedTestCase.class, //
"CONTAINER: DisplayNameGenerationInheritanceTestCase", //
"CONTAINER: InnerNestedTestCase", //
"TEST: this is a test"//
);
check(DisplayNameGenerationInheritanceTestCase.StaticNestedTestCase.class, //
"CONTAINER: DisplayNameGenerationInheritanceTestCase$StaticNestedTestCase", //
"TEST: this_is_a_test()"//
);
}
@Test
void indicativeSentencesGenerationInheritance() {
check(IndicativeSentencesGenerationInheritanceTestCase.InnerNestedTestCase.class, //
"CONTAINER: IndicativeSentencesGenerationInheritanceTestCase", //
"CONTAINER: IndicativeSentencesGenerationInheritanceTestCase -> InnerNestedTestCase", //
"TEST: IndicativeSentencesGenerationInheritanceTestCase -> InnerNestedTestCase -> this is a test"//
);
check(IndicativeSentencesGenerationInheritanceTestCase.StaticNestedTestCase.class, //
"CONTAINER: IndicativeSentencesGenerationInheritanceTestCase$StaticNestedTestCase", //
"TEST: this_is_a_test()"//
);
}
private void check(Class<?> testClass, String... expectedDisplayNames) {
var request = request().selectors(selectClass(testClass)).build();
var descriptors = discoverTests(request).getDescendants();
assertThat(descriptors).map(this::describe).containsExactlyInAnyOrder(expectedDisplayNames);
}
private String describe(TestDescriptor descriptor) {
return descriptor.getType() + ": " + descriptor.getDisplayName();
}
// -------------------------------------------------------------------
static class NoNameGenerator implements DisplayNameGenerator {
@Override
public String generateDisplayNameForClass(Class<?> testClass) {
return "nn";
}
@Override
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
return "nn";
}
@Override
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
return "nn";
}
}
@DisplayNameGeneration(NoNameGenerator.class)
static abstract class AbstractTestCase {
@Test
void test() {
}
@Test
void test(TestInfo testInfo) {
testInfo.getDisplayName();
}
@Test
void testUsingCamelCaseStyle() {
}
@Test
void testUsingCamelCase_and_also_UnderScores() {
}
@Test
void testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact(TestInfo testInfo) {
testInfo.getDisplayName();
}
@Test
void test_with_underscores() {
}
@DisplayName("@DisplayName prevails")
@Test
void testDisplayNamePrevails() {
}
}
@DisplayNameGeneration(DisplayNameGenerator.Standard.class)
static class DefaultStyleTestCase extends AbstractTestCase {
}
@DisplayNameGeneration(DisplayNameGenerator.Simple.class)
static class SimpleStyleTestCase extends AbstractTestCase {
}
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
static class UnderscoreStyleTestCase extends AbstractTestCase {
}
@IndicativeSentencesGeneration(separator = " -> ", generator = DisplayNameGenerator.ReplaceUnderscores.class)
static class IndicativeStyleTestCase extends AbstractTestCase {
}
@DisplayNameGeneration(NoNameGenerator.class)
static class NoNameStyleTestCase extends AbstractTestCase {
}
// No annotation here! @DisplayNameGeneration is inherited from super class
static class UnderscoreStyleInheritedFromSuperClassTestCase extends UnderscoreStyleTestCase {
}
// -------------------------------------------------------------------
@DisplayName("A stack")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
static class StackTestCase {
Stack<Object> stack;
@Test
void is_instantiated_using_its_noarg_constructor() {
new Stack<>();
}
@Nested
class A_new_stack {
@BeforeEach
void createNewStack() {
stack = new Stack<>();
}
@Test
void is_empty() {
assertTrue(stack.isEmpty());
}
@Test
void throws_an_EmptyStackException_when_popped() {
assertThrows(EmptyStackException.class, () -> stack.pop());
}
@Test
void throws_an_EmptyStackException_when_peeked() {
assertThrows(EmptyStackException.class, () -> stack.peek());
}
@Nested
class After_pushing_an_element_to_an_empty_stack {
String anElement = "an element";
@BeforeEach
void pushAnElement() {
stack.push(anElement);
}
@Test
void the_stack_is_no_longer_empty() {
assertFalse(stack.isEmpty());
}
@Test
void pop_returns_that_element_and_leaves_an_empty_stack() {
assertEquals(anElement, stack.pop());
assertTrue(stack.isEmpty());
}
@Test
void peek_returns_that_element_without_removing_it_from_the_stack() {
assertEquals(anElement, stack.peek());
assertFalse(stack.isEmpty());
}
}
}
}
// -------------------------------------------------------------------
@DisplayName("A stack")
@IndicativeSentencesGeneration(generator = DisplayNameGenerator.ReplaceUnderscores.class)
static class IndicativeGeneratorTestCase {
Stack<Object> stack;
@Test
void is_instantiated_with_new_constructor() {
new Stack<>();
}
@Nested
class when_new {
@BeforeEach
void create_with_new_stack() {
stack = new Stack<>();
}
@Test
void throws_EmptyStackException_when_peeked() {
assertThrows(EmptyStackException.class, () -> stack.peek());
}
@Nested
class after_pushing_an_element_to_an_empty_stack {
String anElement = "an element";
@BeforeEach
void push_an_element() {
stack.push(anElement);
}
@Test
void is_no_longer_empty() {
assertFalse(stack.isEmpty());
}
}
}
}
// -------------------------------------------------------------------
@DisplayName("A stack")
@IndicativeSentencesGeneration(separator = " >> ", generator = DisplayNameGenerator.ReplaceUnderscores.class)
static class IndicativeGeneratorWithCustomSeparatorTestCase {
Stack<Object> stack;
@Test
void is_instantiated_with_new_constructor() {
new Stack<>();
}
@Nested
class when_new {
@BeforeEach
void create_with_new_stack() {
stack = new Stack<>();
}
@Test
void throws_EmptyStackException_when_peeked() {
assertThrows(EmptyStackException.class, () -> stack.peek());
}
@Nested
class after_pushing_an_element_to_an_empty_stack {
String anElement = "an element";
@BeforeEach
void push_an_element() {
stack.push(anElement);
}
@Test
void is_no_longer_empty() {
assertFalse(stack.isEmpty());
}
}
}
}
}