-
Notifications
You must be signed in to change notification settings - Fork 11
Cucumber
Cucumber is a Behavior-Driven Development(BDD) framework.
BDD is a technique in agile software development to achieve a close collaboration between the quality assurance and the business analysis parts of the team. The team focuses on the targets of the stakeholders. The user stories are written in a natural language that follows a known structure and utilizes certain keywords to provide some kind of API that can be used by the developers later on to implement the test automation.
Cucumber itself is a popular BDD framework that provides some structural elements to orchestrate the test and uses Gherkin a defined set of keywords to differentiate and organize the steps.
- Feature is equivalent to a JUnit test class
- Scenario is matching a JUnit test method
- Scenario Outline is matching a JUnit test method with an attached test data table (Examples see below)
- Background could be seen as a JUnit @Before annotated method to set up the environment for each test method in the same way
- Examples is used to set up test data for a Scenario
It is good to know that the keywords are just used to build up a more natural language but the implementation it self doesn't differentiate between. This means you could use the And keyword all the time an it wouldn't make a difference for the execution of the script.
-
Given
: mostly the start of a scenario, but can be used for prerequisites -
When
: a start to describe the interaction with the page -
Then
: the keyword to bring up validation phrases -
And
: is used to chain all kinds of phrases -
But
: can be used to start and chain any kind of negative phrases
The following example show some basic structure of a test case and demonstrates the usage of the keywords.
Feature: Browse
Scenario Outline: Browsing the catalog
Given The browser "<browser>" is open
And I am on the homepage of the Posters shop
When I hover over "<categoryName>" and click on "<subCategoryName>"
Then I want to be on a category page and see the "<subCategoryName>" as headline
When I click on the product "<productName>"
Then I want to be on a product detail page and see the "<productName>" as headline
Examples:
| browser | categoryName | subCategoryName | productName |
| Chrome_1024x768 | World of Nature | Animals | Grizzly Bear |
| Chrome_1024x768 | Dining | Main Dishes | Tuna Steak |
| Chrome_1024x768 | Dining | Sweets | Colored Sprinkles |
Neodymium provides an utility class that can be called statically from you Cucumber support (hook) classes. It's called Driver and provides the functionality to setup and tear down WebDrivers. You can choose between the following two ways to setup a WebDriver via Neodymium. The tear down will stay the same for both. Please find a hands on example here: DriverHooks.java.
By calling a Cucumber Given
step and passing the browser profile name via the standard test data mechanism you can call the Neodymium WebDriverUtils
class to setup the browser.
@Given("^\"([^\"]*)\" is open$")
public static void setUp(final String browserProfileName)
{
Driver.setUp(browserProfileName);
}
The corresponding feature file could look like this. Each row of the example data leads to a WebDriver setup.
@Browse
Feature: Browse
Scenario Outline: Browsing the catalog
Given "<browser>" is open
And homepage is loaded
When I choose main category "<categoryName>" and sub category "<subCategoryName>"
Then I see category page with "<subCategoryName>" headline
Examples:
| browser | categoryName | subCategoryName |
| Chrome_1024x768 | Transportation | Air Travel |
| Chrome_1024x768 | World of Nature | Animals |
| FF_1024x768 | Dining | Main Dishes |
| FF_1024x768 | Dining | Sweets |
Please see the following example for more hand on experience: Browse.feature
If you don't need or want the extra step you can create a general before hook, that does the browser setup if it detects a configured browser profile name within the tags of the scenario. Beware tagging a test execution with more than one browser profile name will lead to an exception, since it can't be decided which was meant to run.
@Before()
public static void setUp(Scenario scenario)
{
Driver.setUpWithBrowserTag(scenario);
}
The corresponding feature file could look like this. Each row of the example data leads to a WebDriver setup.
@Search
Feature: Searching for products
Scenario Outline: Searching for existing products
Given homepage is loaded
When I search for "<searchTerm>"
Then I see category page
And result page contains searchterm "<searchTerm>" and shows "<expectedCount>" products
And product "<productName>" is visible
@Chrome_1024x768
Examples:
| searchTerm | expectedCount | productName |
| bear | 3 | Grizzly Bear |
@FF_1024x768
Examples:
| searchTerm | expectedCount | productName |
| bee | 9 | Indian Summer: Orange Beech |
Please see the following example for more hand on experience: Search.feature
Note: Since we demonstrate both ways of setting up the WebDriver in the same demo project we had to add a special tag to the hook and the test case to avoid interferences. Probably you won't need this in your project.
To tear down the WebDriver you just need to add a general hook. Beware you need to pass an order number below 10000 to run it after all other After
hooks. Doing so you make sure that the browser will be teared down once all standard After
steps have been executed.
@After(order = 100)
public void tearDown(Scenario scenario)
{
Driver.tearDown(scenario);
}
Sometimes test cases need a special setup on execution. In a perfect test world you could just start your test with a new prepared environment but since this can't be realized in every case you need to clean up after the test execution. Cucumber supports hooks to add an After
step after a scenario but you can't share data between different step without further programming. We present an easy solution to the problem below.
We demonstrate how to share data between steps using Cucumber PicoContainer. This technique is used to implement clean up steps for Register.feature
- Add Cucumber PicoContainer to to your project
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>[Should match the Cucumber version of the Neodymium library]</version>
<scope>test</scope>
</dependency>
- Implement a global storage object that can hold the data that is supposed to be shared. Please see GlobalStorage.java example.
- This should ideally be a POJO that just holds data fields that can be other POJOs.
- Use dependency injection to set data. Please see DataSetup.java example.
- The
GlobalStorage
is passed in via constructor dependency injection into the setup class. - We introduced this extra class in order to avoid messing up your page objects with data set up for cucumber. One reason is that this would be needlessly executed during the Neodymium test. The other reason is that the a second constructor would be needed, since the Selenide page concept relies on a constructer without arguments and this causes more struggle for the page object code.
- The
- Use dependency injection to read the data. Please see UserHooks.java example.
- The
GlobalStorage
is passed in via constructor dependency injection into the hook class. - The
@After
annotation registers a hook after a scenario which is tagged with the tag given to the annotation. See Cucumber documentation for more information.
- The
Overview
Neodymium features
- Neodymium configuration properties
- Neodymium context
- Utility classes
- Test data provider
- Test Environments
- Multi browser support
- Applitools Plugin
- Localization
- Highlight and Wait
- Advanced Screenshots
- Seperate Browser Sessions for Setup and Cleanup
Best practices and used frameworks
Special