Personally I see playwright
as a tool that goes into the direction of system/end-to-end tests. So I used playwright
+ jest
to build-up user journeys and integrated them in a CI/CD process.
Since playwright
created it's own test runner with useful features like taking videos and trace on failures, it would make sense to switch from jest
to @playwright/test
. On their home page playwright
recommends to use test fixtures so I definitly want to include them in the switch.
In the following I will take amazon as an example.
With playwright
+ jest
the first thing that I did was to create a function for generic setup of the environment:
function setupSuite({ browserOptions, userConfig }){
// create playwright browser and use browserOptions as overrides
// create page from browser
// register self-implemented trace and screenshot reporters to page
// go to baseUrl of current environment (e.g. local, branch etc..)
// click on cookie banner, since it's blocking the UI
// create a user based on userConfig (e.g. user has amazon prime user? payment options? etc.)
// return { browser, page, user, ... }
}
And of course a function to clean up everything again:
function teardownSuite(suite){
// close browser
// delete user
// etc..
}
Then I would use a file for each user journey. In case of amazon a user journey could be the successful processing of an order:
describe("Successful Order", () => {
let suite
beforeAll(async () => {
const userConfig = { isPrime: false, paymentOptions: [ "paypal", "visa" ] }
suite = await setupBrowser({ userConfig })
// I actually extracted that logic in a function to be able to use it in other tests too,
// but just want to make clear whats happening here
const { page, user } = suite
await page.fill(".login-username-input", user.username)
await page.fill(".login-password-input", user.password)
await page.click(".login-submit-button")
})
afterAll(() => teardownSuite(suite))
test("search for toothbrush with suggestions", async () => {
const { page } = suite
await page.fill(".search-input", "tooth")
await page.click("text='toothbrush")
// hit enter
// do some assertions to check if the search was really successful
})
test("click on first item and add to chart", async () => {
// page actions and assertions
})
test("go back, click on second item and add to chart", async () => {
// page actions and assertions
})
test("go to chart and pay", async () => {
// page actions and assertions
})
test("check order confirmation mail", async () => {
// page actions and assertions
})
})
As you can see I split up my test in logical parts to make it more readable and also to see at which step (test
block) it failed.
What would be the best way to migrate this to @playwright/test
+ fixtures?
- How would you migrate
setupSuite
/teardownSuite
? Yes you could use a fixture, butsetupSuite
expects arguments like the userConfig . Is it possible to have parameterized fixtures? - How would you structure tests with fixtures? If you want to simulate complete user journey the tests are getting bigger than just testing a login for example. A test block would then have a lot of lines without the possibility to structure them.
- Is it possible to setup a page so it's shared accross all tests? The
beforeAll
hook doesn't receive any page and the eachtest
block always receives its own page. This means that there is no connection betweentest
blocks. If you create a page manually inbeforeAll
and use the same page instance in every test it would probably be a bad practice and video and tracing would probably not work.. so what can be done here? - Are user journey like tests actually bad? I feel like they can't be combined well with the fixture approach of
playwright
as mentioned in the docs. Fixtures inplaywright
feel like verydata-driven
which doesn't really fit toend-to-end
testing IMO.