Introduction
Fixtures set up the right environment, providing the test with exactly what it needs and nothing more. They are isolated between tests and operate on an on-demand basis, allowing us to define as many as needed. Playwright Test will then set up only the fixtures required by our specific test, optimizing efficiency.
Built-in fixtures
Playwright comes with several built-in fixtures that we are likely to use most of the time. Following are few of them.
page: Isolated page for the test run.
context: Isolated context for the run. The page fixture belongs to this context.
browser: Provides necessary resources for the test to run. Browsers are shared across tests to optimize resources.
browserName: The name of the browser currently running the test.
It is important to note that fixtures can only be used by destructuring them. This is because the lifecycle of the fixtures start when we destructure them in a test.
If we use fixtures without destructuring them, Playwright throws an error.
Custom fixtures
We can create custom fixtures for any data or helpers we might need in a test. For doing this we can make use of the .extend
method. Each fixture
has a setup and teardown phase separated by the await use()
. The use
function is passed as an argument to the fixture function, and is used to
provide the fixture object to the test function. To utilize the fixture in our tests, import the extended test
we have created into our test files instead of importing it
directly from @playwright/test
.
Fixture Lifecycle
The lifecycle of a fixture can be classified into three steps. The setup, usage and teardown step. To understand it better consider the following sample fixture.
The output when executing the above tests will be as follows.
As seen from the output above, the fixture lifecycle is dependent on the test lifecycle. The lifecycle is as follows.
-
Setup: Here we can write all the logic to setup our custom fixture. Some common usage includes initializing a POM and
setting up the page for using the fixture. This step takes place before the test begins. Playwright goes through all the
fixtures we have destructred in a test and sets them up.
-
Usage: This is the step where we actually use the fixture. In the fixture we can provide any useful data or helper to
the tests through the use
command. Doing this replaces all the occurrences of the fixture name
in the tests with the value we pass in the use
command.
-
Teardown: This is the final step in the fixture lifecycle which can be used to execute some cleanup actions. This can
be used to do something like cleaning up the test data from a site after testing in it. The teardown of a fixture is
executed only after the dependent test has completed execution.
This approach spares us from the need to include the repeating logic within individual tests, promoting cleaner and
more efficient test code.
Page Object Models as fixtures
Imagine a Page Object Model named TodoPage
representing the todo page of the application and that it includes methods that facilitate navigating to the page, adding additional todos, and removing existing ones.
In the provided code snippet, it's important to highlight that a class variable named todoItems has been introduced. This addition was made because of the need to access the todo item multiple times within the class.
In the below code snippet, a fixture has been set up, creating an instance of TodoPage, which is then shared with tests through the await use(todoPage)
function call.
Hence, to employ the todo page methods in our test, we can effortlessly import the test function from fixture.ts
.
Note that custom fixture names should start with a letter or underscore, and can contain only letters, numbers and underscores.
This is a theoretical chapter. There is nothing to commit in here. If you have made some changes to the project, clean them up by executing the
following command.