| /* |
| * 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()); |
| } |
| } |
| } |
| } |
| } |