Basics

CodeceptJS is a modern end to end testing framework with a special BDD-style syntax. The test is written as a linear scenario of user's action on a site.

Feature('CodeceptJS demo');

Scenario('check Welcome page on site', (I) => {
  I.amOnPage('/');
  I.see('Welcome');
})

Tests are expected to be written in ECMAScript 6. Each test is described inside a Scenario function with I object passed into it. I object is an actor, an abstraction for a testing user. I is a proxy object for currently enabled Helpers.

  "helpers": {
    "WebDriverIO": {
      "url": "http://localhost",
      "browser": "firefox"
    }
  }

For current config all methods of I will be taken from WebDriverIO helper. This is done to allow easy switching of running backends so you could replace WebDriverIO with Protractor or Nightmare helpers.

How It Works

Tests are written in synchronous way. Test scenarios should be linear, so tests by themselves should not include promises or callbacks as well. However, behind the scene all actions are wrapped in promises inside the I object. Global promise chain is initialized before each test and all I.* calls will be appended to it as well as setup and teardown.

If you want to get information from a running test you can use yield inside a generator function and special methods of helpers started with grab prefix.

Scenario('try grabbers', function* (I) {
  var title = yield I.grabTitle();
});

then you can use those variables in assertions:

var title = yield I.grabTitle();
var assert = require('assert');
assert.equal(title, 'CodeceptJS');

Pause

Test execution can be paused in any place of a test with pause() call. This also launches interactive console where you can call actions of I object.

shell

You can also use pause() to check the web application in a browser. Press ENTER to resume test execution.

Interactive shell can be started outside test context by running

codeceptjs shell

Before

Common preparation steps like opening a web page, logging in a user, can be placed in Before or Background hook:

Feature('CodeceptJS Demonstration');

Before((I) => { // or Background
  I.amOnPage('/documentation');
});

Scenario('test some forms', (I) => {
  I.click('Create User');
  I.see('User is valid');
  I.dontSeeInCurrentUrl('/documentation');
});

Scenario('test title', (I) => {
  I.seeInTitle('Example application');
});

Same as Before you can use After to run teardown for each scenario.

BeforeSuite

If you need to run complex setup before all tests and teardown this afterwards you can use BeforeSuite and AfterSuite functions. BeforeSuite and AfterSuite have access to I object, but BeforeSuite/AfterSuite don't have an access to the browser because it's not running at this moment. You can use them to execute handlers that will setup your environment. BeforeSuite/AfterSuite will work only for a file where it was declared (so you can declare different setups for files)

BeforeSuite((I) => {
  I.syncDown('testfolder');
});

AfterSuite((I) => {
  I.syncUp('testfolder');
  I.clearDir('testfolder');
});

Here are some ideas where to use BeforeSuite hooks.

Within

To specify the exact area on a page where actions can be performed you can use within function. Everything executed in its context will be narrowed to context specified by locator:

Usage: within('section', ()=>{})

I.amOnPage('https://github.com');
within('.form-signup-home', () => {
  I.fillField('user[login]', 'User');
  I.fillField('user[email]', 'user@user.com');
  I.fillField('user[password]', 'user@user.com');
  I.click('button');
});
I.see('There were problems creating your account.');

within can also work with iframes

When running steps inside a within block will be shown with a shift:

within

Comments

There is a simple way to add additional comments to your test scenario. Use say command to print information to screen:

I.say('I am going to publish post');
I.say('I enter title and body');
I.say('I expect post is visible on site');

IntelliSense

If you are using Visual Studio Code or other IDE that supports TypeScript Definitions, you can generate step definitions with

codeceptjs def

Now you should include /// <reference path="./steps.d.ts" /> into your test files to get method autocompletion while writing tests.

Skipping

Like in Mocha you can use x and only to skip tests or making a single test to run.

Reporters

CodeceptJS supports Mocha Reporters. They can be used with --reporter options. By default a custom console reporter is enabled.

We are currently working on improving reporters support.

Translation

Because CodeceptJS tests use high level DSL it is possible to write tests using different languages. Tests can be written in Portuguese, Russian, Italian, Polish languages using predefined translations.

Test Options

Features and Scenarios have their options that can be set by passing a hash after their names:

Feature('My feature', {key: val});

Scenario('My scenario', {key: val}, (I) => {});

Timeout

By default there is no timeout for tests, however you can change this value for a specific suite:

Feature('Stop me', {timeout: 5000}); // set timeout to 5s

or for the test:

// set timeout to 1s
Scenario("Stop me faster", {timeout: 1000}, (I) => {});

// disable timeout for this scenario
Scenario("Don't stop me", {timeout: 0}, (I) => {});

Retries

Browser tests can be very fragile and some time you need to re run the few times just to make them pass. This can be done with retries option added to Feature declaration.

CodeceptJS implements retries the same way Mocha do; You can set number of a retries for a feature:

Feature('Complex JS Stuff', {retries: 3})

Every Scenario inside this feature will be rerun 3 times. You can make an exception for a specific scenario by passing retries option to it:

Feature('Complex JS Stuff', {retries: 3})

Scenario('Not that complex', {retries: 1}, (I) => {
  // test goes here
});

Scenario('Really complex', (I) => {
  // test goes here
});

"Really complex" test will be restarted 3 times, while "Not that complex" test will be rerun only once.


done()