ruby 在每个功能之前和之后是否有一个黄瓜钩可以运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23113370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a cucumber hook to run before and after each feature
提问by LukasMac
Is there a way to run specific code block before and after each cucumber feature with certain tag?
有没有办法在每个带有特定标签的黄瓜特征之前和之后运行特定的代码块?
Since setup process is very expensive I don't want to run it before each scenario.
由于设置过程非常昂贵,我不想在每个场景之前运行它。
采纳答案by LukasMac
Few days ago I've spoke with Matt Wynne (one of the core team member of cucumber gem) and he told me that there is no such feature in cucumber (at the time of writing this).
几天前,我与 Matt Wynne(Cucumber gem 的核心团队成员之一)进行了交谈,他告诉我黄瓜中没有这样的功能(在撰写本文时)。
As a workaround he suggested to tag whole feature and use before each hook with a flag like so:
作为一种解决方法,他建议在每个钩子之前标记整个功能并使用如下标志:
Before('@feature_with_expensive_setup') do
unless @setup_is_done
# perform expensive setup code here ..
@setup_is_done = true
end
end
回答by Gob00st
LukasMac's answer didn't work with @ variable. Ande based on official cucumber wikipage, my example below worked and tested ok, the before hook below only execute once per feature:
LukasMac 的答案不适用于 @ 变量。安德基于官方黄瓜维基页面,我下面的例子工作和测试正常,下面的前钩子每个功能只执行一次:
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
回答by Mike H-R
The hooks for cucumber are described in this wiki pagewhich show the before and after hooks you can have.
这个 wiki 页面描述了黄瓜的钩子,它显示了你可以拥有的前后钩子。
Taken from that page is this example:
取自该页面的是这个例子:
The following example will cause scenarios tagged with @fast to fail if the execution takes longer than 0.5 seconds:
如果执行时间超过 0.5 秒,以下示例将导致标有 @fast 的场景失败:
Around('@fast') do |scenario, block|
Timeout.timeout(0.5) do
block.call
end
end
回答by emc
Cucumber before and after feature hooks
特征钩之前和之后的黄瓜
Usage info
使用信息
As ruby cucumber does not come supplied with the option to create hooks for before and after a feature, an ad hoc solution has been put forward.
由于 ruby Cucumber 没有提供为特征前后创建钩子的选项,因此提出了一个特别的解决方案。
In order to specify a hook relating to a feature, the method name must be in the following format:
为了指定与功能相关的钩子,方法名称必须采用以下格式:
before_feature_[formatted feature name] after_feature_[formatted feature name]
before_feature_[格式化特征名称] after_feature_[格式化特征名称]
Where the formatted feature name is the text from the 'Feature:' line in the feature file formatted with:
其中格式化功能名称是功能文件中“功能:”行中的文本,格式为:
(i) all characters lowercased; (ii) all spaces replaced with underscores; and, (iii) all special characters deleted
(i) 所有字符小写;(ii) 所有空格都用下划线代替;(iii) 删除所有特殊字符
Within methods matching this convention code can be specified as with scenario hooks.
在与此约定代码匹配的方法中,可以像使用场景挂钩一样指定。
Technical info
技术信息
Building on the solutions by LukasMac and Gob00st I have implemented the following workarounds for my current client.
基于 LukasMac 和 Gob00st 的解决方案,我为我当前的客户实施了以下解决方法。
The methods go in a hooks subdirectory called AAA_special_hooks, in a special_hooks.rb file in that directory (the sole file), this is because all other things being equal the hooks will be run in the order they appear in the project structure and this way the hooks created here are run before any scenario hooks specified in other subdirectories or in the hooks base directory.
这些方法位于名为 AAA_special_hooks 的 hooks 子目录中,位于该目录中的 special_hooks.rb 文件(唯一文件)中,这是因为所有其他条件相同,挂钩将按照它们在项目结构中出现的顺序运行,这样此处创建的钩子在其他子目录或钩子基目录中指定的任何场景钩子之前运行。
The code in the below appendix is vanilla, so far as I can see it would work for anyone.
下面附录中的代码是普通的,据我所知,它适用于任何人。
The before hook runs on the principle of setting a global flag to ensure the hook is only run once for a feature (as per LukasMac and Gob00st). That principle has been extended to the abstract hook for two reasons, firstly to simplify the specification of hooks in general and also to have consistency with the after hook implementation.
before 钩子运行的原则是设置全局标志以确保钩子只为一个功能运行一次(根据 LukasMac 和 Gob00st)。出于两个原因,该原则已扩展到抽象钩子,首先是为了简化钩子的一般规范,以及与后钩子实现保持一致。
The after hook is designed to determine whether the feature has changed since the last scenario was executed. If so the after hook will be run for the previous feature before anything happens in the current one. Clearly the vulnerability could be that the new feature has in fact been started before the after hook runs for the previous one, but I can't see how this might cause any issues. The final feature however cannot have an after hook run in this way and that is the reason for the reimplementation of that code in the at_exit method.
after 挂钩旨在确定自上一个场景执行以来该功能是否已更改。如果是这样,则在当前功能发生任何事情之前,将为前一个功能运行 after 挂钩。显然,该漏洞可能是新功能实际上是在前一个功能的 after 挂钩运行之前启动的,但我看不出这会如何导致任何问题。然而,最后一个功能不能以这种方式运行后挂钩,这就是在 at_exit 方法中重新实现该代码的原因。
Appendix - special_hooks.rb code
附录 - 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
回答by Neetesh Kumar Gupta
Mocking of BeforeFeature/ AfterFeature hooks is achievable by tagging the first scenario of the feature with a tag say @ExecuteBeforeFeature and last scenario with tag say @ExecuteAfterFeature and then writing the tagged Before and After hooks as following:
模拟 BeforeFeature/AfterFeature 钩子可以通过使用标记 @ExecuteBeforeFeature 标记功能的第一个场景和使用标记 @ExecuteAfterFeature 标记最后一个场景,然后编写标记的 Before 和 After 钩子来实现,如下所示:
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
回答by Smiti
a modification of the first answer works for me with single quotes
第一个答案的修改对我有用单引号
Before('@feature_with_expensive_setup') do
unless '@setup_is_done'
# perform expensive setup code here ..
@setup_is_done = true
end
end

