如何获取cucumber中step的name?

用cucumber测试时,有一个需求,就是提取每个step的name,以及对应的scenario和feature的name。

Google了不少,也试过几个前人提供的方法, 屡屡败北,在坑里挣扎了两天, 发现这方面的资料其实还是挺少的,特别是ruby这块,记录下这趟比较揪心的求解过程,给需要的提供个参考。「我揪心就好了,大伙就别再揪心了。」

正文

cucumber hooks 中提到了多个hook,包括before,after,但是对于step hooks,只有一个AfterStep, 看AfterStep 的用法:

AfterStep do |scenario|
  # Do something after each step.
end

官方文档是这么写的,可是你会发现根本不是那么回事。「吐槽下:文档没有及时更新让人很是心塞啊」

在你的feature/support目录下,新建一个文件hooks.rb, 添加如下内容:

Before do |scenario|
  # do something before scenario
end

AfterStep do |scenario|
    puts scenario.methods
    puts scenario.class
  # Do something after each step.
end

终端运行cucumber的时候,你会发现AfterStep中根本不是scenario,得到的是这样的结果:

这里可以看到它的class是Cucumber::Core::Test::Result::Passed, method里面也没有任何name,text之类。那么,每次afterstep后,返回的Cucumber::Core::Test::Result::Passed是个什么鬼?是个step?

看源码:Class: Cucumber::Core::Test::Result::Passed, cucumber中每个step运行后,其实有7种情况:

[:failed, :flaky, :skipped, :undefined, :pending, :passed, :unknown]

而passed只是其中的一个type,它不是一个step。看cucumber的doc,可以找到step, 里面的text字段,这正是我们想要的:

可是如何获取到step呢?

你Google后会发现有一些可能”有用”的解决方法,列出几个我觉得特别的:

​ 「竟然直接在step definition里面添加argument,然后在每个step里面添加一行代码 ‘puts step_name ‘, 且 不说这种方法能不能正常运行,你这样每个step都加,成千上万的steps,手都要断吧?」

  • 有坑的解答:Get current step within step

    Cukes 上,一个叫Marc Divins的人也遇到这个问题,未解决,身为cucumber backers之一的Matt Wynneg给出了custom formatter的解决建议, 这方法已试过,failed。

  • 版本问题的坑:get current step from scenario outline

    这里面用到了Cucumber::Ast::Scenario, 这个在cucumber3.0下运行会报错,无法识别,这是其一,其二是在AfterStep中调用的scenario并没有定义,会报错。

OK,不废话了,直接上解答:

在新建好的features/support/hooks.rb 中,添加如下内容:

Before do |scenario|
  $step_index = 0
  $stop_count = scenario.test_steps.count
  @scenario = scenario
end

AfterStep do |step|
  if $step_index < $stop_count
    puts "steps: #{@scenario.test_steps[$step_index].text}\n"
  end
  $step_index += 2
end

运行一个feature试试:

cucumber features/xxxx.feature

每个step之后,都会输出了AfterStep中定义的"steps: #{@scenario.test_steps[$step_index].text}\n"

类似这样:

说明:

代码上的$step_index += 2, 给step_index累加了2,而不是1, 是因为每输出一个step,后面会跟一个aferstep hook,为了不输出aferstep hook字段,所以累加2。

参考

add step to AfterStep

cucumber JVM:Hooks

P.S.

这次的求解过程,更深刻地感受到一句话的正确性:不要盯着锁找答案,钥匙在别处

P.P.S

Happy coding and bye bug : )