Is there a cucumber hook to start before and after each function

Is there a way to run a specific block of code before and after each function of a cucumber with a specific tag?

Since the installation process is very expensive, I do not want to run it before each scenario.

+8
ruby hook cucumber
source share
6 answers

A few days ago I talked with Matt Wynn (one of the members of the cucumber pearl team), and he told me that there was no such possibility in the cucumber (at the time of writing this).

As a workaround, he suggested marking the entire function and using flags before each hook like this:

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

LukasMac answer did not work with @ variable. Ande, based on the official cucumber wiki page, my example below worked and tested fine before taking a snapshot only once for each function:

 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 
+3
source share

Cucumber hooks are described on this wiki page , which displays before and after hooks you may have.

The following example taken from this page:

In the following example, scripts with the @fast tag will fail if the execution takes more than 0.5 seconds:

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

Cucumbers before and after hooks function

Usage Information

Since the ruby ​​cucumber does not come with the ability to create hooks for before and after the function, a special solution has been proposed.

To indicate a hook related to a function, the method name should be in the following format:

before_feature_ [formatted function name] after_feature_ [formatted function name]

If the formatted function name is the text from the "Feature:" line in the function file formatted with

(i) all lower characters; (ii) all spaces are replaced by underscores; and (iii) all special characters are removed

Within methods consistent with this convention, code can be specified as if using scripts.

Technical information

Based on LukasMac and Gob00st solutions, I applied the following workarounds for my current client.

The methods go to the hooks subdirectory called AAA_special_hooks in the special_hooks.rb file in this directory (single file), this is because, all things being equal, the hooks will be executed in the order in which they are displayed in the project structure and the hooks created here run before any script intercepts the hooks specified in other subdirectories or in the base directory.

The code in the app below is vanilla, as far as I see, it will work for everyone.

Before the interception is triggered by the principle of setting a global flag, to ensure that the hook is triggered only once for the function (according to LukasMac and Gob00st). This principle has been extended to an abstract hook for two reasons, firstly, to simplify the specification of hooks in general, and also to have consistency with the implementation after capture.

The final hook is used to determine if this function has changed since the last script. If so, then after the previous start, the previous function will be executed before anything happens in the current one. Obviously, the vulnerability could be that a new function was actually launched before it clung to the previous one, but I do not see how this could cause problems. The final function, however, cannot be executed after this, and this is the reason for the repeated implementation of this code in the at_exit method.

Application - special_hooks.rb code

 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 
0
source share

The failure of the BeforeFeature / AfterFeature interceptors is achieved by tagging the first script of the function with the tag: @ExecuteBeforeFeature and the last script with the tag: @ExecuteAfterFeature, and then writing the Before and After hooks labels as follows:

 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 
0
source share

modifying 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 
0
source share

All Articles