CodeceptJS is a modern end to end testing framework. In this tutorial we will setup BDD end-to-end testing using CodeceptJS along with Puppeteer.
Requirements:
npm
- An app to write tests to: If you already have an app you can use that OR you can just clone this basic todo app https://github.com/taniarascia/react-hooks and follow along
If you cloned the above app please browse inside the cloned directory and run the following commands to set it up:
npm install
npm run start
CodeceptJS Setup
Browse inside your project directory
1) Install CodeceptJS with Puppeteer
npm install codeceptjs puppeteer --save-dev
2) Initialize CodeceptJS in the current directory by running:
npx codeceptjs init
You will be asked some questions as shown below:
When asked to select helpers choose Puppeteer
but in other cases take the default (i.e. hit Enter
).
3) The above initialization of codeceptjs will create some files:
-
codecept.conf.js
: main configuration file _test.js
jsconfig.json
steps.d.ts
steps_file.js
-
output
: a directory that will contain screenshot of failed tests
We only need condecept.conf.js
as it is the main configuration file. The rest of the files are not needed so you can delete them.
4) We can enable Gherkin for the current project by running:
npx codeceptjs gherkin:init
It will add a gherkin section to the codecept.conf.js
file and create directories for features and step definitions.
5) Now edit codecept.conf.js
file according to your testing infrastructure so it looks similar to:
exports.config = {
output: './output', // screenshot directory and contains screenshot of failed tests
helpers: {
Puppeteer: {
url: 'http://localhost:3000', // host url
show: true,
windowSize: '1200x900'
}
},
gherkin: {
features: './features/*.feature', // feature files location
steps: ['./step_definitions/steps.js'] // step definitions location
},
plugins: {
screenshotOnFail: { // if true take screenshot of failed scenarios
enabled: true
},
retryFailedStep: { // if true rerun failed tests
enabled: true
}
},
name: 'react-hooks' // name of the application folder
}
Note: React applications by default run on port 3000
. So, if you cloned the application from Requirements
section don't forget to include the port in url
section of Puppeteer
object.
6) After you create a feature file and write some scenarios, to generate gherkin snippets run:
`npx codeceptjs gherkin:snippets`
Writing Tests with CodeceptJS
1) Let's create a basic test scenario to add a user
File: features/basic.feature
Feature: add user
As a user
I want to be able to create other users
So that different people can have individual data
Scenario: signup a user
Given the user has browsed to the homepage
When the user adds user with name "Hari Bhandari" and username "hari" using the webUI
Then user with name "Hari Bhandari" and username "hari" should be listed on users table
2) After you wrote some scenarios, to generate gherkin snippets run:
npx codeceptjs gherkin:snippets
Now edit the generated step definitions so that it looks like:
File: step_definitions/steps.js
const { I } = inject();
Given('the user has browsed to the homepage', () => I.amOnPage('/'));
When('the user adds user with name {string} and username {string} using the webUI', (name, username) => {
I.waitForVisible("//input[@name='name']");
I.fillField("name", name)
I.fillField("username", username)
I.click("//button[contains(text(),'Add new user')]")
});
Then('user with name {string} and username {string} should be listed on users table', (name, username) => {
I.see(name);
I.see(username);
});
In CodeceptJS tests are written as a sequence of actions performed by an actor. So, the I
object is an actor, an abstraction for a testing user. The I
is also a proxy object for the currently enabled Helper(Puppeteer).
So basically in the above step definitions, I
browse to the homepage(http://localhost:3000), wait until the name
input field is visible, fill the fields, click on the Add new user
button and check if the user I added is listed on the View users
table.
3) To run the test and see step-by step output use --steps option:
`npx codeceptjs run --steps`
To see not only the business steps but the actual performed steps use the --debug flag:
`npx codeceptjs run --debug`
By using the `debug` flag you can see the execution of step definitions and it is very useful for debugging purposes.
Page object
A page object is basically a wrapper around an HTML page, or a fragment of the page that provides an access to the state of the underlying page/fragment. A page object provides a separation between the test code and the locators and makes our code more DRY.
If an application has different pages (login, admin, etc.) you should use a page object. Even though our example app doesn't have different pages we are going to create a page object.
To get more ideas about page objects and page objects in CodeceptJS check the following links:
https://github.com/SeleniumHQ/selenium/wiki/PageObjects
https://codecept.io/pageobjects/
CodeceptJS can generate a sample template for a page object with the command:
npx codeceptjs gpo
In the above screenshot, I am creating a page object with the name dashboardPage.js
Now, include the page object section in your config file. codecept.conf.js
should now look similar to:
exports.config = {
.....
include: {
Page: './pages/dashboardPage.js' // page object location
},
.....
}
Edit pages/dashboardPage.js
so that it looks like:
const { I } = inject();
module.exports = {
elements: {
addNewUserButton: '//button[contains(text(),"Add new user")]',
name: String('name'),
username: String('username')
},
addUser(name, username) {
I.waitForVisible(this.elements.addNewUserButton);
I.fillField(this.elements.name, name)
I.fillField(this.elements.username, username)
I.click(this.elements.addNewUserButton)
}
}
CodeceptJS provides flexible strategies for locating elements. Here, I have used xpath
for
Add new user
button and semantic locator(name) for name
and username
.
Edit the When
step in step_definitions/steps.js
to include the pageObject's function
File: step_definitions/steps.js
....
const dashboard = require('../pages/dashboardPage');
....
When('the user adds user with name {string} and username {string} using the webUI', (name, username) => {
dashboard.addUser(name, username)
});
...
Now, run your test again with npx codeceptjs run --steps
In this way we have set up BDD end-to-end testing using CodeceptJS. Happy Testing.
Top comments (4)
Hi @haribhandari07 When I run the npx codeceptjs gherkin:snippets command no test steps are generating. I have scenario like this in the './features/*.feature'
Feature: Business rules
Scenario Outline: do something
Given I have a defined step currency
Examples:
| currency | Header 2 | Header 3 |
| EUR | Value 2 | Value 3 |
| USD | Value 2 | Value 3 |
and existing step definition in './step_definitions/steps.js'
const { I } = inject();
// Add in your custom step files
package.json
{
"name": "codeceptTest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"codeceptjs": "^2.6.5",
"puppeteer": "^4.0.0"
}
}
Output logs:
savitamaurya@savitamaurya-xx codeceptTest % npx codeceptjs gherkin:snippets
Debugger listening on ws://127.0.0.1:55931/0f14bbe9-133b-48d3-8948-c9ce2e0ececa
For help, see: nodejs.org/en/docs/inspector
Debugger attached.
Loaded 1 files
No new snippets found
Waiting for the debugger to disconnect...
savitamaurya@savitamaurya-xx codeceptTest %
Can you please suggest how to create step definitions for scenario outlines types example.
Hi, sorry for the late response. You need to add
in your
package.json
file. Also, if you face more issues, compare yourpackage.json
file to mine.In the above step:
Given I have a defined step currency
currency is inside angular brackets but after posting here it's removing the brackets.pls note this
How do you create reports I use allure but is not reproting when the steps are skipped ??