If you already have a subscription, you can sign in.
Enjoy free content straight from your inbox 💌
00:00
In terms of patterns for writing end-to-end tests, the most famous pattern, which is almost inevitable in any project, is the pattern of page object models. Consider the simple case of testing A to-do style application. We bring in test and expect and then before each test we clear all the to-dos using the request fixture followed by visiting the page, by using the page dot GoTo method. Next for our test to make sure that to-dos get added to the page, we use the new to-do input to type in some text followed by the enter key and then we make sure
00:31
that the request has been sent to the backend. If we want to test multiple to-dos, then we have to repeat the same process with a singular difference of typing in a different piece of text. Finally, to verify that the new to-dos are rendered by the page successfully, we expect that the to-do list labels should match the text of the to-dos that we added. There is nothing technically incorrect about this approach and if we run this test you can see that it runs to completion successfully and it verifies that the to-dos are added to the page. But if we look at the code without the comments, it's pretty hard to see what the code is trying to do.
01:05
For example, here we are trying to clear all the to-dos. We have three steps to add a single to-do and then even the expectation by itself is a bit hard to read and if the application code ever gets reflected, we have lots of places in our test to keep up to date and this is just one test. The scenarios will only become more complicated as we add more tests. There is nothing particularly special about the page object model pattern. It is simply a convenient class to wrap the common functionality for reuse and provide a single place
01:37
for updating any page specific dependencies in a new folder. In our project called test details, we create our first page object model in a simple file called to do page, we bring in some types and utilities from playwright test, which include page API request context and the expect method. We create two simple variables, one for the page URL and one for the API route URL. To allow us to create instances of our page objects, we create a simple class called to do. Page instances of this class will need access to the underlying page object created by playwright,
02:10
so we accept that within the to-do page constructor for clearing all existing to-dos, we create a simple utility method called clear to-dos, which accepts a request object and then makes a request to the backend To clear all the current items, we add another utility method to visit the page in which we simply use the provided page object to go to the page URL because it is going to be common for us to clear all the to-dos and visit the page in our test. Before each functions, we create another utility called clear to-dos and visit, which simply takes the request, uses that
02:43
to clear the to-dos and then visits the page. For any access to the page elements, we create simple getters. For example, here we are creating a getter called new to-DO input which simply uses page do ator to find the to-do input for any common actions that we carry out on the page we Create simple utilities. For example, we are creating a function called add to do, which takes a text as an input, types it into the input presses, the enter key waits for the ad response from the backend, and finally even makes sure that the new to-do input is now going to be cleared. We can even create utility functions
03:16
for common expectations. For example, here we are creating a utility called Expect to-dos, which takes A to-do array as input and then expects that the list of to-dos within the page should match the provided to-DOS array. With this class defined, now we have a well-defined contract of how we want to interact with the page in our tests. Once we have our page objects created, they greatly simplify our test code and when done correctly, our tests even start to look almost self-documenting within the same test that we had before. Now completely empty. We start by bringing in the to-DO page class from the test
03:49
details folder within the before each, we simply instantiate a new instance of the to-do page using the provided page fixture and then use its method clear to-dos and visit to make sure that we have a nice clean slate. Also within our test, once we have the page fixture from playwright, we use it to create a new instance of the to-DO page and now we have a simple matter of using the methods of the to-do page to carry out our testing. For example, we add a new to-do and because it has become so easy, we can even expect that right now there should be only one to-do with a simple call to expect to-dos.
04:22
Next we add a second item to the to-Do page and then once more expect that the page should now contain two items. Let's go ahead and run this test to make sure that everything is in order, and of course everything works as expected, but now you can see that the code is much cleaner. It is almost self-documenting. We have an explicit intent of clearing the to-dos and visiting the page. And then for our test we have a very clear actions to add certain to-dos and make sure that they show up on the page.