25

I am using jest to run my test suite (with back-end as Node.js & express). Below is my code:

const puppeteer = require ('puppeteer');

test('testing login function', async () => {
    const browser = await puppeteer.launch ({  
        headless: true,
        args: ['--no-sandbox']
  });

    const page = await browser.newPage();

    await page.type('#username', 'admin');
    await page.type('#password', 'password');

    await page.click('login-button');

    await page.waitFor('.card');

    expect(texthead).toEqual('Welcome to webpage');

    await browser.close();
});

I am trying to run this same test multiple times at once, is there a way using it by jest, or maybe using other tools.

2
  • Can you wrap the testing code in in a loop? Commented Sep 13, 2018 at 17:15
  • Yes, I tried for loop but it will run sequentially. I want to run multiple tests at once. Commented Sep 13, 2018 at 19:08

4 Answers 4

40

If you're looking for something that will essentially stress test a single test (looking for test flakiness like I was) then you could use the following one-liner in your terminal, which of course uses bash and Jest together.

for i in {1..100}; do npx jest <test_file> --silent || (echo "Failed after $i attempts" && break); done

This specific command requires you to have npx installed and it uses the --silent option but you can change it as you please.

Sign up to request clarification or add additional context in comments.

2 Comments

A useful flag in jest for this case would be -o (instead of <test_file>). Run only modified/new tests that way you can have "Flakiness CI" on your tests.
When running this with a failing test, I get the following printed Failed after $i attempts bash: break: only meaningful in a for', while', or until' loop` and the loop doesn't break. An alternative is for i in {1..100}; do npx jest <test_file> --silent; if [[ "$?" != 0 ]]; then echo "Failed after $i attempts" && break; fi; done . The double quotes are needed to interpolate $i
23

Jest has a built in method for this using .each(). https://jestjs.io/docs/api#testeachtablename-fn-timeout

If you want to change the parameters of each test, you can pass an array of test parameters to .each([1,2,3]). If this is un-necessary, just fill the array with null.

test.each(Array(100).fill(null))('may be flaky test', async () => {})

This can optionally be run in parallel using .concurrent test.concurrent.each(Array(100).fill(null))('may be flaky test', async () => {})

Comments

6

If you don't want tests run sequentially, you can use Promise.all. Here is a quick example of how you could refactor your code.

const runTheTest = async () => { 
  const browser = await puppeteer.launch ({
    headless: true, args: ['--no-sandbox'] 
  });
  .......
  return browser.close();
}

test('testing login function', async () => { 
  const testRuns = []
  for (let index = 0; index < NUMBER_OF_RUNS; index++) {
    testRuns.push(runTheTest())
  }
  return Promise.all(testRuns);
})

Comments

3

npx installed packages over and over and I wanted to time if my change improved the test speed. It's not great, but what I did was putting a command in the package.json

"jest": "jest <file_path> --silent"

and then borrowed the script from Brady as

for i in {1..100}; do yarn jest || (echo 'Failed after $i attempts' && break); done

I wrapped it in a timer, but that's not necessary really.

1 Comment

(echo 'Failed after $i attempts' && break) is going to execute in a subshell and break will exit that subshell, not the actual loop. This can be fixed by using curly braces instead: {echo "Failed after $i attempts" && break}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.