Files
openide/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5EventsTest.java
Aleksey Dobrynin 247bef8e18 [junit 5] add escaping for service message IDEA-330442
GitOrigin-RevId: a31d0ad69a5ed2d9626bd2b1b55d506feec0eff5
2025-05-14 20:37:15 +00:00

199 lines
15 KiB
Java

// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.junit5;
import com.intellij.junit5.testData.AnnotationsTestClass;
import com.intellij.junit5.testData.MyTestClass;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.platform.engine.DiscoverySelector;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.discovery.ClassSelector;
import org.junit.platform.engine.reporting.ReportEntry;
import org.junit.platform.engine.support.descriptor.*;
import org.junit.platform.launcher.TestIdentifier;
import org.opentest4j.AssertionFailedError;
import org.opentest4j.MultipleFailuresError;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class JUnit5EventsTest {
@Test
void multipleFailures() throws Exception {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
JUnit5TestRunnerBuilder.TestDescriptorContext testContext = builder
.withRootName("testClass")
.withPresentableName("testClass")
.withTestMethod(MyTestClass.class, "test1");
builder.buildTestPlan().execute();
testContext.startExecution();
MultipleFailuresError multipleFailuresError = new MultipleFailuresError("2 errors", Arrays.asList(
new AssertionFailedError("message1", "expected1", "actual1"),
new AssertionFailedError("message2", "expected2", "actual2")
));
Map<String, String> map = new TreeMap<>();
map.put("key1", "value1");
map.put("stdout", "out1");
ReportEntry reportEntry = ReportEntry.from(map);
testContext.publishReportEntry(reportEntry)
.finishWithFailure(multipleFailuresError);
Assertions.assertEquals("""
##teamcity[enteredTheMatrix]
##teamcity[rootName name = 'testClass' location = 'java:suite://testClass']
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='test1()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' locationHint='java:test://com.intellij.junit5.testData.MyTestClass/test1' metainfo='']
##teamcity[testStdOut id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='test1()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' out = 'timestamp = ${timestamp}, key1 = value1, stdout = out1|n']
##teamcity[testFailed name='test1()' id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' message='message1|nComparison Failure: ' expected='expected1' actual='actual1' details='TRACE']
##teamcity[testFailed name='test1()' id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' message='message2|nComparison Failure: ' expected='expected2' actual='actual2' details='TRACE']
##teamcity[testFailed name='test1()' id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' message='2 errors (2 failures)|n\torg.opentest4j.AssertionFailedError: message1|n\torg.opentest4j.AssertionFailedError: message2' details='TRACE']
##teamcity[testFinished id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='test1()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0']
""".replace("${timestamp}", reportEntry.getTimestamp().toString()), builder.getFormattedOutput());
}
@Test
void testsWithExplicitTestSources() {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
List<JUnit5TestRunnerBuilder.TestDescriptorContext> tests = List.of(
builder.withTestDescriptor(MyTestClass.class, "test1", "test1 display name",
ClassSource.from(MyTestClass.class, FilePosition.from(111, 222))),
builder.withTestDescriptor(MyTestClass.class, "test2", "test2 display name", FileSource.from(
new File("/directory/test2.java"), FilePosition.from(12, 13))),
builder.withTestDescriptor(MyTestClass.class, "test3", "test3 display name", MethodSource.from(
"MyTestClass", "test4Method", "java.lang.String,java.util.List")),
builder.withTestDescriptor(MyTestClass.class, "test4", "test4 display name", CompositeTestSource.from(List.of(
ClassSource.from(JUnit5EventsTest.class, FilePosition.from(123, 456)),
ClassSource.from(MyTestClass.class, FilePosition.from(3, 4))
)))
);
builder.buildTestPlan().execute();
for (JUnit5TestRunnerBuilder.TestDescriptorContext test : tests) {
test.startTestOnly();
}
Assertions.assertEquals(
"""
##teamcity[enteredTheMatrix]
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:test1|]' name='test1 display name' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:test1|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' locationHint='java:suite://com.intellij.junit5.testData.MyTestClass' metainfo='110:221']
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:test2|]' name='test2 display name' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:test2|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' locationHint='file:///directory/test2.java:12']
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:test3|]' name='test3 display name' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:test3|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' locationHint='java:test://MyTestClass/test4Method' metainfo='java.lang.String,java.util.List']
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:test4|]' name='test4 display name' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:test4|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' locationHint='java:suite://com.intellij.junit5.JUnit5EventsTest']
""", builder.getFormattedOutput());
}
@Test
void containerFailure() throws Exception {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
JUnit5TestRunnerBuilder.TestDescriptorContext testContext = builder
.withRootName("testMethod")
.withPresentableName("testMethod")
.withSendTree()
.withTestFactory(MyTestClass.class, "brokenStream");
builder.buildTestPlan().execute();
testContext.startTestOnly().finishWithFailure(new IllegalStateException());
Assertions.assertEquals("""
##teamcity[enteredTheMatrix]
##teamcity[suiteTreeStarted id='|[engine:engine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[class:testClass|]' parentNodeId='0' locationHint='java:suite://com.intellij.junit5.testData.MyTestClass']
##teamcity[suiteTreeEnded id='|[engine:engine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[class:testClass|]' parentNodeId='0']
##teamcity[treeEnded]
##teamcity[rootName name = 'testMethod' location = 'java:suite://testMethod']
##teamcity[testStarted name='Class Configuration' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' ]
##teamcity[testFailed name='Class Configuration' id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' error='true' message='' details='TRACE']
##teamcity[testFinished name='Class Configuration' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' ]
##teamcity[testSuiteFinished id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='brokenStream()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]']
""", builder.getFormattedOutput());
}
@Test
void nestedEngines() {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
builder.withSendTree()
.withNestedEngine("secondEngine", MyTestClass.class)
.buildTestPlan()
.execute();
TestDescriptor theSameDescriptor = builder.getNestedClassDescriptor();
TestIdentifier testIdentifier = TestIdentifier.from(theSameDescriptor);
builder.getExecutionListener().executionStarted(testIdentifier);
builder.getExecutionListener().executionFinished(testIdentifier, TestExecutionResult.successful());
Assertions.assertEquals("""
##teamcity[enteredTheMatrix]
##teamcity[suiteTreeStarted id='|[engine:engine|]/|[suite:suiteClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[suite:suiteClass|]' parentNodeId='0' locationHint='java:suite://com.intellij.junit5.testData.MyTestClass']
##teamcity[suiteTreeStarted id='|[engine:secondEngine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:secondEngine|]/|[class:testClass|]' parentNodeId='|[engine:engine|]/|[suite:suiteClass|]' locationHint='java:suite://com.intellij.junit5.testData.MyTestClass']
##teamcity[suiteTreeEnded id='|[engine:secondEngine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:secondEngine|]/|[class:testClass|]' parentNodeId='|[engine:engine|]/|[suite:suiteClass|]']
##teamcity[suiteTreeEnded id='|[engine:engine|]/|[suite:suiteClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[suite:suiteClass|]' parentNodeId='0']
##teamcity[treeEnded]
##teamcity[testSuiteStarted id='|[engine:secondEngine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:secondEngine|]/|[class:testClass|]' parentNodeId='|[engine:engine|]/|[suite:suiteClass|]'locationHint='java:suite://com.intellij.junit5.testData.MyTestClass']
##teamcity[testSuiteFinished id='|[engine:secondEngine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:secondEngine|]/|[class:testClass|]' parentNodeId='|[engine:engine|]/|[suite:suiteClass|]']
""", builder.getFormattedOutput());
}
@Test
void containerDisabled() throws Exception {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
JUnit5TestRunnerBuilder.TestDescriptorContext testContext = builder
.withSendTree()
.withTestFactory(MyTestClass.class, "brokenStream");
builder.buildTestPlan().execute();
testContext.startTestOnly().finishAborted();
Assertions.assertEquals("""
##teamcity[enteredTheMatrix]
##teamcity[suiteTreeStarted id='|[engine:engine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[class:testClass|]' parentNodeId='0' locationHint='java:suite://com.intellij.junit5.testData.MyTestClass']
##teamcity[suiteTreeStarted id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='brokenStream()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]' locationHint='java:test://com.intellij.junit5.testData.MyTestClass/brokenStream' metainfo='']
##teamcity[suiteTreeEnded id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='brokenStream()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]']
##teamcity[suiteTreeEnded id='|[engine:engine|]/|[class:testClass|]' name='MyTestClass' nodeId='|[engine:engine|]/|[class:testClass|]' parentNodeId='0']
##teamcity[treeEnded]
##teamcity[testSuiteStarted id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='brokenStream()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]'locationHint='java:test://com.intellij.junit5.testData.MyTestClass/brokenStream' metainfo='']
##teamcity[testIgnored name='brokenStream()' id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]']
##teamcity[testSuiteFinished id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='brokenStream()' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='|[engine:engine|]/|[class:testClass|]']
""", builder.getFormattedOutput());
}
@Test
void singleMethodTestOneFromMyTest() {
var request =
JUnit5TestRunnerUtil.buildRequest(new String[]{"com.intellij.junit5.testData.InitStaticField$MyTest,testOne"}, new String[1], null);
var selectors = request.getSelectorsByType(DiscoverySelector.class);
Assertions.assertFalse(selectors.isEmpty(), "Selectors should not be empty");
var selector = selectors.get(0);
Assertions.assertInstanceOf(ClassSelector.class, selector);
Assertions.assertEquals("com.intellij.junit5.testData.InitStaticField$MyTest", ((ClassSelector)selector).getClassName());
}
@Test
void testEscaping() throws NoSuchMethodException {
JUnit5TestRunnerBuilder builder = new JUnit5TestRunnerBuilder();
JUnit5TestRunnerBuilder.TestDescriptorContext testContext = builder
.withRootName("testClass")
.withPresentableName("testClass")
.withTestMethod(AnnotationsTestClass.class, "test1");
builder.buildTestPlan().execute();
testContext.startExecution().finish();
Assertions.assertEquals("""
##teamcity[enteredTheMatrix]
##teamcity[rootName name = 'testClass' location = 'java:suite://testClass']
##teamcity[testStarted id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='|[test|'s method|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0' locationHint='java:test://com.intellij.junit5.testData.AnnotationsTestClass/test1' metainfo='']
##teamcity[testFinished id='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' name='|[test|'s method|]' nodeId='|[engine:engine|]/|[class:testClass|]/|[method:testMethod|]' parentNodeId='0']
""", builder.getFormattedOutput());
}
}