Organize Tests
This topic describes how to organize test code, declare fixtures, tests, and hooks.
- Fixtures
- Tests
- Specify the Start Webpage
- Specify Test Metadata
- Initialization and Clean-Up
- Skip Tests
If you use eslint in your project, install the TestCafe plugin to avoid the
'fixture' is not defined
and'test' is not defined
errors.
Fixtures #
TestCafe tests must be organized into categories called fixtures. A JavaScript, TypeScript or CoffeeScript file with TestCafe tests can contain one or more fixtures.
To declare a test fixture, use the fixture function.
fixture `Authentication tests`;
Tests that constitute a fixture go after this declaration.
Tests #
To create a test, call the test function and pass a function with test code inside.
fixture `MyFixture`;
test('Test1', async t => {
/* Test 1 Code */
});
test('Test2', async t => {
/* Test 2 Code */
});
The test code function accepts the test controller object as a parameter. The test controller provides access to the TestCafe test API.
You can arrange test code in any manner and reference any modules or libraries.
TestCafe tests are executed server side. You can use test actions to manipulate the tested webpage. To determine page element states or obtain other data from the client side, use the selectors and client functions.
To check if page elements have the expected parameters, use assertions.
Specify the Start Webpage #
You can specify the web page where all tests in a fixture begin with the fixture.page function.
fixture `MyFixture`
.page `http://devexpress.github.io/testcafe/example`;
test('Test1', async t => {
// Starts at http://devexpress.github.io/testcafe/example
});
Similarly, you can specify a start page for individual tests with the test.page function that overrides the fixture.page.
fixture `MyFixture`
.page `http://devexpress.github.io/testcafe/example`;
test
.page `http://devexpress.github.io/testcafe/blog/`
('My test', async t => {
// Starts at http://devexpress.github.io/testcafe/blog/
});
Specify Test Metadata #
TestCafe allows you to specify additional information for tests in the form of key-value metadata. You can display this information in the reports and use it to filter tests.
To define metadata, use the fixture.meta and test.meta methods.
fixture `My fixture`
.meta('fixtureID', 'f-0001')
.meta({ author: 'John', creationDate: '05/03/2018' });
test
.meta('testID', 't-0005')
.meta({ severity: 'critical', testedAPIVersion: '1.0' })
('MyTest', async t => { /* ... */});
Use Metadata to Filter Tests #
You can run tests or fixtures whose metadata contains specific values. Use the following options to filter tests by metadata:
- the --test-meta and --fixture-meta command line options
- the
testMeta
andfixtureMeta
parameters in the runner.filter method - the filter.testMeta and filter.fixtureMeta configuration file properties
Display Metadata in the Reports #
You can include test's metadata to reports in custom reporters. The reporter's reportFixtureStart and reportTestDone methods can access the fixture and test metadata.
Initialization and Clean-Up #
You can specify functions to be executed before a fixture or test starts and after it is completed. These functions are called hooks.
Test Hooks #
Test hooks run before a test starts and after it is completed. If a test runs in several browsers, test hooks are executed in each browser.
When test hooks run, the tested webpage is already loaded, and you can use test actions and other test run API inside test hooks.
You can specify a hook for each test in a fixture with the fixture.beforeEach and fixture.afterEach methods.
fixture `My fixture`
.page `http://example.com`
.beforeEach( async t => {
await t
.useRole(admin)
.click('#open-management-console');
})
.afterEach( async t => {
await t.click('#delete-data');
});
You can also specify hooks for an individual test with the test.before and test.after methods.
test
.before( async t => {
await t
.useRole(admin)
.click('#open-management-console');
})
('MyTest', async t => { /* ... */ })
.after( async t => {
await t.click('#delete-data');
});
If
test.before
ortest.after
is specified, it overrides the correspondingfixture.beforeEach
andfixture.afterEach
hooks, and the latter are not executed.
Share Variables Between Test Hooks and Test Code #
You can share variables between test hook functions and test code in the test context object.
Use the t.ctx property to access test context.
fixture `Fixture1`
.beforeEach(async t => {
t.ctx.someProp = 123;
});
test
('Test1', async t => {
console.log(t.ctx.someProp); // > 123
})
.after(async t => {
console.log(t.ctx.someProp); // > 123
});
Fixture Hooks #
Fixture hooks run before the first test in a fixture starts and after the last test finishes.
Unlike test hooks, fixture hooks run between tests and do not have access to the tested page. Use them to perform server-side operations, like preparing the server that hosts the tested app.
To specify fixture hooks, use the fixture.before and fixture.after methods.
import { utils } from './my-utils.js';
fixture `My fixture`
.page `http://example.com`
.before( async ctx => {
utils.populateDb(ctx.dbName);
})
.after( async ctx => {
utils.dropDb(ctx.dbName);
});
Share Variables Between Fixture Hooks and Test Code #
Hook functions passed to fixture.before
and fixture.after
methods accept the ctx
parameter that contains fixture context. You can add properties to this parameter to share the value or object with test code.
fixture `Fixture1`
.before(async ctx => {
ctx.someProp = 123;
})
.after(async ctx => {
console.log(ctx.someProp); // > 123
});
To access fixture context from tests, use the t.fixtureCtx property.
fixture `Fixture1`
.before(async ctx => {
ctx.someProp = 123;
})
.after(async ctx => {
console.log(ctx.newProp); // > abc
});
test('Test1', async t => {
console.log(t.fixtureCtx.someProp); // > 123
});
test('Test2', async t => {
t.fixtureCtx.newProp = 'abc';
});
Skip Tests #
TestCafe allows you to specify a test or a fixture to skip when tests run. Use the fixture.skip and test.skip methods for this.
fixture.skip `Fixture 1`; // All tests in this fixture are skipped
test('Fixture 1 - Test 1', () => {});
test('Fixture 1 - Test 2', () => {});
fixture `Fixture 2`;
test('Fixture 2 - Test 1', () => {});
test.skip('Fixture 2 - Test 2', () => {}); // This test is skipped
test('Fixture 2 - Test 3', () => {});
You can also use the fixture.only and test.only methods to specify that only a particular test or fixture should run while all others should be skipped.
fixture.only `Fixture 1`;
test('Fixture 1 - Test 1', () => {});
test('Fixture 1 - Test 2', () => {});
fixture `Fixture 2`;
test('Fixture 2 - Test 1', () => {});
test.only('Fixture 2 - Test 2', () => {});
test('Fixture 2 - Test 3', () => {});
// Only tests in 'Fixture 1' and the 'Fixture 2 - Test 2' test are run
If several tests or fixtures are marked with only
, all the marked tests and fixtures are run.