Cucumber 在运行时提取步骤名称

Cucumber 在运行时提取步骤名称,cucumber,cucumber-jvm,cucumber-java,Cucumber,Cucumber Jvm,Cucumber Java,我试图找出是否有一个选项来确定当前正在执行的cucumber步骤,我试图根据步骤名称执行某些操作 我可以看到StepDefinitionMatch类获取这些步骤,但我不确定如何在运行时访问这些步骤。有什么帮助吗?添加调用堆栈的快照(如果有帮助的话) public StepDefinitionMatch(List<Argument> arguments, StepDefinition stepDefinition, String featurePath, Step step, Loca

我试图找出是否有一个选项来确定当前正在执行的cucumber步骤,我试图根据步骤名称执行某些操作

我可以看到StepDefinitionMatch类获取这些步骤,但我不确定如何在运行时访问这些步骤。有什么帮助吗?添加调用堆栈的快照(如果有帮助的话)

public StepDefinitionMatch(List<Argument> arguments, StepDefinition stepDefinition, String featurePath, Step step, LocalizedXStreams localizedXStreams) {
    super(arguments, stepDefinition.getLocation(false));
    this.stepDefinition = stepDefinition;
    this.featurePath = featurePath;
    this.step = step;
    this.localizedXStreams = localizedXStreams;
}

公共步骤定义匹配(List

只需等待Cucumber 3.0.0发行版,就可以使用@AfterStep和@beforstep注释访问步骤名称


多亏了Aniket(Coding Yogi)

获得运行时变量的一种方法是使用插件选项。尽管这似乎是滥用
Reporter
界面来访问
StepDefinitionMatch
变量以获得Cucumber版本1.2.5

为此,创建一个实现
Reporter
接口的自定义类

public class CustomFormatter implements Reporter{

    public  CustomFormatter() { }

    @Override
    public void before(Match match, Result result) {}

    @Override
    public void result(Result result) {}

    @Override
    public void after(Match match, Result result) {}

    @Override
    public void match(Match match) {
        ThreadLocalStepDefinitionMatch.set((StepDefinitionMatch)match);
    }

    @Override
    public void embedding(String mimeType, byte[] data) {}

    @Override
    public void write(String text) {}
}
用于存储
StepDefinitionMatch
变量的
ThreadLocal

public class ThreadLocalStepDefinitionMatch {

    private static final ThreadLocal<StepDefinitionMatch> threadStepDefMatch = new InheritableThreadLocal<StepDefinitionMatch>();

    private ThreadLocalStepDefinitionMatch() {
    }

    public static StepDefinitionMatch get() {
        return threadStepDefMatch.get();
    }

    public static void set(StepDefinitionMatch match) {
        threadStepDefMatch.set(match);
    }

    public static void remove() {
        threadStepDefMatch.remove();
    }
}
最后访问步骤定义类中的
StepDefinitionMatch
变量

@When("^user gets count from \"([^\"]*)\"$")
    public void userGetsCountFromAndStores(String arg) {
        StepDefinitionMatch match = ThreadLocalStepDefinitionMatch.get();
        System.out.println(match.getStepName());
        System.out.println(match.getPattern());
        System.out.println(match.getArguments());
    }
@When("^user gets count from \"([^\"]*)\"$")
    public void userGetsCountFromAndStores(String arg) {

        System.out.println(ThreadLocalPickleStep.get().getStepText());
        System.out.println(ThreadLocalPickleStep.get().getPattern());
        System.out.println(ThreadLocalPickleStep.get().getDefinitionArgument());
    }
控制台输出提供以下信息

user gets count from "Car1"
^user gets count from "([^"]*)"$
[Car1]

您使用的是一个非常旧的Cucumber版本,如果升级到Cucumber 2,将会有一些更改。
StepDefinitionMatch
PickleTestStep
替换。运行程序中的声明保持不变。
ThreadLocal
类将存储的类更改为
PickleTestStep

自定义格式化程序变为

public class CustomFormatter implements Formatter {

    public CustomFormatter() {}

    private EventHandler<TestStepStarted> stepStartedHandler = new EventHandler<TestStepStarted>() {
        @Override
        public void receive(TestStepStarted event) {
            handleTestStepStarted(event);
        }
    };

    @Override
    public void setEventPublisher(EventPublisher publisher) {
        publisher.registerHandlerFor(TestStepStarted.class, stepStartedHandler);
    }

    private void handleTestStepStarted(TestStepStarted event) { 
        if(event.testStep instanceof PickleTestStep) {
            ThreadLocalPickleStep.set((PickleTestStep)event.testStep);
        }

    }
}

