Hooks
The following hooks are supported:
- Before
- After
- setup
- Teardown
Hooks can be defined in files with the following extensions, and should be located under the stepDefinitionsRoot
*.hooks.ts
*.before.ts
*.after.ts
*.setup.ts
*.teardown.ts
Setup
The setup hook is executed before any tests are run. It is useful for bootstrapping the environment.
The setup call back recieves a special copy of the app which is shared between all Setup
and TearDown
calls but not tests or other hooks.
import { Setup } from "@autometa/runner";
Setup("Setup the services 'foo'", (app) => {
app.world.foo = 2;
});
Before
The before hook is executed before each test. It is useful for setting up the world in advance of a test, setting up data from the service or preparing data base entries.
Before recieves the same copy of the App
that the test it preceeds will have.
import { Before } from "@autometa/runner";
import { setupFooObject } from "../objects";
Before("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
});
After
The after hook is executed after each test. It is useful for cleaning up data from the service or database, or resetting the environment to a known state.
After recieves the same copy of the App
that the test it succeeds will have.
import { After } from "@autometa/runner";
After("Reset the services 'foo'", (app) => {
return app.myHttpClient.delete("/foo", app.world.someId);
});
Teardown
The teardown hook is executed after all tests have run. It is useful for cleaning up the environment
after all tests have run. It shares the same copy of the App
as the Setup
hook.
import { Teardown } from "@autometa/runner";
Teardown("Reset the services 'foo'", (app) => {
return app.myHttpClient.delete("/foo?type=testType");
});
Order Of Execution
Hooks are executed according to 2 orders:
The order in which the hooks files are loaded.
Hooks will be loaded in filesystem order. Consider the following directory,
which will be in test/steps
:
test/steps
├── common.hooks.ts
├── cleanup.hooks.ts
├── products/
│ ├── products.hooks.ts
Hooks will be executed in the following file order:
common.hooks.ts
cleanup.hooks.ts
products/products.hooks.ts
The order in which the hooks are defined in the file.
Hooks will be executed in the order they are defined in the file. Consider the following file:
// common.hooks.ts
import { Before, After } from "@autometa/runner";
Before("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
});
Before("Setup the services 'bar'", (app) => {
return app.myHttpClient.post("/bar", setupBarObject);
});
The Setup the services 'foo'
hook will be executed before the Setup the services 'bar'
hook.
So the first before hook that will be executed is Setup the services 'foo'
and the second will be Setup the services 'bar
,
followed by the Before
hooks in the next file and so on.
Grouped Hooks
available in version >0.5.8Specific hooks exist for group types in Cucumber, such as Features, Rules, Scenario Outlines and Examples. Each grouping has a Before and After hook which can be filtered using cucumber tags.
Hook names:
- BeforeFeature
- AfterFeature
- BeforeRule
- AfterRule
- BeforeScenarioOutline
- AfterScenarioOutline
- BeforeExamples
- AfterExamples
Filtering
Hooks can be filtered using a cucumber expression, or a custom filter function which accepts a list of the current tests tags.
import { BeforeFeature } from "@autometa/runner";
BeforeFeature("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
}).tagFilter("@foo and not @bar");
BeforeFeature("Setup the services 'bar'", (app) => {
return app.myHttpClient.post("/bar", setupBarObject);
}).customFilter((tags) => tags.includes("@bar=2"));
Note: CustomFilters take priority over TagFilters.
Ordering
By default, hooks are executed in file order, so files in a higher directory will be executed before files in a lower directory, while hooks in the same file will be executed in the order they are defined.
The default ordering can be overridden by setting the order
property on the hook.
import { BeforeFeature } from "@autometa/runner";
BeforeFeature("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
}).order(1);
By default, all hooks have an order of 5. Lower orders have higher priority. So an order of 1 will execute before the same hook type with an order of 5.
Timeouts
Hooks can have a timeout set on them, which will cause the hook to fail if it takes longer than the specified time to execute.
import { BeforeFeature } from "@autometa/runner";
BeforeFeature("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
}).timeout(5000);
Timeouts can also be specified with a time unit:
import { BeforeFeature } from "@autometa/runner";
BeforeFeature("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
}).timeout(5, 's');
Chaining
Options can be chained together to create a more complex hook.
import { BeforeFeature } from "@autometa/runner";
BeforeFeature("Setup the services 'foo'", (app) => {
return app.myHttpClient.post("/foo", setupFooObject);
}).tagFilter("@foo and not @bar")
.order(1)
.timeout(5000);