JUnit5 - 如何在 AfterTestExecutionCallback 中获取测试结果

9

我是一个有用的助手,可以为您翻译文本。

我编写了JUnit5扩展,但我找不到获取测试结果的方法。

扩展的代码如下:

import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.TestExtensionContext;

public class TestResultExtension implements AfterTestExecutionCallback {
    @Override
    public void afterTestExecution(TestExtensionContext context) throws Exception {
        //How to get test result? SUCCESS/FAILED
    }
}

任何提示如何获取测试结果?

你的使用情况是什么?通过当前的快照和即将到来的里程碑(M4),你可以插入你自己的TestExecutionListener - Marc Philipp
我在这里描述了我的使用情况。https://github.com/junit-team/junit5/issues/542 - bugs_
6个回答

8
这对我有用:
public class RunnerExtension implements AfterTestExecutionCallback {

    @Override
    public void afterTestExecution(ExtensionContext context) throws Exception {
        Boolean testResult = context.getExecutionException().isPresent();
        System.out.println(testResult); //false - SUCCESS, true - FAILED
    }
}

@ExtendWith(RunnerExtension.class)
public abstract class Tests {

}

这对我起作用,虽然不完全确定如何管理ExentTest实例的上下文。 - djangofan
对我来说不起作用。尽管断言失败,但没有执行异常。 - Metareven

6
如其他答案所指出的那样,JUnit通过异常来传达失败的测试情况,因此可以使用AfterTestExecutionCallback了解发生了什么。请注意,这种方法存在错误风险,因为稍后运行的扩展可能仍会导致测试失败。
另一种方法是注册自定义TestExecutionListener。这两种方法都有点绕弯子。有一个问题跟踪特定的扩展点以对测试结果做出反应, 这很可能是回答您问题最直接的方式。如果您能提供一个具体的用例,那么请前往#542并留下一条评论描述它将会非常好。

2

您可以使用位于org.junit.platform.launcher.listenersSummaryGeneratingListener

它包含MutableTestExecutionSummary字段,该字段实现TestExecutionSummary接口,因此您可以获取有关容器、测试、时间、失败等信息。

您可以创建自定义侦听器,例如:

  1. 创建扩展SummaryGeneratingListener的类
public class ResultAnalyzer extends SummaryGeneratingListener {
    @Override
    public void testPlanExecutionFinished(TestPlan testPlan) {
        //This method is invoked after all tests in all containers is finished
        super.testPlanExecutionFinished(testPlan);
        analyzeResult();
    }

    private void analyzeResult() {
        var summary = getSummary();
        var failures = summary.getFailures();
        //Do something
    }
}
  1. 通过创建文件注册监听器

src\main\resources\META-INF\services\org.junit.platform.launcher.TestExecutionListener

并在其中指定你的实现

path.to.class.ResultAnalyzer

  1. 启用扩展名自动检测,设置参数

-Djunit.jupiter.extensions.autodetection.enabled=true

就是这样了!

文档

https://junit.org/junit5/docs/5.0.0/api/org/junit/platform/launcher/listeners/SummaryGeneratingListener.html

https://junit.org/junit5/docs/5.0.0/api/org/junit/platform/launcher/listeners/TestExecutionSummary.html

https://junit.org/junit5/docs/current/user-guide/#extensions-registration-automatic


你能提供一些代码吗?你正在使用哪个版本的JUnit?已经过去两年了,也许API在某些方面发生了变化 :) - Alexander Oreshin

1
在JUnit中,失败是通过异常传播的。有几种异常,表示不同类型的错误。
因此,在TestExtensionContext#getTestException()中出现异常表示出现了错误。该方法无法操纵实际的测试结果,因此根据您的使用情况,您可能需要实现TestExecutionExceptionHandler,它允许您吞噬异常,从而改变测试是否成功的结果。

1
我只有这个解决方案:
String testResult = context.getTestException().isPresent() ? "FAILED" : "OK";

看起来它工作得很好。但我不确定它在所有情况下是否能正常工作。


你是否尝试了这两种情况,测试通过和失败时?我认为这不起作用。 - Naman
1
是的,我做了。我尝试通过测试。但是测试失败了。 - bugs_
更新后的代码目前可以运行,但其可靠性还不是很确定。 - Naman

0

你快成功了。

为了实现测试执行回调并获得测试结果以进行日志记录(或生成报告),您可以执行以下操作:

import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

public class TestResultExtension implements AfterTestExecutionCallback
{
    @Override
    public void afterTestExecution(ExtensionContext context) throws Exception
    {
        // check the context for an exception 
        Boolean passed = context.getExecutionException().isEmpty();
        
        // if there isn't, the test passed
        String result = passed ? "PASSED" : "FAILED";

        // now that you have the result, you can do whatever you want 
        System.out.println("Test Result: " + context.getDisplayName() + " " + result);
    }
}

然后,您只需在测试用例中使用@ExtendWith()注释添加TestResultExtension:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.junit.jupiter.api.Assertions.assertTrue;

@ExtendWith(TestResultExtension.class)
public class SanityTest
{
    @Test
    public void testSanity()
    {
        assertTrue(true);
    }

    @Test
    public void testInsanity()
    {
        assertTrue(false);
    }
}

将扩展包含在基本测试中是一个好主意

import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(TestResultExtension.class)
public class BaseTest
{}

接下来您不需要在每个测试中包含注释:

public class SanityTest extends BaseTest
{ //... }

如果您想在测试类执行成功或失败后访问变量,可以参考:https://dev59.com/FHENtIcB2Jgan1zn6kw7#76050531 - Yang Bodong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接