输出与之前相同。

以下是我在cucumber 4中所做的操作

创建一个event Listener类,并将其作为插件添加到cucumber options:

公共类TestStepWatch实现ConcurrentEventListener{
private EventHandler stepHandler=new EventHandler()
{
@凌驾
公共无效接收(TestStepStarted事件)
{
handleTestStep(事件)
}
私有同步的void handleTestStep(TestStepStarted事件)
{
System.out.println(“运行步骤:+event.testStep.getStepText());
}
}
}

您可以实现ConcurrentEventListener,在插件部分进行设置:

@RunWith(Cucumber.class)
@CucumberOptions(
...
plugin = {
   ...,
   "com.mycompany.myproduct.AcceptanceStepNameLogger"
}...
AcceptanceStepNameLogger示例(在本例中,我只需要记录PickleStepTestStep步骤,而不需要记录挂钩):

import cucumber.api.*;
导入cumber.api.event.*;
公共类AcceptanceStepNameLogger实现ConcurrentEventListener{
@凌驾
public void setEventPublisher(EventPublisher publisher){
publisher.registerHandlerFor(TestStepStarted.class,new EventHandler()){
@凌驾
公共无效接收(TestStepStarted事件){
if(event.testStep instanceof PickleStepTestStep){
最终PickleStepTestStep ev=(PickleStepTestStep)event.testStep;
最后一个字符串args=StringUtils.join(ev.getDefinitionArgument().stream().map(Argument::getValue).toArray(),“,”);
字符串testDescription=ev.getStepText()+“:“+ev.getStepLocation();
if(StringUtils.isNotBlank(args)){
testDescription+=(“:args=(“+args+”);
}
System.out.println(“开始步骤:+testDescription”);
}
}
});
publisher.registerHandlerFor(TestStepFinished.class,新的EventHandler()){
@凌驾
公共作废接收(TestStepFinished事件){
if(event.testStep instanceof PickleStepTestStep){
PickleStepTestStep ev=(PickleStepTestStep)event.testStep;
最终字符串testDescription=ev.getStepText()+“:“+ev.getStepLocation();
System.out.println(“完成步骤:+testDescription”);
}
}
});
}
}

下面的代码可用于获取当前步骤方法名称

new Throwable().getStackTrace()[0].getMethodName()
例如: 给定用户在登录页面上

@给定(“^user位于登录页$”) public void user_在_Login_page()上是可丢弃的{

}

new Throwable().getStackTrace()[0].getMethodName()=>它将返回当前步骤方法名称为“user\u is\u on\u Login\u page”

如果您使用的是5.6.0或最新版本的cucumber jvm,请遵循以下解决方案。 由于Reporter类已被弃用,您必须实现ConcurrentEventListener并将该类添加到TestRunner插件部分

public class StepDetails implements ConcurrentEventListener {
    public static String stepName;

    public EventHandler<TestStepStarted> stepHandler = new EventHandler<TestStepStarted>() {
        @Override
        public void receive(TestStepStarted event) {
            handleTestStepStarted(event);
        }

    };

    @Override
    public void setEventPublisher(EventPublisher publisher) {
        publisher.registerHandlerFor(TestStepStarted.class, stepHandler);
    }

    private void handleTestStepStarted(TestStepStarted event) {
        if (event.getTestStep() instanceof PickleStepTestStep) {
            PickleStepTestStep testStep = (PickleStepTestStep)event.getTestStep();
            stepName = testStep.getStep().getText();
        }


    }
}

需要传递给AfterStep和BeforeStep的对象是什么?场景对象getName()返回场景的描述。如何使用
@BeforeStep
?TestStepStarted只有getCodeLocation,没有getStepText。
}
public class StepDetails implements ConcurrentEventListener {
    public static String stepName;

    public EventHandler<TestStepStarted> stepHandler = new EventHandler<TestStepStarted>() {
        @Override
        public void receive(TestStepStarted event) {
            handleTestStepStarted(event);
        }

    };

    @Override
    public void setEventPublisher(EventPublisher publisher) {
        publisher.registerHandlerFor(TestStepStarted.class, stepHandler);
    }

    private void handleTestStepStarted(TestStepStarted event) {
        if (event.getTestStep() instanceof PickleStepTestStep) {
            PickleStepTestStep testStep = (PickleStepTestStep)event.getTestStep();
            stepName = testStep.getStep().getText();
        }


    }
}
@CucumberOptions(dryRun=false,plugin = {"<yourPackage>.StepDetails"})
System.out.println(StepDetails.stepName);