每个function之前和之后都有一个黄瓜钩

有没有办法在每个黄瓜function之前和之后运行特定代码块与某些标签?

由于设置过程非常昂贵,我不想在每个场景之前运行它。

LukasMac的回答与@var不兼容。 Ande基于官方黄瓜维基页面,下面我的例子工作和测试好了,下面的挂钩只执行一次每个function:

Before('@my_feature_tag') do unless $dts_test_preparation_done # expensive setup in my case setup lots of database tables for test $dts_test_preparation_done = true end end 

几天前我和Matt Wynne(黄瓜gem的核心团队成员之一)交谈过,他告诉我黄瓜没有这样的function(在撰写本文时)。

作为一种解决方法,他建议在每个钩子之前标记整个特征和使用标志,如下所示:

 Before('@feature_with_expensive_setup') do unless @setup_is_done # perform expensive setup code here .. @setup_is_done = true end end 

黄瓜的钩子在这个维基页面中描述,它显示了你可以拥有的前后挂钩。

从该页面获取的是此示例:

如果执行时间超过0.5秒,以下示例将导致使用@fast标记的方案失败:

 Around('@fast') do |scenario, block| Timeout.timeout(0.5) do block.call end end 

通过使用标记@ExecuteBeforeFeature标记特征的第一个场景,并使用标记说@ExecuteAfterFeature,然后编写标记的Before和After钩子,如下所示,可以实现对BeforeFeature / AfterFeature挂钩的模拟:

 Before('@ExecuteBeforeFeature') do #code in this method will be executed only before the first scenario or before the feature if only the first scenario is tagged for this hook. end After('@ExecuteAfterFeature') do #code in this method will be executed only after the last scenario or after the feature if only the last scenario is tagged for this hook. end 

特色挂钩之前和之后的黄瓜

使用信息

由于ruby黄瓜没有提供在特征之前和之后创建钩子的选项,因此提出了一种临时解决方案。

要指定与要素相关的挂钩,方法名称必须采用以下格式:

before_feature_ [格式化function名称] after_feature_ [格式化function名称]

格式化的要素名称是特征文件中“要素:”行中的文本,其格式为:

(i)所有字符小写; (ii)所有空格均以下划线代替; 并且,(iii)删除所有特殊字符

在匹配此约定的方法中,可以使用场景挂钩指定代码。

技术信息

在LukasMac和Gob00st的解决方案的基础上,我为我当前的客户实施了以下变通方法。

这些方法在一个名为AAA_special_hooks的hooks子目录中,位于该目录(唯一文件)中的special_hooks.rb文件中,这是因为所有其他条件相同,钩子将按照它们在项目结构中出现的顺序运行,这样此处创建的挂钩在其他子目录或挂钩基目录中指定的任何方案挂钩之前运行。

下面附录中的代码是vanilla,据我所知,它对任何人都有效。

before钩子的运行原则是设置一个全局标志,以确保钩子只为一个特征运行一次(根据LukasMac和Gob00st)。 由于两个原因,该原则已经扩展到抽象钩子,首先是简化钩子的规范,并且与钩子实现具有一致性。

挂钩用于确定自上次方案执行以来function是否已更改。 如果是这样,在当前特征发生任何事件之前,将对前一特征运行后钩子。 显然,该漏洞可能是新function实际上已经在之前的挂钩运行之前启动,但我看不出这可能会导致任何问题。 然而,最终的特性不能以这种方式运行后钩子,这就是在at_exit方法中重新实现该代码的原因。

附录 – special_hooks.rb代码

 def get_formatted_name(feature_name) formatted_name = feature_name.downcase.gsub(' ', '_') %w[@ ' , . / ! " £ $ % ^ & * ( ) { } [ ] ; : # ~ ? < > \] + = - ` ¬ |].each { |char| formatted_name.gsub! char, '' } formatted_name end Before do |scenario| $completed_before_hooks ||= [] $feature_name ||= scenario.feature.name unless $feature_name == scenario.feature.name # run after hook for previous feature begin send "after_feature_#{get_formatted_name $feature_name}" rescue NoMethodError end end #run before hook for current feature if not already done begin formatted_name = get_formatted_name scenario.feature.name unless $completed_before_hooks.include? formatted_name $completed_before_hooks << formatted_name send "before_feature_#{formatted_name}" end rescue NoMethodError end $feature_name = scenario.feature.name end at_exit do # don't run final hook if error raised that was not handled unless $! && $!.status > 1 puts 'EXECUTING FINAL AFTER HOOK... PLEASE WAIT' begin send "after_feature_#{get_formatted_name $feature_name}" rescue NoMethodError end puts 'FINAL AFTER HOOK COMPLETED' end end 

第一个答案的修改对我来说只有单引号

  Before('@feature_with_expensive_setup') do unless '@setup_is_done' # perform expensive setup code here .. @setup_is_done = true end end