question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Run code before and after a group of test files

See original GitHub issue

Description

The before and after hooks are really useful, but they are limited to a given file.

When doing integration test we often have to do some relatively long set up tasks such as starting a database, a server or a docker container. As those tasks take often several dozen of seconds or a few minutes, we want to do them only once per test run.

As before and after are limited to the file in which they are defined, it forces us to write all the integration tests in the same file. This is not ideal as it ends up creating a giant file that is difficult to maintain.

So it would be great to be able to define have a special before and after hook that spans a group of file.

I’m not really sure what would be the best API, but I can think of two solutions.

t.beforeAll(scope, [function]) and t.afterAll(scope, [function])

Those special version of beforeAll and afterAll could be defined in any test file (even by themselves without other tests) and the function is optional.

All the test files that have a beforeAll or an afterAll for a given scope would have to be run only after the function of all the beforeAll of the same scope ran. And it will run the function of all afterAll only when the files having the same scope are completed.

// integration/mocks.js
test.beforeAll('database', async () => {
  await startDatabase();
});
test.beforeAll.always('database', async () => {
  await stopDatabase();
});
// integration/scenario1.js
test.beforeAll('database')

test.serial('First step of scenario 1' async t => {
  // Do something with the database
}

test.serial('Second step of scenario 1' async t => {
  // Do something else with the database
}

test.beforeAll.always('database');
// integration/scenario2.js
test.beforeAll('database')

test.serial('First step of scenario 2' async t => {
  // Do something with the database
}

test.serial('Second step of scenario 2' async t => {
  // Do something else with the database
}

test.beforeAll.always('database');

after.js and before.js in a diretory:

.
+-- test/
|   +-- integration
|       +-- before.js
|       +-- scenario1.js
|       +-- scenario2.js
|       +-- scenario3.js
|       +-- after.js

ava would run before.js, then all the tests in scenario1.js, scenario2.js, scenario3.jsthe same way it does now (in parralel or serially is.serialis used) then runafter.js`.

In other word, ava would guarantee that the files scenario1.js, scenario2.js, scenario3.jsare run only oncebefore.jsresolves and thatafter.jsis called only when all the tests inscenario1.js, scenario2.js, scenario3.js are completed.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:6
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

6reactions
pvdlgcommented, Dec 2, 2017

That would be possible but that would make it impossible to use ava directly during development, for example to select which test to run during with ava <files_to_test>.

I found a workaround that kind of works in the current version:

With the following:

.
+-- test/
|   +-- integration
|       +-- index.test.js
|       +-- scenario-1.test.js
|       +-- scenario-2.test.js
// test/integration/index.text.js
import test from 'ava';
import delay from 'delay';
import requireGlob from 'require-glob';

test.before(async () => {
  console.log('Setup start');
  await delay(1000);
  console.log('Setup complete');
});

requireGlob(['./_*.test.js']);

test.after(async () => {
  console.log('Tear down start');
  await delay(1000);
  console.log('Tear down complete');
});
// test/integration/scenario-1.text.js
import test from 'ava';
import delay from 'delay';

test('Scenario 1 - Test 1', async t => {
  await delay(400);
  t.is(true, true);
});

test('Scenario 1 - Test 2', async t => {
  await delay(100);
  t.is(true, true);
});
// test/integration/scenario-2.text.js
import test from 'ava';
import delay from 'delay';

test('Scenario 2 - Test 1', async t => {
  await delay(200);
  t.is(true, true);
});

test('Scenario 2 - Test 2', async t => {
  await delay(300);
  t.is(true, true);
});

On ava -v I obtain:

Setup start
Setup complete
  ✔ integration › index › Scenario 1 - Test 2 (104ms)
  ✔ integration › index › Scenario 2 - Test 1 (200ms)
  ✔ integration › index › Scenario 2 - Test 2 (300ms)
  ✔ integration › index › Scenario 1 - Test 1 (404ms)
Tear down start
Tear down complete

  4 tests passed

if I use t.test.serial it also work as expected.

The problem is that if define t.before, t.after, t.beforeEach or t.afterEach hooks they are executed within the context of index.test.js. That mean a t.beforeEach defined in scenario-1.test.js will be executed before each test in both scenario-1.test.js and scenario-2.test.js. But as long as all the scenario share the same t.before, t.after, t.beforeEach or t.afterEach hooks its ok.

So, yes there is workarounds that are not too bad. But having such feature in the core would still be nice, even in a simpler than what I proposed.

But feel free to close if you think the improvement of having that in the core vs a workaround doesn’t worth the effort/extra code/extra maintenance.

4reactions
LeBovincommented, Jul 8, 2020

It’s definitely something Ava should have

Read more comments on GitHub >

github_iconTop Results From Across the Web

Run code before and after each test in py.test? - Stack Overflow
It will call setup_module before this test and teardown_module after test completes. You can include this fixture in each test-script to run it...
Read more >
Setup and Teardown - Jest
By default, the beforeAll and afterAll blocks apply to every test in a file. You can also group tests together using a describe...
Read more >
How to group test cases in TestNG [with Examples]
In this tutorial, you will learn how to group test cases in TestNG along with the demonstration with relevant TestNG group examples.
Read more >
Set Up and Tear Down State in Your Tests - Apple Developer
Prepare initial state before tests run, and clean up resources after tests complete. Overview. To consistently and reliably check that your code produces...
Read more >
Writing and Organizing Tests - Cypress Documentation
There are some folders that may be generated after a test run, containing assets that ... To include code before your test files,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found