web-dev-qa-db-ja.com

各機能の前後に実行するキュウリのフックはありますか

特定のタグを使用して各キュウリ機能の前後に特定のコードブロックを実行する方法はありますか?

セットアッププロセスは非常にコストがかかるため、各シナリオの前に実行したくありません。

11
LukasMac

数日前、私はマット・ウィン(キュウリの宝石のコアチームメンバーの1人)と話をしましたが、彼はキュウリにはそのような機能はないと言っていました(これを書いている時点で)。

回避策として、彼は機能全体にタグを付け、各フックの前に次のようなフラグを使用することを提案しました。

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

LukasMacの答えは@変数では機能しませんでした。 Andeは公式 cucumber wiki ページに基づいています。以下の例は正常に機能し、テストされています。以下のbeforeフックは機能ごとに1回だけ実行されます。

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
4
Gob00st

キュウリのフックについて説明します このwikiページで これはあなたが持つことができるフックの前後を示しています。

そのページから抜粋したのは次の例です。

次の例では、実行に0.5秒以上かかると、@ fastでタグ付けされたシナリオが失敗します。

Around('@fast') do |scenario, block|
  Timeout.timeout(0.5) do
    block.call
  end
end
2
Mike H-R

フィーチャーフック前後のキュウリ

使用情報

Rubyキュウリには、機能の前後にフックを作成するオプションが付属していないため、アドホックソリューションが提案されています。

機能に関連するフックを指定するには、メソッド名が次の形式である必要があります。

before_feature_ [フォーマットされた機能名] after_feature_ [フォーマットされた機能名]

フォーマットされたフィーチャ名は、次のようにフォーマットされたフィーチャファイルの「Feature:」行のテキストです。

(i)すべての文字を小文字にします。 (ii)すべてのスペースがアンダースコアに置き換えられました。 (iii)すべての特殊文字が削除されました

この規則に一致するメソッド内では、シナリオフックと同様にコードを指定できます。

技術情報

LukasMacとGob00stによるソリューションに基づいて、現在のクライアントに対して次の回避策を実装しました。

メソッドは、AAA_special_hooksと呼ばれるフックサブディレクトリ、そのディレクトリ内のspecial_hooks.rbファイル(唯一のファイル)に配置されます。これは、フックが等しい他のすべてのものが、プロジェクト構造に表示される順序で実行されるためです。ここで作成されたフックは、他のサブディレクトリまたはフックのベースディレクトリで指定されたシナリオフックの前に実行されます。

以下の付録のコードはVanillaですが、私が見る限り、誰でも機能します。

Beforeフックは、グローバルフラグを設定する原則に基づいて実行され、機能に対してフックが1回だけ実行されるようにします(LukasMacおよびGob00stによる)。この原則は、2つの理由で抽象フックに拡張されました。まず、一般的なフックの仕様を簡素化することと、アフターフックの実装との一貫性を保つことです。

アフターフックは、最後のシナリオが実行されてから機能が変更されたかどうかを判断するように設計されています。その場合、現在の機能で何かが発生する前に、前の機能に対してアフターフックが実行されます。明らかに脆弱性は、前のフックのアフターフックが実行される前に新しい機能が実際に開始されたことである可能性がありますが、これがどのように問題を引き起こす可能性があるかはわかりません。ただし、最後の機能では、この方法でアフターフックを実行することはできません。これが、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
2
emc

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
1

最初の答えの変更は一重引用符で私のために働きます

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