Meta Matchers

One of the principal use cases for defining meta info in our stories is to be able to filter the stories based on the meta info provided.

A meta filter is represented as a string and supports multiple meta matcher languages based on the prefix used:

  • default meta matcher: activated if no known prefix is found
  • groovy meta matcher: needs to prefixed by groovy:

Default Meta Matcher

The default meta matcher has a very simple language structure that mirrors that of the meta properties, expressed as a sequence of name-value patterns:

   default meta matcher :== ([+|-] [name] [value pattern])+

where [+|-] indicates if the filter should include or exclude the meta property and the [value pattern] can be either an exact match of the property value (including empty value) or use the * matching notation.

The following are all valid meta matchers:

   +author Mauro
   +theme filtering
   +author * +theme filtering
   +author * +theme filtering -skip
   -skip

A few examples of meta matchers and properties that matched or not:

Meta MatcherMeta PropertyMatched
+theme smoke testing -skip@theme smoke testingtrue
+theme smoke testing -skip@skipfalse
+theme smoke testing@theme smoke testingtrue
+theme smoke testing@theme testingfalse
-skip@theme testingtrue
-skip@skipfalse
+theme smoke testing -theme UI@theme smoke testingtrue
+theme smoke testing -theme UI@theme UIfalse

Groovy Meta Matcher

The Groovy meta matcher allows the logic of the matching to be expressed in Groovy using the values of the meta property names and values:

The following are all valid meta matchers (excluding the "groovy:" prefix):

   author == 'Mauro'
   !skip
   theme == 'filtering' && theme != 'smoke testing' 
   theme ==~ /.*[testing|regression].*/
As Groovy is an optional dependency, users wanting to use the Groovy Meta Matcher need to add it to the runtime classpath. If using Maven, you need to define Groovy as a Plugin dependency, c.f. Maven goals.

Custom Meta Matchers

Custom meta matcher instances can also be provided to the Embedder as a map, indexed by the prefix used in the filter content:

The filter content will then need to start by the same prefix defined in the map:

    ruby: # some ruby matching code

Custom instances that are matched by the prefix of the filter content will take precedence over the Groovy or default matchers.

Users wanting to use a custom Meta Matcher need to add to the runtime classpath any dependencies required by the implementation of the matcher. If using Maven, you need to define them as a Plugin dependency, c.f. Maven goals.

Filtering on Story and Scenario Elements

In addition to the meta info that is defined by the user, both at story and scenario level, JBehave also exposes the top-level elements of stories and scenarios, which can be filtered on. These include:

  • story: path, description and narrative
  • scenario: title, givenStories and examplesTable
The meta properties are exposed by default with no prefix, but can be configured to have one via the configuration StoryControls:

configuration.storyControls().useStoryMetaPrefix("story_").useScenarioMetaPrefix("scenario_");

Filtering on Example Scenarios

Meta info can also be specified to filter the example scenarios to be run:

Scenario:  A scenario with filtering on examples

Meta:  @os 

Given an operating system [value]

Examples:
|Meta:|value|
|@os Linux|Ubuntu|
|@os Unix|OS X| 

To activate meta-filtering on example scenarios, add a column Meta: (or equivalent Meta keyword in your language locale). If the meta info in a given row of the column is matched by the meta filter, the corresponding scenario is run.

Note that because the meta filter is unique, this must also match the containing scenario or story. For example, if the rows are filtered on a meta property value, this can be ensured by the presence of the property name (without value) at the scenario level.

Configuring Meta Filters

As usual, JBehave allow multiple equivalent ways of configuration. One can specify the meta filters directly via the Embedder, either programmatically or via the annotation:

Embedder embedder = ... // define as required
embedder.useMetaFilters(asList("+author Mauro", "+theme filtering", "-skip"));
@RunWith(AnnotatedEmbedderRunner.class)
@UsingEmbedder(metaFilters = {"+author Mauro", "+theme filtering", "-skip"})
public class AnnotatedTraderEmbedder extends InjectableEmbedder {
}

The meta filters can also be specified via Ant tasks or Maven goals, using the "metaFilters" attribute or configuration element.

Note that because of its additive sequential nature, the meta filters will all be joined together when running the stories. Have different meta filters comes into play when doing story mapping.