每个功能之前和之后是否有黄瓜钩

时间:2014-04-16 15:10:08

标签: ruby cucumber hook

有没有办法在每个黄瓜特征之前和之后使用特定标记运行特定代码块?

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

6 个答案:

答案 0 :(得分:3)

几天前,我与Matt Wynne(黄瓜宝石的核心团队成员之一)进行过交谈,他告诉我黄瓜没有这样的功能(在撰写本文时)。

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

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

答案 1 :(得分:3)

LukasMac的答案与@var不同。 Ande基于官方cucumber wiki页面,下面我的例子工作和测试好了,下面的挂钩只执行一个功能:

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

答案 2 :(得分:2)

功能挂钩前后的黄瓜

使用信息

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

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

before_feature_ [格式化功能名称] after_feature_ [格式化功能名称]

格式化的功能名称是'功能中的文字:'格式为:

的要素文件中的行

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

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

技术信息

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

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

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

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

After hook旨在确定自上次方案执行以来功能是否已更改。如果是这样,在当前特征发生任何事件之前,将对前一特征运行后钩子。显然,该漏洞可能是新功能实际上已经在之前的挂钩运行之前启动,但我无法看到这可能会导致任何问题。然而,最终的特性不能以这种方式运行后钩子,这就是在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

答案 3 :(得分:1)

描述了黄瓜的钩子in this wiki page,它显示了你可以拥有的前后钩子。

从该页面采取的是这个例子:

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

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