用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。
参考
P.S.
这次的求解过程,更深刻地感受到一句话的正确性:不要盯着锁找答案,钥匙在别处。
P.P.S
Happy coding and bye bug : )