diff --git a/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java index bc58333a3951..574c9ce2ce22 100644 --- a/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java +++ b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java @@ -148,10 +148,19 @@ public class JUnit5TestExecutionListener implements TestExecutionListener { messageName = MapSerializerUtil.TEST_IGNORED; } if (messageName != null && myFinishCount == 0) { - for (TestIdentifier childIdentifier : myTestPlan.getDescendants(testIdentifier)) { - testStarted(childIdentifier); - testFailure(childIdentifier, messageName, throwableOptional, 0, reason, true); - testFinished(childIdentifier, 0); + final Set descendants = myTestPlan.getDescendants(testIdentifier); + if (!descendants.isEmpty()) { + for (TestIdentifier childIdentifier : descendants) { + testStarted(childIdentifier); + testFailure(childIdentifier, messageName, throwableOptional, 0, reason, true); + testFinished(childIdentifier, 0); + } + } + else { + testStarted(testIdentifier); + testFailure(testIdentifier, messageName, throwableOptional, 0, reason, true); + testFinished(testIdentifier, 0); + myFinishCount++; } } myPrintStream.println("##teamcity[testSuiteFinished " + idAndName(testIdentifier, displayName) + "\']"); diff --git a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5EventsTest.java b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5EventsTest.java index ee2fc8e0f1f0..3a281ead15f6 100644 --- a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5EventsTest.java +++ b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5EventsTest.java @@ -15,29 +15,37 @@ */ package com.intellij.junit5; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import com.intellij.openapi.util.text.StringUtil; +import org.junit.jupiter.api.*; +import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.MethodTestDescriptor; +import org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.TestIdentifier; +import org.junit.platform.launcher.TestPlan; import org.opentest4j.AssertionFailedError; import org.opentest4j.MultipleFailuresError; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.util.Collections; +import java.util.stream.Stream; class JUnit5EventsTest { - @Test - void multipleFailures() throws Exception { - StringBuffer buf = new StringBuffer(); - JUnit5TestExecutionListener executionListener = new JUnit5TestExecutionListener(new PrintStream(new OutputStream() { + private JUnit5TestExecutionListener myExecutionListener; + private StringBuffer myBuf; + + @BeforeEach + void setUp() { + myBuf = new StringBuffer(); + myExecutionListener = new JUnit5TestExecutionListener(new PrintStream(new OutputStream() { @Override public void write(int b) throws IOException { - buf.append(new String(new byte[]{(byte)b})); + myBuf.append(new String(new byte[]{(byte)b})); } })) { @Override @@ -50,14 +58,24 @@ class JUnit5EventsTest { return "TRACE"; } }; + } + + @AfterEach + void tearDown() { + myBuf = null; + } + + @Test + void multipleFailures() throws Exception { + TestDescriptor testDescriptor = new MethodTestDescriptor(UniqueId.forEngine("engine"), TestClass.class, TestClass.class.getDeclaredMethod("test1")); TestIdentifier identifier = TestIdentifier.from(testDescriptor); - executionListener.executionStarted(identifier); + myExecutionListener.executionStarted(identifier); MultipleFailuresError multipleFailuresError = new MultipleFailuresError("2 errors"); multipleFailuresError.addFailure(new AssertionFailedError("message1", "expected1", "actual1")); multipleFailuresError.addFailure(new AssertionFailedError("message2", "expected2", "actual2")); - executionListener.executionFinished(identifier, TestExecutionResult.failed(multipleFailuresError)); + myExecutionListener.executionFinished(identifier, TestExecutionResult.failed(multipleFailuresError)); Assertions.assertEquals("##teamcity[enteredTheMatrix]\n" + @@ -70,12 +88,40 @@ class JUnit5EventsTest { "\n" + "##teamcity[testFailed name='test1()' details='TRACE' id='|[engine:engine|]' message='2 errors (2 failures)|n\tmessage1|n\tmessage2']\n" + "\n" + - "##teamcity[testFinished id='[engine:engine]' name='test1()']\n", buf.toString()); + "##teamcity[testFinished id='[engine:engine]' name='test1()']\n", StringUtil.convertLineSeparators(myBuf.toString())); + } + + @Test + void containerFailure() throws Exception { + ClassTestDescriptor classTestDescriptor = new ClassTestDescriptor(UniqueId.forEngine("engine"), TestClass.class); + TestDescriptor testDescriptor = new TestFactoryTestDescriptor(UniqueId.forEngine("engine1"), TestClass.class, + TestClass.class.getDeclaredMethod("brokenStream")); + TestIdentifier identifier = TestIdentifier.from(testDescriptor); + final TestPlan testPlan = TestPlan.from(Collections.singleton(classTestDescriptor)); + myExecutionListener.sendTree(testPlan, ""); + myExecutionListener.executionStarted(identifier); + myExecutionListener.executionFinished(identifier, TestExecutionResult.failed(new IllegalStateException())); + + Assertions.assertEquals("##teamcity[enteredTheMatrix]\n" + + "##teamcity[treeEnded]\n" + + "##teamcity[testSuiteStarted id='[engine:engine1]' name='brokenStream()']\n" + + "\n" + + "##teamcity[testStarted id='[engine:engine1]' name='brokenStream()']\n" + + "\n" + + "##teamcity[testFailed name='brokenStream()' details='TRACE' id='|[engine:engine1|]' error='true' message='']\n" + + "\n" + + "##teamcity[testFinished id='[engine:engine1]' name='brokenStream()']\n" + + "##teamcity[testSuiteFinished id='[engine:engine1]' name='brokenStream()']\n", StringUtil.convertLineSeparators(myBuf.toString())); } private static class TestClass { @Test void test1() { } + + @TestFactory + Stream brokenStream() { + return Stream.generate(() -> { throw new IllegalStateException(); }); + } } }