测试报告 API 允许您以编程方式捕获测试执行事件,并生成类似于 Gradle 内置 Test 任务的结果。它对于将非 JVM 测试结果集成到 Gradle 的测试基础设施中,并在 Gradle 的 HTML 测试报告中发布它们特别有用。

该 API 主要面向插件开发人员和平台提供商,Javadoc 作为主要参考。

让我们快速看一个示例,该示例定义了一个自定义 Gradle 任务 CustomTest,演示了如何捕获和报告测试事件

src/main/java/com/example/CustomTest.java
package com.example;

import org.gradle.api.DefaultTask;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.testing.GroupTestEventReporter;
import org.gradle.api.tasks.testing.TestEventReporter;
import org.gradle.api.tasks.testing.TestEventReporterFactory;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.TestExecutionSummary;

import javax.inject.Inject;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;

/**
 * A custom task that demonstrates the {@code TestEventReporter} API.
 */
public abstract class CustomTest extends DefaultTask {

    @Inject
    public abstract ProjectLayout getLayout();

    @Inject
    protected abstract TestEventReporterFactory getTestEventReporterFactory();


    @TaskAction
    void runTests() {
        try (GroupTestEventReporter root = getTestEventReporterFactory().createTestEventReporter(
            "root",
            getLayout().getBuildDirectory().dir("test-results/custom-test").get(),
            getLayout().getBuildDirectory().dir("reports/tests/custom-test").get()
        )) {
            root.started(Instant.now());

            List<String> failedTests = new ArrayList<>();

            try (GroupTestEventReporter junittest = root.reportTestGroup("CustomJUnitTestSuite")) {
                junittest.started(Instant.now());

                LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
                    .selectors(
                        selectClass(MyTest1.class)
                    )
                    .build();

                Launcher launcher = LauncherFactory.create();
                TestExecutionSummary summary = executeTests(launcher, request);

                summary.getFailures().forEach(result -> {
                    try (TestEventReporter test = junittest.reportTest(result.getTestIdentifier().getDisplayName(),
                        result.getTestIdentifier().getLegacyReportingName())) {
                        test.started(Instant.now());
                        String testName = String.valueOf(result.getTestIdentifier().getParentIdObject());
                        failedTests.add(testName);
                        test.metadata(Instant.now(),"Parent class:", String.valueOf(result.getTestIdentifier().getParentId().get()));
                        test.failed(Instant.now(), String.valueOf(result.getException()));
                    }
                });

                String failedTestsList = String.join(", ", failedTests);
                junittest.metadata(Instant.now(), "Tests that failed:", failedTestsList);

                if (summary.getTestsFailedCount() > 0) {
                    junittest.failed(Instant.now());
                } else {
                    junittest.succeeded(Instant.now());
                }
            }

            if (!failedTests.isEmpty()) {
                root.failed(Instant.now());
            } else {
                root.succeeded(Instant.now());
            }
        }
    }

    private TestExecutionSummary executeTests(Launcher launcher, LauncherDiscoveryRequest request) {
        // Use SummaryGeneratingListener to collect test execution data
        SummaryGeneratingListener listener = new SummaryGeneratingListener();
        launcher.registerTestExecutionListeners(listener);

        // Execute the tests
        launcher.execute(request);

        // Return the summary generated by the listener
        return listener.getSummary();
    }
}
  1. GroupTestEventReporter 被初始化为充当根事件报告器。

    它在项目的构建目录下创建测试结果和报告目录

    这建立了报告层次结构。支持嵌套

  2. 该任务使用 JUnit Platform 动态发现和执行测试,这将替换为您的自定义测试系统/平台

    它选择类 MyTest1 进行测试。

    JUnit 的 Launcher 用于执行测试并收集结果摘要。

  3. TestEventReporter 用于记录每个测试的详细事件。

    对于每个失败,测试都会报告元数据并标记为失败。

  4. 每个测试组 (junittest) 和根组 (root) 都会根据测试结果最终确定成功或失败。

通过使用测试报告 API

  • 集成:自定义测试(即使是 JVM 框架之外的测试)也可以生成与 Gradle 测试报告基础设施兼容的事件。

  • 丰富的元数据:开发人员可以将额外的上下文(例如,错误消息或父类详细信息)附加到测试事件。

  • 一致性:结果与 Gradle 的 HTML 报告无缝集成,从而更容易调试和理解测试结果。

有关 HTML 报告本身的更多详细信息,请参阅 JVM 测试文档

有关可下载的示例,请参阅自定义测试任务示例