Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run concurrent tests in Jest with multiple tests per request?

Tags:

jestjs

I'd like to run my Jest tests concurrently, but I'm having issues with one scenario:

I'm testing the results on an endpoint, and I want to test multiple things about it. So in my beforeAll function, I make the request and store the response, and then I test the response in multiple tests. This works fine synchronously, but when I make the tests concurrent, it no longer lets you pass a variable into the test, so it's a no go. Alternatively, I can put the request in the test itself and then expect many things about the response, but then I don't have the granularity to see what went wrong if something fails.

Is there any solution for this scenario?

This works:

let data;
beforeAll(async () => {
    data = await getDataFromRequest();
}
it('value1 should be truthy', () => {
    expect(data.value1).toBeTruthy();
}
it('value2 should be truthy', () => {
    expect(data.value2).toBeTruthy();
}

This also works:

it.concurrent('data should have correct values', async () => {
    const data = await getDataFromRequest();
    expect(data.value1).toBeTruthy();
    expect(data.value2).toBeTruthy();
}

But what I want is:

let data;
beforeAll(async () => {
    data = await getDataFromRequest();
}
it.concurrent('value1 should be truthy', () => {
    expect(data.value1).toBeTruthy();
}
it.concurrent('value2 should be truthy', () => {
    expect(data.value2).toBeTruthy();
}
like image 697
Ben Nichols Avatar asked Mar 06 '17 19:03

Ben Nichols


People also ask

How do I run multiple test files in Jest?

Run multiple Jest tests in a file using .$ run-skip-jest-tests/node_modules/. bin/jest src/many-only-tests. test. js PASS src/many-only-tests.

Does Jest run concurrently?

Each time a test run completes, the global environment is automatically reset for the next. Since tests are standalone and their execution order doesn't matter, Jest runs tests in parallel.

Do Jest tests run synchronously?

Jest typically expects to execute the tests' functions synchronously. If we do an asynchronous operation, but we don't let Jest know that it should wait for the test to end, it will give a false positive.

Does Jest support parallel execution?

To speed-up your tests, Jest can run them in parallel. By default, Jest will parallelise tests that are in different files. IMPORTANT: Paralellising tests mean using different threads to run test-cases simultaneously.


2 Answers

Seems worth pointing out, that there is also a discussion about this in a jest issue: https://github.com/facebook/jest/issues/4281

Gist of it: It doesn't work that way and isn't planned. Possible workaround:

const dataPromise = getSomeDataPromise();

test.concurrent('one', async () => {
  const data = await dataPromise;
});

test.concurrent('two', async () => {
  const data = await dataPromise;
});
like image 150
Mo. Avatar answered Sep 21 '22 19:09

Mo.


Was having same issue when doing browser testing with Playwright where one test suite only requires one instance of browser. Had to wrap it with a Promise with setInterval. In your case it should be like below:

let data;

beforeAll(async () => {
    data = await getDataFromRequest();
}
test.concurrent('value1 should be truthy', async () => {
    await waitForData();
    expect(data.value1).toBeTruthy();
}
test.concurrent('value2 should be truthy', async () => {
    await waitForData();
    expect(data.value2).toBeTruthy();
}

/**
 * @param {number} interval -  the interval to check data availability
 * @param {number} timeout -  the overall timeout value
 * @return Promise of your data OR reject if timeout.
 */
function waitForData(interval = 500, timeout = 5000){
  let acc = 0; // time accumulation
  return new Promise((resolve, reject) => {
    const i = setInterval(() => {
      acc += interval;
      if (data) {
        clearInterval(i);
        resolve(data);
      }
      if (acc > timeout) {
        clearInterval(i);
        reject();
      }
    }, interval);
  });
}

So you just need to assign the proper check interval and timeout which should be long enough for your data asycn call to come back.

like image 31
LeOn - Han Li Avatar answered Sep 24 '22 19:09

LeOn - Han Li