简体   繁体   English

在每个功能之前和之后是否有一个黄瓜钩可以运行

[英]Is there a cucumber hook to run before and after each feature

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.由于设置过程非常昂贵,我不想在每个场景之前运行它。

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(黄瓜宝石的核心团队成员之一)进行过交谈,他告诉我黄瓜没有这样的特征(在撰写本文时)。

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

LukasMac's answer didn't work with @ variable. LukasMac的答案与@var不兼容。 Ande based on official cucumber wiki page, my example below worked and tested ok, the before hook below only execute once per feature: Ande基于官方的黄瓜维基页面,下面我的例子工作和测试好了,下面的挂钩只执行一次每个功能:

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

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. 由于红宝石黄瓜没有提供在特征之前和之后创建钩子的选项,因此提出了一种临时解决方案。

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; (i)所有字符小写; (ii) all spaces replaced with underscores; (ii)所有空格均以下划线代替; and, (iii) all special characters deleted (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. 下面附录中的代码是vanilla,据我所知它可以适用于所有人。

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

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. 但是最终的特性不能以这种方式运行后钩子,这就是在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

The hooks for cucumber are described in this wiki page which show the before and after hooks you can have. 黄瓜的钩子在这个维基页面中描述它显示了你可以拥有的前后挂钩。

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

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: 可以通过使用标记@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

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

您可以使用 at_exit 实现 after 功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM