Boilerplate project to run WebdriverIO tests with Cucumber. It is based on a framework called yadda and brings true BDD to JavaScript and WebdriverIO. Instead of writing complicated test code that only devs can understand, Cucumber maps an ordinary language to code and allows to start with the test process in the early stages of your product development.
Choose one of the following options:
- Download the latest stable release here or
- Clone the git repo —
git clone https://github.com/webdriverio/cucumber-boilerplate.git
- and checkout the tagged release you'd like to use.
Then just embed the test directory into the root folder of your project and copy/install the necessary dependencies from the package.json file and you are all set.
- Super simple setup
- Full integration with WebdriverIO
- Over 65 predefined steps that cover almost everything you need, you can start writing tests right away
- Easy integration with cloud services like Sauce Labs
- Support for different languages (French, Spanish, Norwegian, Polish, German, Russian)
- Integration of WebdriverIO's Multiremote functionality (coming soon)
- Easy to run tests in parallel (coming soon)
Tests are written in Gherkin syntax
that means that you write down what suppose to happen in a real language. All test files are located in
./test/features/*
and have the file ending .feature
. You will already find some test files in that
directory. They should demonstrate, how tests could look like. Just create a new file and write your first
test.
myFirstTest.feature
Feature:
In order to keep my product stable
As a developer or product manager
I want to make sure that everything works as expected
Scenario: Check title of website after search
Given I open the url "http://google.com"
When I set "WebdriverIO" to the inputfield "#gbqfq"
And I press "Enter"
Then I expect that the title is "WebdriverIO - Google Search"
Scenario: Another test
Given ...
This test opens the browser and navigates them to google.com to check if the title contains the search query after doing a search. As you can see, it is pretty simple and understandable for everyone.
To run your tests just call the run.js file:
$ ./test/run.js
To configure your tests, checkout the config.js
file in your test directory. It comes with a bunch of documented options you can choose from.
You can setup multiple configs for specific environments. Lets say you want to have a different baseUrl for
your local and pre-deploy tests. Use the config.js
to set all general configs (like mochaOpts) that don't change.
They act as default values. For each different environment you can create a new config with the following name
scheme:
config.<ENVIRONMENT>.js
Now you can create a specifc config for your pre-deploy tests:
config.staging.js
module.config = {
baseUrl: 'http://staging.example.com'
}
Your environment specific config file will get merged into the default config file and overwrites the values you set.
To run a test in a specific environment just set the desired NODE_ENV
environment variable:
$ NODE_ENV=staging ./test/run.js
The predefined snippets allow you to do a lot of common things but you might need extra snippets which
are better aligned to your aims. To do so you will find all step definitions in ./test/steps
. They
are separated in given
, when
and then
. For instance if you want to have a login step that helps
you to login the browser before each test, you can start to add that as a "given" snippet:
./test/steps/given.js
module.exports = function() {
this.given(/I open the (url|site) "$string"$/, function (type, page, done) {
var url = type === 'url' ? page : this.baseUrl + page;
this.browser.url(url , done);
})
// ... other predefined snippets
// ...
// ...
/**
* my login snippet
*/
.given(/^I login as "$string" with password "$string"$/, function(username, password, done) {
this.browser
.setInput('input#username', username)
.setInput('input#password', password)
.submitForm('#login')
.call(done);
})
You define your snippet as regular expression. This is pretty powerful as it allows you to create complex
sentences with multiple options. Everything that's within "$string"
gets captured and appended to the
callback. The last argument is always a callback function that needs to get call if your step is done.
You can access the browser and your WebdriverIO instance with this.browser
.
To assert values this boilerplate project comes with a Chai integration. Let's say you want to check if the username gets display in the header properly. For that we add a new snippet in
./test/steps/then.js
module.exports = function(dict) {
this.then(/^I expect that the title is( not)* "$string"$/,
require('../support/helper/checkTitle'))
// ... other predefined snippets
// ...
// ...
/**
* my check username in header snippet
*/
.then(/^should the username "$string" be present in the header$/, function(username, done) {
client.getText('#header .username', function(err, headerUsername) {
should.not.exist(err);
username.should.equal(headerUsername, 'username in header doesn\'t match');
})
.call(done);
})
That's it. We created to new snippets to test something on our page. We can use these snippets now in our Scenario like this:
Feature: ...
Scenario: check if username is present
Given I login as "roboter" with password "test123"
Then should the username "roboter" be present in the header
You can add additional descriptive comments in your feature files.
###
This is a
block comment
###
Feature: As a bystander
I can watch bottles falling from a wall
So that I can be mildly amused
# This is a single line comment
Scenario: check if username is present
Given I login as "roboter" with password "test123"
Then should the username "roboter" be present in the header
If you have failing or unimplemented tests you can mark them as "Pending" so they will get skipped.
// skip whole feature file
@Pending
Feature: ...
// only skip a single scenario
@Pending
Scenario: ...
If you are developing and you want to run only some test you can mark them as "Isolate" so the others will not.
// run only the "isolated" scenarios
@Isolated
Scenario: ...
Checkout all predefined snippets. You can find the way how they get used in sampleSnippets.feature
.
/I open the (url|site) "$string"$/
open url in browser/^the element "$string" is( not)* visible$/
test if element is visible/^there is (an|no) element "$string" on the page
test if element exists/^the title is( not)* "$string"$/
test title of page/^the element "$string" contains( not)* the same text as element "$string"$/
compare text of two elements/^the (element|inputfield) "$string" does( not)* contain the text "([^"]*)"$/
test if element or input has(n't) certain value/^the page url is( not)* "$string"$/
test url/^the( css)* attribute "$string" from element "$string" is( not)* "$string"$/
assert if css attribute of element has certain value/^the checkbox "$string" is( not)* selected$/
test if checkbox is selected/^the cookie "$string" contains( not)* the value "$string"$/
test if cookie with certain value exists/^the cookie "$string" does( not)* exist$/
test if cookie exists/^the element "$string" is( not)* \d+px (broad|tall)$/
test if element has certain height/width
/^I (click|doubleclick) on the (link|button|element) "$string"$/
click/doubleclick on link, button or element/^I (add|set) "$string" to the inputfield "$string"$/
add value to inputfeld/^I clear the inputfield "$string"$/
clear input field/^I drag element "$string" to element "$string"$/
drag n drop element from element to element/^I submit the form "$string"$/
submit form/^I wait on element "$string"( for (\d+)ms)*$/
wait for certain element/^I wait on element "$string"( for (\d+)ms)*( to (be checked|be enabled|be selected|be visible|contain a text|contain a value|exist))*$/
wait on element to be checked, enabled, selected, visible, to contain a text/value or to exist/^I pause for (\d+)ms$/
pause execution for x ms/^I set a cookie "$string" with the content "$string"$/
set a cookie with certain value/^I delete the cookie "$string"$/
delete cookie by name/^I press "$string"$/
press certain key/^I (accept|dismiss) the alertbox$/
accept or dismiss alertbox
/^I expect that the title is( not)* "$string"$/
test title of page/^I expect that element "$string" is( not)* visible$/
test if element is visible/^I expect that element "$string" does( not)* exist$/
test if element exists- `/^I expect that element "$string" does( not)* contain the same text as element "$string"$/
compare text of two elements /^I expect that (element|inputfield) "$string"( not)* contains the text "([^"]*)"$/
compare text of two elements/^I expect that the url is( not)* "$string"$/
test url/^I expect that the( css)* attribute "$string" from element "$string" is( not)* "$string"$/
assert if css attribute of element has certain value/^I expect that checkbox "$string" is( not)* selected$/
test if checkbox is selected/^I expect that cookie "$string"( not)* contains "$string"$/
test if cookie with certain value exists/^I expect that cookie "$string"( not)* exists$/
test if cookie exists/^I expect that element "$string" is( not)* \d+px (broad|tall)$/
test if element has certain height/width
Please fork, add specs, and send pull requests! In lieu of a formal styleguide, take care to maintain the existing coding style. Currently not all WebdriverIO commands are mapped and implemented as snippets. Any contribution that adds new snippets + test are highly welcome.