loading...
JankariTech

CodeceptJs Setup & BDD

haribhandari07 profile image Hari Bhandari ・4 min read

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:

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:
2

When asked to select helpers choose Puppeteer but in other cases take the default (i.e. hit Enter).
1

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

3

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.

JankariTech

JankariTech specializes in helping customers set up test automation. We particularly like to help with: UI testing, API testing, retrofitting tests, behaviour driven development

Discussion

pic
Editor guide
 

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

gherkin: {
      features: './features/*.feature'
    }


in your package.json file. Also, if you face more issues, compare your package.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