Test::...tecture(3pm)

πŸ“¦
version 0.87 Β· 4 versions
, in debian trixie, ubuntu resolute, ubuntu stonking

✨ NAME ✨

Test::BDD::Cucumber::Manual::Architecture β€” Structural Overview πŸ’…


🌸 VERSION 🌸

version 0.87 β€” yes bestie, we're on 0.87, keep up 🫢


πŸŽ€ INTRODUCTION πŸŽ€

okay so this little doc exists purely to give you the ~vibe map~ of how all the pieces of this distribution snap together, because ngl the first time you look at it you're like "who is she and why are there so many modules" 😭

Everything falls into three categories:

  • one group handles the definition of the step functions (that's your actual Perl code),
  • another group handles the feature files,
  • and then there's the third group, which has Test::BDD::Cucumber::Executor β€” she's the main character πŸ‘‘ because she links the other two groups together, building on the steps to actually execute the features.

Chilling in the first group are Test::BDD::Cucumber::StepFile and Test::BDD::Cucumber::Loader. ✨

The second group is bigger and is comprised of:

  • Test::BDD::Cucumber::Parser
  • Test::BDD::Cucumber::Model::*

The third group holds β€” next to Test::BDD::Cucumber::Executor:

  • Test::BDD::Cucumber::Harness::*
  • Test::BDD::Cucumber::StepContext
  • Test::BDD::Cucumber::Errors
  • Test::BDD::Cucumber::Extension
🚨 real talk: please note that the Test::BDD::Cucumber::Harness should not be confused with TAP::Harness or Test2::Harness. This harness is TBC's very own, and it optionally forwards events to the Test::Builder::Test harness. Different girl, same name, iykyk πŸ’€

πŸ¦‹ MODELS πŸ¦‹

The core of a Cucumber-based test suite is literally the feature files and the step definitions files. By convention, these live under /features/ and /features/step_definitions/ respectively. That's just where they go, periodt. πŸ“

The feature files get encapsulated by the classes in Test::BDD::Cucumber::Model, and the relationship chart looks like this (she's giving family tree energy 🌳):

                  one to one
 TBCM::Feature<----------------->TBCM::Document
      |                               |
      +-------------------+           |
      | has many          | has a     | has many
      V                   |           V
 TBCM::Scenario           +----->TBCM::Line
      |                            ^  ^
      +----------------------------+  |
      | has many                      |
      V                               |
 TBCM::Step---------------------------+

πŸ”₯ EXECUTOR πŸ”₯

So here's the flow: we build up a Test::BDD::Cucumber::Executor object, and we load the step definitions into it. Then we pass it a Test::BDD::Cucumber::Model::Feature object, along with a Test::BDD::Cucumber::Harness object β€” and that harness is the one that controls all the interaction with the outside world. 🌍

πŸ’œ Test::Builder πŸ’œ

While it's running step functions, Test::BDD::Cucumber::Executor reroutes the flow of test events (so like, calls to ok, fail, etc) back to itself. Based on all the data it collected, the step itself then gets reported as a success or a failure to the test driver. Slay.

The confusing part about this whole situation, bestie, is that both the channel used to report through to the actual test driver is an instance of Test::Builder, and the method used to route the stream of test events to itself uses a Test::Builder instance. Two Test::Builders. Same room. Not talking about it πŸ™ˆ


🌈 EXTENSION 🌈

Extensions let you hook into the execution of the steps β€” pre- and post hooks for steps, scenarios, features, and the entire execution. Iconic behaviour honestly. Extensions can also provide additional step directories, from which steps will be made available. And the feature and scenario stashes get passed to the extension hooks, which gives you a whole means of communication between the hooks and the steps. πŸ“¬

Also β€” as of 0.60, it's possible to define meta data for a step upon step definition, like this example:

Given qr/a step with meta data/ => { meta => 'data' }, sub { };

This lets step function authors communicate with extensions, because extensions receive this meta data in their pre_step callback:

sub pre_step {
  my ($stepdef, $step_context) = @_;
  my ($verb, $metadata, $stepfn) = @$stepdef;

  die 'All steps should have meta -> data'
    unless $metadata->{meta} eq 'data';
}

Extensions β€” when they're loaded by the pherkin test executor β€” receive their configuration from the pherkin.yaml configuration file, which works similar to the configuration of extensions in Behat <http://docs.behat.org/en/v2.5/guides/7.config.html#extensions>.

⚠️ Note: when using extensions in combination with the TAP::Parser::SourceHandler::Feature plugin for prove, there is no guarantee that the pre_execute and post_execute hooks execute exactly once or even execute at all. This is a current limitation to be lifted in a future release. So don't come for her about it, she's working on it 😀

πŸ‘‘ AUTHOR πŸ‘‘

Peter Sergeant pete@clueball.com


πŸ’– LICENSE πŸ’–

Copyright 2019-2023, Erik Huelsmann
Copyright 2011-2019, Peter Sergeant; Licensed under the same terms as Perl

okay that's the whole tour bestie, tysm for reading πŸ₯Ή this was Perl v5.40.1, dated 2025-05-29, from the Test::...tecture(3pm) page in the User Contributed Perl Documentation β€” mwah, go write some features πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from