Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tags #34

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions SUMMARY.md
Expand Up @@ -70,10 +70,9 @@
* [Tags](docs/tags.md)
* [Background](docs/gherkin.md#background)
* [Scenario Outline](docs/gherkin.md#background)
* [Background](gdocs/herkin.md#background)
* [Data Tables](docs/gherkin.md#background)
* [Doc Strings](docs/gherkin.md#background)
* [Comments](#)
* [Doc Strings](docs/gherkin.md#doc-strings)
* [Comments](docs/gherkin.md#comments)
* [Internationalisation](#)
* [Step Definitions](docs/step-definitions.md)
* [Regular Expressions](#)
Expand Down
204 changes: 204 additions & 0 deletions docs/gherkin.md
@@ -0,0 +1,204 @@
# Gherkin

Gherkin is the language that Cucumber understands. It is a Business Readable, [Domain Specific Language](http://martinfowler.com/bliki/BusinessReadableDSL.html) that lets you describe software’s behaviour without detailing how that behaviour is implemented.

Gherkin serves two purposes — documentation and automated tests. The third is a bonus feature — when it yells in red it’s talking to you, telling you what code you should write.

Gherkin’s grammar is defined in the Treetop grammar that is part of the Cucumber codebase. The grammar exists in different flavours for many spoken languages (37 at the time of writing), so that your team can use the keywords in your own language.

There are a few conventions.

* Single Gherkin source file contains a description of a single feature.
* Source files have `.feature` extension.

## Gherkin Syntax

Like Python and YAML, Gherkin is a line-oriented language that uses indentation to define structure. Line endings terminate statements (eg, steps). Either spaces or tabs may be used for indentation (but spaces are more portable). Most lines start with a keyword.

Comment lines are allowed anywhere in the file. They begin with zero or more spaces, followed by a hash sign (`#`) and some amount of text.

The parser divides the input into features, scenarios and steps. When you run the feature the trailing portion (after the keyword) of each step is matched to a Ruby code block called [Step Definitions](docs/step-definitions.md).

A Gherkin source file usually looks like this
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add gherkin after backticks to get syntax highlighting

1: Feature: Some terse yet descriptive text of what is desired
2: Textual description of the business value of this feature
3: Business rules that govern the scope of the feature
4: Any additional information that will make the feature easier to understand
5:
6: Scenario: Some determinable business situation
7: Given some precondition
8: And some other precondition
9: When some action by the actor
10: And some other action
11: And yet another action
12: Then some testable outcome is achieved
13: And something else we can check happens too
14:
15: Scenario: A different situation
16: ...
```

First line starts the feature. Lines 2–4 are unparsed text, which is expected to describe the business value of this feature. Line 6 starts a scenario. Lines 7–13 are the steps for the scenario. Line 15 starts next scenario and so on.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd avoid referring to line numbers unless we can display them in the margin somehow. Maybe GitBook has a plugin for that?


Read more

* [Feature Introduction](docs/gherkin.md#feature) – general structure of a feature
* [Given/When/Then (Steps)](docs/gherkin.md#steps)

## Feature Introduction {#feature}

Every `.feature` file conventionally consists of a single feature. A line starting with the keyword Feature followed by free indented text 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 the word Scenario (or localized equivalent; Gherkin is localized for [dozens of languages](https://github.com/cucumber/cucumber/wiki/Spoken-languages)) on a new line. You can use tagging to group features and scenarios together independent of your file and directory structure.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Start by explaining that a Cucumber feature is a grouping of related scenarios, describing the same software feature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please break long lines. Makes commenting easier.


Every scenario consists of a list of steps, which must start with one of the keywords **Given, When, Then, But** or **And**. Cucumber treats them all the same, but you shouldn’t. Here is an example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bold each word (without the comma inside).

Saying people should treat the differently without explaining how isn't helpful (people are very confused about it).

  • Given describes the current state of the world. It can also describe something that has happened in the past.
  • When is an event, or an action that is expected to cause an observable change
  • Then is an expected and observable outcome, or result


```
Feature: Serve coffee
Coffee should not be served until paid for
Coffee should not be served until the button has been pressed
If there is no coffee left then money should be refunded

Scenario: Buy last coffee
Given there are 1 coffees left in the machine
And I have deposited 1$
When I press the coffee button
Then I should be served a coffee
```

In addition to a scenario, a feature may contain a background, scenario outline and examples. Respective keywords (in English) and places to read more about them are listed below. You can get a list of localized keywords with cucumber `--i18n [LANG]`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalise keywords, and link to their section.

Don't assume Ruby - we should rather generate docs with all the translations.


| keyword | localized | more info see |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a bullet list where you only use the last column. The first two columns aren't useful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove file path from links, use anchors only

|-----------------|-------------------------|-------------------|
| name | 'English' | |
| native | 'English' | |
| encoding | 'UTF-8' | |
| feature | 'Feature' | [Feature](gherkin.md#feature)
| background | 'Backgroound' | [Background](gherkin.md#background)
| scenario | 'Scenario' | [Scenario](gherkin.md#feature)
| scenario_outline| 'Scenario Outline' | [Scenario Outline](gherkin.md#background)
| examples | 'Examples'/ 'Scenarios' | [Scenario Outline](docs/gherkin.md#background)
| given | 'Given' | [Given/When/Then (Steps)](docs/gherkin.md#steps)
| when | 'When' | [Given/When/Then (Steps)](docs/gherkin.md#steps)
| then | 'Then' | [Given/When/Then (Steps)](docs/gherkin.md#steps)
| and | 'And' | [Given/When/Then (Steps)](docs/gherkin.md#steps)
| but | 'But' | [Given/When/Then (Steps)](docs/gherkin.md#steps)

## Step definitions {#steps}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step definitions don't belong in this document. Please move to a separate step-definitions.md doc, in a separate PR.


For each step Cucumber will look for a matching **step definition**. A step definition is written in Ruby. Each step definition consists of a keyword, a string or regular expression, and a block. Example:

```
# features/step_definitions/coffee_steps.rb

Then "I should be served coffee" do
@machine.dispensed_drink.should == "coffee"
end
```

Step definitions can also take parameters if you use regular expressions:

```
# features/step_definitions/coffee_steps.rb

Given /there are (\d+) coffees left in the machine/ do |n|
@machine = Machine.new(n.to_i)
end
```

This step definition uses a regular expression with one match group – `(\d+)`. (It matches any sequence of digits). Therefore, it matches the first line of the scenario. The value of each matched group gets yielded to the block as a string. You must take care to have the same number of regular expression groups and block arguments. Since block arguments are always strings, you have to do any type conversions inside the block, or use Step Argument Transforms.

When Cucumber prints the results of the running features it will underline all step arguments so that it’s easier to see what part of a step was actually recognised as an argument. It will also print the path and line of the matching step definition. This makes it easy to go from a feature file to any step definition.

Take a look at [Step Definitions](docs/step-definitions.md) and the examples directory to see more.

## Background {#background}

A background section in a feature file allows you to specify a set of steps that are common to every scenario in the file. Instead of having to repeat those steps over and over for each scenario, you move them up into a Background element. There are a couple of advantages to doing this:

A Background is much like a scenario containing a number of steps. The difference is when it is run. The background is run before each of your scenarios but after any of your Before [Hooks](hooks.md).

Example:

```
Feature: Change PIN
#some feature description comes here

Background:
Given I have been issued a new card
And I insert the card, entering the correct PIN
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you express these steps in past tense please?

And I choose "Change PIN" from the menu

Scenario: Change PIN successfully
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unindent these two scenarios to be at the same level as the background

When I change the PIN to 9876
Then the system should remember my PIN is now 9876

Scenario: Try to change PIN to the same as before
When I try to change the PIN to the original PIN number
Then I should see a warning message
And the system should not have changed my PIN
```

You can have a single `Background` element per feature file, and it must appear before any of the `Scenario` or `Scenario Outline` elements. Just like all the other _Gherkin_ elements, you can give it a name, and you have space to put a multiline description before the first step. For example:

```
Feature: Change PIN
In order to be able to change it to something they can easily
remember, customers with new bank cards need to be able to
change their PIN using the ATM.

Background: Insert a newly issued card and sign in
Whenever the bank issues new cards to customers, they are supplied
with a Personal Identification Number (PIN) that is randomly
generated by the system.

Given I have been issued a new card
And I insert the card, entering the correct PIN
...
```

### Good practices for using Background

* Don’t use `Background` to set up complicated state unless that state is actually something the client needs to know.
* Keep your `Background` section short.
* Make your `Background` section vivid.
* Keep your scenarios short and don’t have too many.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good guideline, but it's not about Background, is it?


## Doc Strings {#doc-strings}

Doc strings just allow you to specify a larger piece of text than you could fit on a single line. For example, if you need to describe the precise content of an email message, you could do it like this:

```
Scenario: Ban Unscrupulous Users
When I behave unscrupulously
Then I should receive an email containing:
"""
Dear Sir,
Your account privileges have been revoked due to your unscrupulous behavior.
Sincerely,
The Management
"""
And my account should be locked
```

Just like a [Data Tables](docs/gherkin.md#datatable), the entire string between the `"""` triple quotes is attached to the step above it. The indentation of the opening `"""` is not important, although common practice is to indent two spaces in from the enclosing step, as shown.

The indentation inside the triple quotes, however, is significant: imagine the left margin running down from the start of the first """. If you want to include indentation within your string, you need to indent it within this margin.

## Comments {#comments}

As well as the description fields that follow Feature and Scenario keywords, Cucumber allows you to precede these keywords with comments.
Like in Ruby, comments start with a `#` character. Unlike in Ruby, comments have to be the first and the only thing on a line (well, apart from whitespace).

Here’s an example:
```
# This feature covers the account transaction and hardware-driver modules
Feature: Withdraw Cash
In order to buy beer
As an account holder
I want to withdraw cash from the ATM

# Can't figure out how to integrate with magic wand interface
Scenario: Withdraw too much from an account in credit
...
```

83 changes: 83 additions & 0 deletions docs/hooks.md
@@ -0,0 +1,83 @@
# Hooks

Cucumber provides a number of hooks which allow us to run blocks at various points in the Cucumber test cycle. You can define them anywhere in your support or step definition layers, using the methods `Before` and `After`. Hooks are global by default, meaning they run for every scenario in your
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/layers/code/

features. If you want them to run for just certain scenarios, you need to tag
those scenarios and then use a [tagged hook](hooks.md#tagged-hooks).

## Scenario hooks

`Before` hooks will be run before the first step of each scenario. They will run in the same order of which they are registered.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make a h3 section for Before and After hooks? can you also describe how Before hooks are similar to Background, and when to use each one? (Before hooks are for techynthings like starting browsers or servers, starting database transactions etc,


```
Before do
# Do something before each scenario.
end
```

or like this:

```
Before do |scenario|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discourage this kind of logging - Cucumber's own formatters take care of that. Instead, show something more useful you can do with a Scenario object, like embedding something into the reports, like an image (typically from a screenshot) or text.

# The +scenario+ argument is optional, but if you use it, you can get the title,
# description, or name (title + description) of the scenario that is about to be
# executed.
Rails.logger.debug "Starting scenario: #{scenario.title}"
end
```

`After` hooks will be run after the last step of each scenario, even when there are failing, undefined, pending or skipped steps. They will run in the opposite order of which they are registered.

```
After do |scenario|
# Do something after each scenario.
# The +scenario+ argument is optional, but
# if you use it, you can inspect status with
# the #failed?, #passed? and #exception methods.

if scenario.failed?
subject = "[Project X] #{scenario.exception.message}"
send_failure_email(subject)
end
end
```

`Around` hooks give you more power than Before and After hooks, allowing you to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Around hooks have caused a lot of pain, and it's a feature we're likely to deprecate and eventually remove. It only exists for ruby. I suggest not documenting it (and perpetuating its use).

actually control how many times the scenario is run. An Around hook is passed
two parameters: an object that represents the scenario and a block of code
that, when called, will run the scenario:

```
Around do |scenario, block|
puts "About to run #{scenario.name}"
block.call
puts "Finished running #{scenario.name}"
end
```

`Around` hooks also accept tags, so you can restrict them to run for only some
scenarios, just like `Before` and `After` hooks. One great trick we’ve seen them used for is to run the same scenario twice under different conditions, like this:

```
Around('@run_with_and_without_javascript') do |scenario, block|
Capybara.current_driver = Capybara.javascript_driver
block.call
Capybara.use_default_driver
block.call
end
```

## Tagged hooks {#tagged-hooks}

Both `Before` and `After` accept a tag expression, which you can use to selectively add the hook to only certain scenarios.

```
@admin
Feature: Delete Widgets
...
Before('@admin') do
user = create_user(:admin => true)
login_as user
end
```

Now, to run a scenario when you need to be logged in as an administrator, you just have to tag the scenario with `@admin`, and this code will automatically run before the steps of the scenario.
31 changes: 31 additions & 0 deletions docs/tags.md
@@ -0,0 +1,31 @@
# 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please backtick-quote each keyword independently


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.

If you want to tag all the scenarios in a feature at once, just tag the `Feature` element at the top, and all the scenarios will inherit the tag. You can still tag individual scenarios as well.

Similarly, if you place a tag above a `Scenario Outline` or `Examples` keyword, all scenarios derived from examples rows will inherit the tags.

A `Scenario` or `Feature` can have as many tags as you like. Just separate them with spaces:

```
@billing @bicker @annoy
Feature: Verify billing
```

You can tell Cucumber to only run scenarios with certain tags, or to exclude scenarios with certain tags.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant with the 3 reasons you mention below. Remove this section?


Cucumber can perform different operations before and after each scenario based on what tags are present on a scenario.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant. Remove?


There are three main reasons for tagging scenarios:

* _Documentation_: You simply want to use a tag to attach a label to certain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the least interesting reason I think. Move down to the bottom.

scenarios, for example to label them with an ID from a project management
tool.
* _Filtering_: Cucumber allows you to use tags as a filter to pick out specific scenarios to run or report on. You can even have Cucumber fail your test run if a certain tag appears too many times.
* _Hooks_: Run a block of Ruby code whenever a scenario with a particular
tag is about to start or has just finished.

See [tagged hooks](hooks.md#tagged-hooks) for more details.