This document describes the internal data structure of a Clornichon feature after parsing from Gherkin text. Understanding this structure is helpful when extending or customizing Clornichon.
A feature is represented as a map with the following keys:
{:scenarios [...] ; Vector of scenario maps
:feature "..." ; The Feature title
:description "..." ; Optional free text between the Feature line and the first keyword
:annotations #{...} ; Optional annotations (tags)
:pre-run [...] ; Hooks to execute before the feature
:post-run [...] ; Hooks to execute after the feature
:messages [...] ; The parser's Source, GherkinDocument and Pickle envelopes, for cucumber-messages
:status :success/:fail ; Status after execution
:exception ... ; What a :pre-run or :post-run hook threw, if one did
}
A narrative (As a … I want to … So that …) has no structure of its own: per
the gherkin spec it is free text under the Feature line, so it lands in
:description.
Annotations (tags) are stored as a set of strings:
{:annotations #{"smoke" "regression" "api"}}
Each scenario is represented as a map within the :scenarios vector:
{:id "uuid-string" ; The pickle's id
:scenario-name "Name" ; The scenario title
:annotations #{...} ; Optional annotations (tags) of the scenario
:description "..." ; Optional free text under the scenario line
:rule {:id "..." :name "..." ; Only in a Rule: the rule grouping the scenario,
:annotations #{...} ; its own tags and description (the scenario
:description "..."} ; already inherits the tags in :annotations)
:steps [...] ; Vector of step maps
:pre-run [...] ; Hooks to run before the scenario
:post-run [...] ; Hooks to run after the scenario
:default-state {} ; Initial state for the scenario
:status :success/:fail/:pending ; Execution status
:exception ... ; What a hook threw, if one did
:started-at 1790511573279 ; Epoch millis, once run
:finished-at 1790511573301
}
Each step within a scenario is represented as a map:
{:id "uuid-string" ; The pickle step's id
:sentence-keyword :given/:when/:then/:and ; Step type
:sentence "Step text" ; The actual step text
:raw "Given Step text" ; Full text with keyword
:order 0 ; Position in scenario
:glue {...} ; Matched step definition
:params [...] ; The glue's captures, then the datatable/docstring block
:status :success/:fail/:pending ; Execution status
:input-state {} ; State before execution
:output-state {} ; State after execution
:exception {...} ; If step failed
:started-at 1790511573279 ; Epoch millis, once run
:duration-ns 1234567 ; Time the glue took, once run
}
Parameters extracted from steps come in three types:
;; Value parameters (extracted from step text)
{:type :value, :val "some string"}
{:type :value, :val 42}
;; Table parameters
{:type :table,
:val [{:header1 "value1", :header2 "value2"},
{:header1 "value3", :header2 "value4"}]}
;; Doc string parameters (multi-line text blocks)
{:type :doc-string,
:val "This is a multi-line\ntext block that can contain\nany content including markdown"}
;; A doc string opened with a content type (```json) carries it
{:type :doc-string, :val "{\"a\": 1}", :media-type "json"}
Each hook of :pre-run / :post-run is the metadata of its var, plus:
{:ref #'user.namespace/clean-db! ; The hook itself
:arglists ([] ...) ; From the var: a single one-argument arity receives the context
:scenari/tags "@db" ; Optional tag expression, from the var's metadata
:tag-expr #object[...] ; That expression, parsed when the feature is loaded
}
The :glue key contains information about the matched implementation function:
{:step "I do something {string}" ; Pattern to match
:ns user.namespace ; Function namespace
:name function-name ; Function name
:ref #'user.namespace/function ; Reference to actual function
:warning "Warning message" ; Optional warning
}
io.cucumber/gherkin, into one pickle per runnable scenariofind-glue-by-step-regex:output-state and :statusio.cucumber/gherkin->feature-astrun-featurerun-stepThis data structure provides a flexible representation that preserves all information from the original Gherkin text while supporting execution, reporting, and integration with test frameworks.
Background, Rule and Scenario Outline have no representation in this
structure. Gherkin's pickle compiler resolves them away: a pickle is one
runnable scenario, and the feature map is a thin translation of it.
:steps
(the feature's background first, then the enclosing rule's, if any).:scenarios, inheriting its tags. Each carries the rule under
:rule, which the report and the Kaocha tree group them by.Examples row, with the
<placeholders> substituted throughout the scenario, its name included.Can you improve this documentation? These fine people already did:
Hiram MADELAINE & davidpanzaEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |