Gherkin syntax
Cucumber executes your .feature files, and those files contain executable specifications written in a language called Gherkin.Gherkin is plain-text English (or one of 60+ other languages) with a little extra structure. Gherkin is designed to be easy to learn by non-programmers, yet structured enough to allow concise description of examples to illustrate business rules in most real-world domains.
Like YAML or Python, Gherkin is a line-oriented language that uses indentation to define structure. Line endings terminate statements (called steps) and either spaces or tabs may be used for indentation. Finally, most lines in Gherkin start with a special keyword:
When you’re executing the feature, the trailing portion of each step (after keywords like Given, And, When, etc) is matched to a regular expression, which executes JAVA callback function.
In Gherkin, each line that isn't blank has to start with a Gherkin keyword, followed by any text you like. The main keywords are:
features
Occasionally you'll find yourself repeating the same Given steps in all of the scenarios in a feature file. Since it is repeated in every scenario it is an indication that those steps are not essential to describe the scenarios, they are incidental details.
You can literally move such Given steps to the background by grouping them under a Background section before the first scenario.
The following scenarios each have 3 steps:
If none of these places suit you, you can start a line with a # to tell Cucumber that the remainder of the line is a comment, and shouldn't be executed.
Gherkin is available in many languages, allowing you to write stories using localized keywords from your language. In other words, if you speak French, you can use the word Fonctionnalité instead of Feature.
When you’re executing the feature, the trailing portion of each step (after keywords like Given, And, When, etc) is matched to a regular expression, which executes JAVA callback function.
In Gherkin, each line that isn't blank has to start with a Gherkin keyword, followed by any text you like. The main keywords are:
- Feature
- Scenario
- Given, When, Then, And, But (Steps)
- Background
- Scenario Outline
- Examples
- """ (Doc Strings)
- | (Data Tables)
- @ (Tags)
- # (Comments)
Here, Syntax for the feature,
Feature: My first testing application
I want test login feature on my application
Scenario: Some determinable business situation
Given some precondition
And some other precondition
When some action by the actor
And some other action
And yet another action
Then some testable outcome is achieved
And something else we can check happens too
Scenario: A different situation
-------
The parser divides the input into features, scenarios and steps. Let’s walk through the above example:- Feature: My first testing application starts the feature and gives it a title. Learn more about features in the “Features” section.
- These lines simply provide context to the people reading your feature, and describe the business value derived from the inclusion of the feature in your software.
- Scenario: Some determinable business situation starts the scenario, and contains a description of the scenario. Learn more about scenarios in the “Scenarios” section.
- The next 7 lines are the scenario steps, each of which is matched to a regular expression defined elsewhere. Learn more about steps in the “Steps” section.
- Scenario: A different situation starts the next scenario, and so on.
features
Every *.feature file conventionally consists of a single feature. Lines starting with the keyword Feature: (or its localized equivalent) followed by three indented lines starts a feature. A feature usually contains a list of scenarios. You can write whatever you want up until the first scenario, which starts with Scenario: (or localized equivalent) on a new line. You can use "tags" to group features and scenarios together, independent of your file and directory structure.
Every scenario consists of a list of "steps", which must start with one of the keywords Given, When, Then, But or And (or localized one).Here is an example:
Every scenario consists of a list of "steps", which must start with one of the keywords Given, When, Then, But or And (or localized one).Here is an example:
Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1 dollar When I press the coffee button Then I should be served a coffee
Steps
A step typically starts with Given, When or Then. If there are multiple Given or When steps underneath each other, you can use And or But. Cucumber does not differentiate between the keywords, but choosing the right one is important for the readability of the scenario as a whole.
Given
Given steps are used to describe the initial context of the system—the scene of the scenario. It is typically something that happened in the past.
When Cucumber executes a Given step it will configure the system to be in a well-defined state, such as creating and configuring objects or adding data to the test database.
It's ok to have several Given steps (just use And or But for number 2 and upwards to make it more readable).
When
When steps are used to describe an event, or an action. This can be a person interacting with the system, or it can be an event triggered by another system.
It's strongly recommended you only have a single When step per scenario. If you feel compelled to add more it's usually a sign that you should split the scenario up in multiple scenarios.
Then
Then steps are used to describe an expected outcome, or result.
The step definition of a Then step should use an assertion to compare the actual outcome (what the system actually does) to the expected outcome (what the step says the system is supposed to do).
Tags
Tags are a way to group Scenarios. They are @-prefixed strings and you can place as many tags as you like above Feature, Scenario, Scenario Outline or Examples keywords. Space character are invalid in tags and may separate them.
Tags are inherited from parent elements. For example, if you place a tag above a Feature, all scenarios in that feature will get that tag.
Similarly, if you place a tag above a Scenario Outline or Examples keyword, all scenarios derived from examples rows will inherit the tags.
You can tell Cucumber to only run scenarios with certain tags, or to exclude scenarios with certain tags.
Tags are inherited from parent elements. For example, if you place a tag above a Feature, all scenarios in that feature will get that tag.
Similarly, if you place a tag above a Scenario Outline or Examples keyword, all scenarios derived from examples rows will inherit the tags.
You can tell Cucumber to only run scenarios with certain tags, or to exclude scenarios with certain tags.
Example:
@billing
Feature: Verify billing
@important
Scenario: Missing product description
Scenario: Several products
A Scenario or Feature can have as many tags as you like, just separate them with spaces:
@billing @bicker @annoy
Feature: Verify billing
If a tag exists on a Feature, It will assign that tag to all child Scenarios and Scenario Outlines too.
backgrounds
You can literally move such Given steps to the background by grouping them under a Background section before the first scenario.
Backgrounds allows you to add some context to all scenarios in a single feature. A Background is like an untitled scenario, containing a number of steps. The difference is when it is run: the background is run before each of your scenarios, but after your BeforeScenario hooks
Examples:
Background: Given a $100 microwave was sold on 2015-11-03 And today is 2015-11-18
scenarios
Scenario is one of the core Gherkin structures. Every scenario starts with the Scenario: keyword (or localized one), followed by an optional scenario title. Each feature can have one or more scenarios, and every scenario consists of one or more steps.The following scenarios each have 3 steps:
Scenario: Shiva posts to his own blog Given I am logged in as Shiva When I try to post to "Cucumber Test automation" Then I should see "Your article was published." Scenario: Shiva fails to post to somebody else's blog Given I am logged in as Shiva When I try to post to "Selenium web driver basics" Then I should see "Hey! That's not your blog!" Scenario: Kumar posts to a client's blog Given I am logged in as Kumar When I try to post to "Web Automation Testing" Then I should see "Your article was published."
Comments
Gherkin provides lots of places to document your features and scenarios. The preferred place is descriptions. Choosing good names is also useful.If none of these places suit you, you can start a line with a # to tell Cucumber that the remainder of the line is a comment, and shouldn't be executed.
scenario outlines
Copying and pasting scenarios to use different values can quickly become tedious and repetitive:Scenario: Eat 5 out of 12 Given there are 12 cucumbers When I eat 5 cucumbers Then I should have 7 cucumbers Scenario: Eat 5 out of 20 Given there are 20 cucumbers When I eat 5 cucumbers Then I should have 15 cucumbers
Scenario Outlines allow us to more concisely express these examples through the use of a template with placeholders:
Scenario Outline: Eating
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |
The Scenario outline steps provide a template which is never directly run. A Scenario Outline is run once for each row in the Examples section beneath it (not counting the first row of column headers).
The Scenario Outline uses placeholders, which are contained within < > in the Scenario Outline’s steps. For example:
Given <placeholder example>Think of a placeholder like a variable. It is replaced with a real value from the Examples: table row, where the text between the placeholder angle brackets matches that of the table column header. The value substituted for the placeholder changes with each subsequent run of the Scenario Outline, until the end of the Examples table is reached.
So when running the first row of our example:
Scenario Outline: controlling order Given there are <start> cucumbers When I eat <eat> cucumbers Then I should have <left> cucumbers Examples: | start | eat | left | | 12 | 5 | 7 |
The scenario that is actually run is:
Scenario Outline: controlling order # <start> replaced with 12: Given there are 12 cucumbers # <eat> replaced with 5: When I eat 5 cucumbers # <left> replaced with 7: Then I should have 7 cucumbers
Note:
- You can also use placeholders in Multi line Arguments.
- Your step definitions will never have to match the placeholder text itself, but rather the values replacing the placeholder.
multi line argumentsThe regular expression matching in steps lets you capture small strings from your steps and receive them in your step definitions. However, there are times when you want to pass a richer data structure from a step to a step definition. This is what multi line step arguments are for. They are written on lines immediately following a step, and are passed to the step definition method as the last argument. Multi line step arguments come in two flavors: tables or pystrings.
tables
Tables as arguments to steps are handy for specifying a larger data set - usually as input to a Given or as expected output from a Then.Scenario: Given the following people exist: | name | email | phone | | Aslak | aslak@email.com | 123 | | Joe | joe@email.com | 234 | | Bryan | bryan@email.org | 456 |
Don’t be confused with tables from scenario outlines - syntactically they are identical, but have a different purpose.
pystrings
Multi line Strings (also known as PyStrings) are handy for specifying a larger piece of text. This is done using the so-called PyString syntax. The text should be offset by delimiters consisting of three double-quote marks (""") on lines by themselves:
Scenario:
Given a blog post named "Random" with:
"""
Some Title, Eh?
===============
Here is the first paragraph of my blog post.
Lorem ipsum dolor sit amet, consectetur adipiscing
elit.
"""
The inspiration for PyString comes from Python where """ is used to delineate doc strings, much in the way /* ... */ is used for multi line doc blocks .
gherkin in many languages
Tips for creating effective features
1. Feature Files Should Actually be Features, Not Entire Portions of an App
One feature per well named file, please, and keep the features focused.
2. Avoid Inconsistencies with Domain Language
- You'll get the most benefit out of using Cucumber when your customers are involved.
- To that end, make sure you use their domain language when you write stories.
- The best course of action is to have them involved in writing the stories.
3. Organize Your Features and Scenarios with the Same Thought You Give to Organizing Your Code
One useful way to organize things is by how fast they run. Use 2-3 levels of granularity for this:
- Fast: scenarios that run very fast, e.g. under 1/10 of a second
- Slow: scenarios that are slower but not painfully so, maybe under one second each
- Glacial: scenarios that take a really long time to run
You can do this separation several different ways (and even some combination):
- Put them in separate features
- Put them in separate subdirectories
- Tag them
4. Use Tags
Tags are a great way to organize your features and scenarios in non functional ways. You could use @small, @medium and @large, or maybe @hare, @tortoise, and @sloth. Using tags let you keep a feature's scenarios together structurally, but run them separately. It also makes it easy to move features/scenarios between groups, and to have a given feature's scenarios split between groups.
The advantage of separating them this way is that you can selectively run scenarios at different times and/or frequencies, i.e. run faster scenarios more often, or run really big/slow scenarios overnight on a schedule.
Tagging has uses beyond separating scenarios into groups based on how fast they are:
When they should be run: on @checkin, @hourly, @daily
What external dependencies they have: @local, @database, @network
Level: @functional, @system, @smoke
Etc.
5. Use Rake Tasks to Run Features
This provides a consistent environment for running features: this way each run uses the same set of options and parameters. This goes a long way toward maintaining deterministic results.
Another benefit is that this makes for easy integration with continuous integration tools. There is a single point of entry into the spec run, with all options/parameters encapsulated.
6. Don't Get Carried Away with Backgrounds (Stick to Givens)
The larger the background, the greater the load of understanding for each scenario. Scenarios that contain all the details are self-contained and as such, can be more understandable at a glance.
7. Make Scenarios Independent and Deterministic
There shouldn't be any sort of coupling between scenarios. The main source of such coupling is state that persists between scenarios. This can be accidental, or worse, by design. For example one scenario could step through adding a record to a database, and subsequent scenarios depend on the existence of that record.
This may work, but will create a problem if the order in which scenarios run changes, or they are run in parallel. Scenarios need to be completely independent.
Each time a scenario runs, it should run the same, giving identical results. The purpose of a scenario is to describe how your system works. If you don't have confidence that this is always the case, then it isn't doing its job. If you have non-deterministic scenarios, find out why and fix them.
8. Write Scenarios for the Non-Happy-Path Cases As Well
Happy path tests are easy; edge cases and failure scenarios take more thought and work.
No comments:
Post a Comment