When testing a website, you may need to test it across different environments, such as development, staging, and production. In this post let's take a look at how to set the baseURL
and run tests across different environments in Playwright.
Setting a base URL
You might have tests that navigate to different pages on your website. By setting the baseURL
you can easily navigate to different pages by using a relative path instead of having to repeat the URL every time you use a page.goto()
in your tests.
await page.goto("https://example.com/products")
await page.goto("https://example.com/offers")
await page.goto("https://example.com/about")
Set the baseURL
in the use
section of your Playwright config.
use: {
baseURL: 'https://example.com',
}
Navigate to different pages on your website using relative paths.
await page.goto("/")
await page.goto("/products")
await page.goto("/offers")
await page.goto("/about")
Setting a sub path
If you want to test a sub path of a website you can add that path to the base URL.
use: {
baseURL: 'https://playwright.dev/docs/',
}
To go to the relative path of the sub path, add a .
before the slash otherwise Playwright will navigate to the root of the website and not the sub path.
await page.goto('./intro');
// https://playwright.dev/docs/intro
await page.goto('/intro');
// https://playwright.dev/intro
Setting different production environments
To set the URL for different environments set the process.env
variable in your baseURL
. In the example below if 'STAGING' is set to '1' then the URL will be https://playwright.dev/docs/next/
, otherwise it will default to https://playwright.dev/docs/
.
use: {
baseURL: process.env.STAGING === '1' ? 'https://playwright.dev/docs/next/'
: 'https://playwright.dev/docs/',
},
Running tests with different environments
Let's write a quick test to see how it works.
test('has title', async ({ page }) => {
await page.goto('./intro');
await expect(page.getByRole("heading", { name: "Installation"})).toBeVisible();
});
If you run the test without setting an environment variable, it will run on the production website by default.
npx playwright test
To run tests on the STAGING environment, add STAGING=1
to the beginning of the CLI command. Additionally, include --trace on
to enable the trace viewer and verify the URL.
STAGING=1 npx playwright test --trace on
Open the HTML report with the following command.
npx playwright show-report
The report shows 3 tests, one for each project. To view the details of the Chromium project, click on the trace image. In the DOM snapshot, you can find the URL that the test navigated to, which corresponds to the staging URL. Running this test without an environment variable navigates to the production URL.
Setting the base URL on CI
When running tests on CI it is best to extract the baseURL
to an environment variable. First install the dotenv
package.
npm install dotenv
Then in the Playwright config file require the dotenv
config.:
require('dotenv').config();
Next, create a .env
file in the root of the project and add the BASE_URL
variable. You can set this to your production URL or staging URL or whatever URL you want to test locally as this file should not be committed to your repository.
BASE_URL=https://playwright.dev/docs/
Then in the playwright config set the baseURL
to the BASE_URL
variable with a fallback to the production URL in case this variable is not set.
use: {
baseURL: process.env.BASE_URL ?? 'https://playwright.dev/docs/'
},
Locally you can modify this URL based on the environment you are testing.
BASE_URL=https://playwright.dev/docs/next/
The BASE_URL
environment variable can then be set on CI or in your CI workflow file.
- name: Run Playwright tests
run: npx playwright test
env:
BASE_URL: ${{ github.event.deployment_status.target_url }}
Setting up different projects
If you are regularly testing against different environments you can set up a different project for staging and production, and set the base URL for each one.
projects: [
{
name: 'staging',
use: {
...devices['Desktop Chrome'],
baseURL: 'https://playwright.dev/docs/next/'
},
},
{
name: 'production',
use: {
...devices['Desktop Chrome'],
baseURL: 'https://playwright.dev/docs/'
},
},
...
]
To run these projects in the CLI add --project=
to the end of the test command.
npx playwright test --project=staging
npx playwright test --project=production
Using projects gives us more freedom to add different configurations and modify more than just the baseURL
to run tests with different configurations such as colorScheme
, locale
and so much more. Check out the guide on test options for more details.
Also using Projects means you can easily toggle between them when using the VS Code extension or when running your tests in UI Mode.
You can create a new config file for each environment, however we don't recommend this for testing across different environments. We do recommend having different config files if you are running different tests within the same application, such as tests for mobile emulation versus desktop.
Conclusion
Setting a baseURL
in the Playwright config can be very useful so as not to repeat the URL across your whole site. When you need to test your website across different URLs, use environment variables to specify a URL for each environment. If you are constantly testing across different environments then set up a new project for that environment and add the base URL and any other configuration you need.
Happy testing! 🎭
Top comments (3)
Hi there, I'm fond of using projects to delineate between environments as well. However, I've found that not all tests need to be run against all environments.
I just came across the
testMatch
andtestDir
properties, which seems like they'd fit the bill.Only thing being, is it possible to pass an array of inputs for either of these properties? So instead of some insane RegEx, it could be a list of file names (or better yet, test names/tags) instead?
Hi @debs_obrien , thanks for sharing, this kind of questions are very common on people that start using Playwright and want to prepare their framework against all their environments.
From my experience, another good approach that I also promote with my teams is to create a function that will encapsulate the logic, will look like this:
The reason I like this article so much is because of its simplicity. Thanks for the great article.