我可以使用以下方法对测试失败执行操作:
@After
public void afterTest(Scenario scenario) {
if (scenario.isFailed()) {
/*Do stuff*/
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我需要执行的某些操作取决于抛出的异常以及抛出的上下文。有没有办法获得导致测试失败的 Throwable?例如在 JUnit 中,我会通过扩展 TestWatcher 并在我的测试中添加规则来做到这一点:
@Override
protected void failed(Throwable e, Description description) {
/*Do stuff with e*/
}
Run Code Online (Sandbox Code Playgroud)
但是,cucumber-junit 实施不允许使用规则,因此该解决方案不适用于 Cucumber。
我认为我不需要解释为什么在测试失败时访问抛出的异常会很有用,但是我仍然会提供一个示例:
我的测试环境并不总是稳定的,所以我的测试可能在任何时候意外失败(没有特定的地方我可以尝试捕获异常,因为它随时可能发生)。发生这种情况时,我需要重新安排测试以进行另一次尝试,并记录事件,以便我们可以获得一些关于环境不稳定的良好统计数据(何时、多频繁、多长时间等)
mpk*_*nje 12
Frank Escobar 建议的解决方法存在的问题:
通过使用反射来了解框架内部,您依赖于实现细节。这是一个不好的做法,当框架更改其实现时,您的代码可能会中断,正如您在 Cucumber v5.0.0 中观察到的那样。
Cucumber 中的钩子旨在在场景之前和之后操作测试执行上下文。它们并不是用来报告测试执行本身的。报告是跨领域的问题,最好通过使用插件系统进行管理。
例如:
package com.example;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.Result;
import io.cucumber.plugin.event.Status;
import io.cucumber.plugin.event.TestCase;
import io.cucumber.plugin.event.TestCaseFinished;
public class MyTestListener implements ConcurrentEventListener {
@Override
public void setEventPublisher(EventPublisher publisher) {
publisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinished);
}
private void handleTestCaseFinished(TestCaseFinished event) {
TestCase testCase = event.getTestCase();
Result result = event.getResult();
Status status = result.getStatus();
Throwable error = result.getError();
String scenarioName = testCase.getName();
String id = "" + testCase.getUri() + testCase.getLine();
System.out.println("Testcase " + id + " - " + status.name());
}
}
Run Code Online (Sandbox Code Playgroud)
使用 JUnit 4 和 TestNG 时,您可以使用以下方法激活此插件:
@CucumberOptions(plugin="com.example.MyTestListener")
Run Code Online (Sandbox Code Playgroud)
使用 JUnit 5,您可以将其添加到junit-platform.properties:
cucumber.plugin=com.example.MyTestListener
Run Code Online (Sandbox Code Playgroud)
或者如果您使用的是 CLI
cucumber.plugin=com.example.MyTestListener
Run Code Online (Sandbox Code Playgroud)
我已经使用反射实现了这个方法。您无法直接访问步骤错误(堆栈跟踪)。我创建了这个静态方法,它允许您访问“stepResults”属性,然后您可以迭代并获取错误并做任何您想做的事情。
import cucumber.runtime.ScenarioImpl;
import gherkin.formatter.model.Result;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
@After
public void afterScenario(Scenario scenario) {
if (scenario.isFailed())
logError(scenario);
}
private static void logError(Scenario scenario) {
Field field = FieldUtils.getField(((ScenarioImpl) scenario).getClass(), "stepResults", true);
field.setAccessible(true);
try {
ArrayList<Result> results = (ArrayList<Result>) field.get(scenario);
for (Result result : results) {
if (result.getError() != null)
LOGGER.error("Error Scenario: {}", scenario.getId(), result.getError());
}
} catch (Exception e) {
LOGGER.error("Error while logging error", e);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过编写自己的自定义Formatter & Reporter接口实现来实现这一点。的空实现Formatter是NullFormatter.java您可以扩展的。您将需要提供该Reporter接口的实现。
感兴趣的方法是result()Reporter 接口的方法,也可能done()是 Formatter 的方法。result() 具有Result存在异常的对象。
你可以看清楚RerunFormatter.java。
public void result(Result result) {
//Code to create logs or store to a database etc...
result.getError();
result.getErrorMessage();
}
Run Code Online (Sandbox Code Playgroud)
您需要将此类(com.myimpl.CustomFormRep)添加到插件选项中。
plugin={"pretty", "html:report", "json:reports.json","rerun:target/rerun.txt",com.myimpl.CustomFormRep}
Run Code Online (Sandbox Code Playgroud)
您可以使用重新运行插件来获取失败场景的列表以再次运行。不确定如何安排运行失败的测试、创建批处理作业的代码或在 CI 工具上安排一个运行。