Rayrun
← Back to Discord Forum

Conditionally skip global setup

dirvinautomation_16636posted in #help-playwright
Open in Discord
dirvinautomation_16636

I am working with a globalSetup function which seeds dependent data for my test suite.

What I want is to be able to skip this global setup based on some flag, options, or other config, while developing tests. The setup goes:

  1. Create fresh source data in globalSetup
  2. Each test file has a beforeAll hook which copies this data to run tests against
  3. Each test file has an afterAll hook which deletes the newly copied data
  4. After all tests run the globalTeardown which deletes the source data

So, ideally, I would be able to run step 1 once, repeat steps 2 and 3 over and over again as I iterate on a test, and then run step 4 once I'm finished. I don't want to have to recreate the source data over and over again, because that process is much slower than simply copying it in.

Anybody have any thoughts or know any strategies to achieve this? I am using typescript node.

This thread is trying to answer question "How can I conditionally skip a global setup function in my test suite to avoid recreating source data repeatedly?"

8 replies

Instead of running globalSetup through playwright.config.ts, you can set up your global setup as a project dependency: https://playwright.dev/docs/test-global-setup-teardown#option-1-project-dependencies.

dirvinautomation_16636

Thanks for your response. I'm not sure your suggestion will allow me to achieve my desired result. Could you elaborate? Let me know if I could be more clear in my question.

Hi, you can add an environment variable for that. You'll need dotenv npm package to read env file with your credentials and this setting (because commit credentials is a bad practice). During the development process you can change the value as you want. Btw, in code this value will be available with process.env.YOUR_ENV_NAME.

dirvinautomation_16636

Thanks Alex, I actually ended up hacking together a generic programming solution (instead of a native playwright solution) that is very similar to your suggestion. I will share my solution once I have it more fleshed out 🙂

lucky_rabbit_44106

Very much possible. I too use the a similar setup where in I store all the storage state files in a particular directory say "local_files". Now in further parts of my script we can check by code if this directory exists or not to run particular set of code. In my case I run login steps only if no storage state is present

dirvinautomation_16636

Ok, after some refining, this is the solution I arrived at:

const dbSetup = async (): Promise<() => Promise<void>> => {
  const setupFileExists = fs.existsSync("tmp/setup.json");
  if (process.env.CI || !setupFileExists) {
    console.info("Setting up source data");
    const { environmentInfo, cleanup } = await runMySeedingFunction();
    process.env.TEST_ENVIRONMENT_INFO = JSON.stringify(environmentInfo);
    if (process.env.CI) return cleanup;
    try {
      fs.mkdirSync("tmp");
    } catch (error) {
      console.info("tmp folder already exists");
    }
    await fsPromise.writeFile("tmp/setup.json", JSON.stringify(environmentInfo));
  }
  if (setupFileExists) {
    console.info("Using existing setup.json");
    const environmentInfo = await fsPromise.readFile("tmp/setup.json", "utf-8");
    process.env.TEST_ENVIRONMENT_INFO = environmentInfo;
    console.info("Skipping db setup");
  }
  return noOpCleanup;
};
async function noOpCleanup() {
  console.info("Teardown not required");
}

Function is called from playwright.config.ts:

export default defineConfig({
  testDir: "./src/e2e",
  globalSetup: require.resolve("./src/e2e/global-setup"),
  // ....
  // ...
})

Overview:

  1. Call global setup at the beginning of a test run
  2. Check for the existence of a setup.json file with info about seeded data
  3. If not in CI and no file exists, seed the data base
    • Return seeded data info, and a data cleanup function from seed function
  4. Set the seeded data info to a JSON string
  5. Save seeded JSON info to environment variable for access by tests
  6. If in CI, return the cleanup function (to be called by playwright on run end)
  7. Otherwise, write the seed info to the file system, matching the file name I check against

On the next test run (locally)

  1. A setup file will be found
  2. Read the info from the file and set it as an env variable
  3. Return a no-op function, since we don't want playwright to cleanup the DB data in this case

Well, usually environment variable is an input to your program so I don't fully understand why you're saving some data into it programatically process.env.TEST_ENVIRONMENT_INFO = JSON.stringify(environmentInfo);

If you seed the data from JSON file you can easily access this file in your tests. I'd suggest you to refactor the code a bit because as for me it's hard to understand and read.

return noOpCleanup; I also didn't understand this line

But I'm glad it works.

dirvinautomation_16636

Using an environment variable is suggested in the documentation so I followed that.

Agree the noOpCleanup is a bit confusing, but playwright will call the function returned from your global setup function as the cleanup. In the case of wanting to save the seeded data, there should be no cleanup action, so I wanted to be super clear that no action was taken during cleanup. I could probably remove the thing entirely, but at my company log every single thing, so I think I will keep it.

Related Discord Threads

TwitterGitHubLinkedIn
AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email luc@ray.run.