特定のタグを使用して各キュウリ機能の前後に特定のコードブロックを実行する方法はありますか?
セットアッププロセスは非常にコストがかかるため、各シナリオの前に実行したくありません。
数日前、私はマット・ウィン(キュウリの宝石のコアチームメンバーの1人)と話をしましたが、彼はキュウリにはそのような機能はないと言っていました(これを書いている時点で)。
回避策として、彼は機能全体にタグを付け、各フックの前に次のようなフラグを使用することを提案しました。
Before('@feature_with_expensive_setup') do
unless @setup_is_done
# perform expensive setup code here ..
@setup_is_done = true
end
end
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
キュウリのフックについて説明します このwikiページで これはあなたが持つことができるフックの前後を示しています。
そのページから抜粋したのは次の例です。
次の例では、実行に0.5秒以上かかると、@ fastでタグ付けされたシナリオが失敗します。
Around('@fast') do |scenario, block|
Timeout.timeout(0.5) do
block.call
end
end
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メソッドでそのコードを再実装する理由です。
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
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
最初の答えの変更は一重引用符で私のために働きます
Before('@feature_with_expensive_setup') do
unless '@setup_is_done'
# perform expensive setup code here ..
@setup_is_done = true
end
end