Meta Features

Branko Juric edited this page Aug 25, 2018 · 23 revisions

Gwen logo Meta Features

In addition to standard Gherkin features, Gwen also supports and introduces meta features. These are also defined in Gherkin and can provide powerful capabilities for eliminating redundancy. They also provide a clean separation between evaluation and configuration. Meta features are loaded into the interpreter on startup and can be used to initialise and configure the environment context for engines at load time.

See also:

Composable Step Definitions

@StepDef Scenarios

Composable step definitions allow you to declaratively compose custom steps in terms of other steps to create what are effectively callable procedures that can optionally accept parameters. They are declared exactly like scenarios but are annotated with the @StepDef tag and bind a sequence of steps to an expression that serves as the callable name. StepDefs can be defined in both standard features and meta features and are cached in the interpreter when loaded. They must be declared before any scenarios that use them, and are evaluated only when referenced by name in those scenarios or other StepDefs at runtime.

StepDefs and Meta

Composable step definitions and meta features are powerful capabilities that are unique to Gwen. It is a good idea to always define step definitions in meta files so that..

  • They do not clutter features
  • They can be reused across many features
  • They are maintained in one place
  • They separate configuration from specification

StepDefs with Parameters

Parameters can be declared in StepDefs using the <name> syntax and dereferenced with $<name>.

For example, you can define a step definition in a meta file as follows (here we borrow a practical example from the Gwen-Web engine):

File: features/Google.meta

   Feature: Google meta

  @StepDef
  Scenario: I do a google search for "<query>"

            This is a custom step definition that accepts a query string as 
            input and performs a google search on it and checks for a returned 
            match. It is not immediately executed but rather loaded into 
            memory and executed only when referenced in another step by name.

      Given I navigate to "http://www.google.com"
        And the search field can be located by name "q"
       When I enter "$<query>" in the search field
       Then the page title should start with "$<query>"
        And the first match can be located by class name "r"
        And the first result can be located by tag name "a" in the first match

You can then use this step definition in any other feature to perform a google search.

File: features/GoogleSearch.feature

   Feature: Google feature

  Scenario: Perform a google search
            
            This scenario calls the a step definition defined in the Goolge.meta
            file to perform a google search for "gwen-web". It then clicks the 
            first link in the returned results and checks the title and URL of 
            the page that is loaded.
            
      Given I do a google search for "gwen-web"
       When I click the first result
       Then the page title should contain "gwen-interpreter/gwen-web"
        And the current URL should be "https://github.com/gwen-interpreter/gwen-web"

If the meta and feature files are in the same directory, then Gwen will auto discover the meta. You can then launch the feature to perform the google search as follows (assuming you have Gwen-web installed and the bin directory is in your system path):

gwen features/GoogleSearch.feature`

If the meta resides in a different directory, then you can use the -m or --meta option to specify its location.

gwen features/GoogleSearch.feature -m other-dir/Google.meta
gwen features/GoogleSearch --meta other-dir/Google.meta

If you have the meta and feature files in a directory structure such as the following and invoke Gwen on the top level directory, then it will find and execute the feature and also auto-discover the meta (since it exists in the path to the feature file). In this case, you don't have to specify the -m/--meta option.

top-dir
top-dir/Google.meta
top-dir/features/GoogleSearch.feature

With the above file structure, Gwen will find the feature and auto discover the meta if you launch it on the top level directory.

gwen top-dir

See also:

Meta Imports

You can also explicitly import meta files into your feature files. This is useful for cases where you have many meta files and it is not practical to load all of them for every feature file. It is also useful for cases where the auto-meta-discovery and -m command line mechanisms are insufficient for controlling exactly what meta you want to load.

You can manage and control exactly what meta will be loaded by your features without ever having to specify it on the command line. This can help avoid redundant meta loads and also greatly improve performance and usability when you have a lot of meta spread across many files.

For example, say you have 10 meta files in a directory and you only want to load one of them when executing a feature. Previously, you could do this through the -m command line switch as follows:

gwen -m metadir/module1.meta test.feature

You could also load all 10 meta files as follows:

gwen -m metadir test.feature

Remembering exactly which meta to load for which features is impractical, and blindly loading all meta files to execute a feature that only uses one or some of them is wasteful.

With meta imports, we can do away with having to use the -m option altogether by adding the following annotation to the Feature declaration in each feature file. For example, we can declare what meta the test.feature file should load by specifying an import annotation in the feature file itself as follows:

test.feature file:

 @Import("metadir/module1.meta")
 Feature: test feature

Scenario: scenario 1
    Given I want ..
    ..

Now we can simply just specify the feature on the command line as follows:

gwen test.feature

Gwen will then load the meta file specified in the import before executing the steps in the feature.

You can add any number of meta imports to a feature. The following imports two meta files.

test.feature file:

 @Import("metadir/module1.meta")
 @Import("metadir/module2.meta")
 Feature: test feature

Scenario: scenario 1
    Given I want ..
    ..

You can also chain (or string together) meta imports across meta files. For example, if the module2.meta always requires module1.meta, then you can import the latter into the former:

metadir/module2.meta file:

 @Import("metadir/module1.meta")
 Feature: module 2 meta

@StepDef
Scenario: ..
    Given I want ..
    ..

Now any feature that imports module2.meta will also implicitly import module1.meta. For example, if we declare test.feature to import module2.meta as follows:

test.feature file:

 @Import("metadir/module2.meta")
 Feature: test feature

Scenario: scenario 1
    Given I want ..
    ..

..Then both module1.meta and module2.meta will be loaded (in that order) when the feature is executed without you having to specify any meta on the command line:

gwen test.feature

The path to the meta file in all import annotations is relative to the working directory where Gwen is invoked.

If a recursive (or cyclic) import is detected in an import chain, Gwen will report it by throwing an exception with a message specifying which import annotation was the culprit and the file it was declared in.

Meta imports are always loaded before any auto discovered meta files or -m command line meta files are loaded, and therefore have the least precedence so their contents can be shadowed.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.