Today I will tell you a little trick how to make your test code a bit fancier and easier to maintain. The PageObject pattern is quite common in Selenium testing world, but it can be also useful when you are writing unit tests on every single UI-Component.
Disclaimer: there will be no any new library that you need to install before get started. This article is about code pattern. You can adopt it with any technology stack, React is used here only for example, but it is not necessary.
But there is a Github repo with examples from this article, that you can bookmark for future reference.
For example, we have a LoginForm component, that provides a simple interface for authorization. For sake of simplicity let’s put state handling logic aside, here will be stateless component:
Let’s try to test out logic. Let’s check that we can pre-fill our inputs with values. Also, we will follow actual best testing practices and will use enzyme library to render our component to testing. So far, test would look like this:
Then we need to test one more use case. Let’s add one more test and refactor it, by moving duplicated code into helper function:
But we still couldn’t get rid of code that finds us form fields. We have a lot of similar
component.find(...)calls that should be also replaced with a helper. Off the top of my head comes the idea to move selector strings into constant to make them reusable. But
component.find(EMAIL_FIELD)doesn’t look much better than code before. Here can be a better way how to organize all elements selectors, you can create a PageObject.
Now we have a single place to describe our component and all interactive elements inside. Every time, when the component inner structure will change, we need update only those accessors, all other code that uses them can be unchanged. Probably, other developers, who are going to support your tests later, will thank you for this helper.
Note, that we have created
formFieldgetter, that accepts a parameter. You may find this not acceptable for you, as an alternative you can create special methods for each element, like
passwordField(), it is also okay and up to you.
Let’s put all things together and update our test suite:
Currently, our test code encourages to do everything through Page object. This can be considered as a good practice, because every time when you are going to do something new, you need to define an accessor, that may be reused later. On the other hand, you can always check what component can do, by looking Page object definition.
Finally, let’s add one more test on handling submit. We can not only use page object to read data but also to simulate user behavior on the component:
That’s it. Page object wrapper gives you nice API to interact with your component, so test code will be more expressive and neat. And this doesn’t require so many efforts from you, just follow this simple pattern.
However, we used React here, it is not required. You can adopt this pattern with almost every framework that has a conception of UI-Component. The actual implementation of
component.find() method would be different, but the general approach with
Page object will be the same.
Here is a Github repository, that contains code from this article and more other examples. I am going to maintain it and add more examples for more complex cases. Feel free to ask any questions and send pull requests!
I hope, this pattern will help you to test your components. Of course, here some more other things that also could help you — custom matchers, data-builders — but that will be another story. Happy coding and stay tuned!