Skip to content

Handle failures in BeforeAll hooks and AfterAll hooks#1857

Open
brasmusson wants to merge 3 commits into
mainfrom
feature/global-hooks-fix
Open

Handle failures in BeforeAll hooks and AfterAll hooks#1857
brasmusson wants to merge 3 commits into
mainfrom
feature/global-hooks-fix

Conversation

@brasmusson
Copy link
Copy Markdown
Contributor

Description

  • All BeforeAll hooks and AfterAll hooks shall be executed regardless of they pass or fail.
  • The TestCases shall only be executed if all BeforeAll hooks passes.
  • BeforeAll hooks shall be executed after the TestRunStarted event has fired.
  • AfterAll hooks shall be executed before the TestRunFinished event is fired.
  • Print the global hook failures shall be printed by the console formatters.
  • Aslo global hook failures shall affect the exit code.

With this change Cucumber-Ruby conforms fully with CCK v22

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds new behaviour)

Checklist:

Your PR is ready for review once the following checklist is
complete. You can also add some checks if you want to.

  • Tests have been added for any changes to behaviour of the code
  • New and existing tests are passing locally and on CI
  • bundle exec rubocop reports no offenses
  • RDoc comments have been updated
  • CHANGELOG.md has been updated

* All BeforeAll hooks and AfterAll hooks shall be executed regardless
  of they pass or fail.
* The TestCases shall only be executed if all BeforeAll hooks passes.
* BeforeAll hooks shall be executed after the TestRunStarted event
  has fired.
* AfterAll hooks shall be executed before the TestRunFinished event
  is fired.
* Print the global hook failures shall be printed by the console
  formatters.
* Aslo global hook failures shall affect the exit code.
Copy link
Copy Markdown
Contributor

@luke-hill luke-hill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once v11 is out I'll get to this. Might take me a week or two

Copy link
Copy Markdown
Contributor

@luke-hill luke-hill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few minor questions. Great stuff though


def on_test_case_started(event)
@current_test_case_started_id = test_case_started_id(event.test_case)
@current_test_run_hook_started_id = nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed

Copy link
Copy Markdown
Contributor Author

@brasmusson brasmusson May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the attach method we need to know if the attachment comes from an before_all/after_all hook or from a test case step of hook. Since we store both current_test_case_started_id and current_test_run_hook_started_id can be set when test step or hooks are executed and when after all hooks are executed. In this pull request the solution is to use the condition if @current_test_run_hook_started_id.nil? to decide whether it is a test step or hook, or a before all hook or after all hook that is executing. Using that condition (in the attach method) requires that we ensure that @current_test_run_hook_started_id is nil when a test step or hook is executed. That is the purpose of this line.

file_name: filename,
timestamp: time_to_timestamp(Time.now)
}
attachment_data = if @current_test_run_hook_started_id.nil?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid crazy indents can we do something like this

Suggested change
attachment_data = if @current_test_run_hook_started_id.nil?
attachment_data =
if @current_test_run_hook_started_id.nil?
{
.....
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread lib/cucumber/glue/registry_and_more.rb Outdated

def before_all
set_up_world_for_global_hooks
all_succeded = true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo *succeeded (In other spots too)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

rescue StandardError => e
@configuration.notify(:test_run_hook_finished, hook, Core::Test::Result::Failed.new(timer.duration, e))
raise
false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is where the magic happens/happened. Thanks for this spot!

end

def before_all
set_up_world_for_global_hooks
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the goal here of this bit (Both the setup and the clearer on line 156 for this method)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling attach from hooks and step definition works since the world object handles the attach and creates an event/message for it. To be able to call attach from before all and after all hooks, I create a world object here so something exist to create the event/message for the attach calls in before all hooks.

Comment thread lib/cucumber/runtime.rb

load_step_definitions
fire_install_plugin_hook
fire_before_all_hook unless dry_run?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to be deleted?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The ndjson files of the cck dev kit specifies that the expected message sequence is that the TestRunHookStarted/Finished messages for the before all hook come after the TestRunStarted message. Therefore I have moved the execution of the before all hooks to after the TestRunStarted event has been sent. The TestRunStarted event is broadcast by one of the filters (BroadcastTestRunStartedEvent) close to the end of the filter chain, so I have therefore created the FilreBeforeAllHooks filter which is placed directly after the BroadcastTestRunStartedEvent filter. Therefore before all hooks shall not be fired from here.

@luke-hill luke-hill mentioned this pull request May 15, 2026
5 tasks
* Fix spelling of succeeded
* Change indentation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants