Surefire 只报告从模块到 RunListener 的第一个测试套件

Surefire only reports first test suite from module to RunListener

所以我有一个 TeamCity 和 JUnit 测试,我想写一个 RunListenernotify TeamCity in real-time about running tests - TeamCity 只支持开箱即用的 JUnit 批量测试报告。

我有几个套件,用 @RunWith(Suite.class) 注释用于测试的逻辑分组。 TeamCity 正确显示按套件分组的测试。但是,我的问题是 Surefire 只会调用 RunListener.testRunStarted 一次,描述中包含两个套件的名称(但无法将测试归因于任何一个)。

所以我实现了

public class JUnitTeamcityReporter extends RunListener {
    /** */
    private volatile Description suite;

    /** */
    @Override public void testRunStarted(Description desc) {
        this.suite = desc;
    }

    /** */
    @Override public void testStarted(Description desc) {
        System.out.println(String.format("##teamcity[testStarted name='%s' captureStandardOutput='true']",
            testName(suite, desc)));
    }
...

我已经把它连接到我的 pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M3</version>
    <configuration>
        <forkCount>0</forkCount>
        <properties>
            <property>
                <name>listener</name>
                <value>com.pany.JUnitTeamcityReporter</value>
            </property>
        </properties>
    </configuration>
</plugin>

我运行 maven -Dtest=FirstTestSuite,SecondTestSuite

输出如下:

[INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.803 s - in com.pany.FirstTestSuite
# I expect that my RunListener will be notified HERE, but it does not happen!
[INFO] Running com.pany.SecondTestSuite

否则,如果每个模块只有一个套件,我的解决方案就可以正常工作。

是否可以让 Surefire 将每个 Suite 正确地报告给 testRunStarted? 不幸的是,似乎没有办法从测试描述中获取当前的 运行ning 套件,所以我不知道如何解决这个问题。

JUnit无法获得此信息,Surefire的扩展能力较差,但可以达到:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M4</version> <!-- upgrade to M4 -->
    <configuration>
        <workingDirectory>${user.dir}</workingDirectory>
        <!-- surefire integration to intercept test suite start: -->
        <statelessTestsetInfoReporter 
            implementation="com.pany.TestSuiteAwareTestsetReporter"/>
        <properties>
            <property>
                <name>listener</name>
                <value>com.pany.JUnitTeamcityReporter</value>
            </property>
        </properties>
    </configuration>
    <dependencies>
    <!-- Add dependency to plugin (for surefire) as well as
    compile,test dependency to module (for junit) since they're on different classpaths -->
        <dependency>
            <groupId>com.pany</groupId>
            <artifactId>dev-tools</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>
</plugin>

和测试套件记者的代码:

public class TestSuiteAwareTestsetReporter extends SurefireStatelessTestsetInfoReporter {
    @Override public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> createListener(
        ConsoleLogger log) {
        return new ConsoleReporter(log, false, false) {
            public void testSetStarting(TestSetReportEntry report) {
                MessageBuilder builder = MessageUtils.buffer();

                /** @see TestSetStats#concatenateWithTestGroup(MessageBuilder, ReportEntry, boolean) */
                JUnitTeamcityReporter.suite = concatenateWithTestGroup(builder, report);

                super.testSetStarting(report);
            }
        };
    }

...