One of the most appealing features in Ember and Ember CLI is the ability to easily create functional or acceptance tests. But, the everyday interaction between UX and development, can hurt how these tests are maintained. Here, I try to describe an approach that helped us overcome this problem.
Let’s consider a simple example. Let’s assume we have a list of users and, we want to validate that a table with 2 users is rendered, so that we can later validate each user’s name.
1 2 3 4 5 6 7 8 9 10 11 12 13
Ember, and more specifically
ember-testing, provide a DSL that simplifies creation and validation of these conditions on our tests. An example of such an acceptance test in Ember would be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
As we can see in the above example, after visiting the
/users route we validate that the data shown is what we expect.
While working on a client project, where we generate dozens of acceptance tests, we noticed that many of the CSS selectors used to look up elements were repeated across tests. In some cases, this repetition seemed like a smell.
Then, in some cases the complexity of selectors used prevented us to easily identify what we were trying to test. This can become very confusing, concealing the original purpose for the test. Take for example:
Another issue was how maintainable such tests became. For every change in the HTML, no matter how big or small, we’d probably need to update many tests to make these CSS selectors match.
Here’s where a widely-used design pattern came to the rescue: Page Objects. The main idea behind this pattern is to encapsulate the page structure being tested with an object, hiding the details of its HTML structure and therefore exposing the semantic structure of the page only.
In our case, the goal was to make the intention of the test clearer, hiding the fact that the users list is an HTML table. We also wanted to make our assertions as obvious and concise as possible, easier to read and understand.
Back to our example, this is a possible implementation for a Page Object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Now, we can take advantage of this object and write our acceptance test in an simpler manner:
1 2 3 4 5 6 7 8 9 10
As we can see, the intention of what we want to test is much clearer after applying the Page Objects pattern.
A step further
After applying this process to our application and introducing several objects, we started to notice a few additional patterns emerging. Our team decided then to extract those into auxiliary functions, which made the creation of Page Objects even easier.
We were then motivated to extract this into an Ember CLI add-on named ember-cli-page-object, which provides a small DSL for creating Page Objects in a declarative fashion.
If using the add-on, our previous example translates into:
1 2 3 4 5 6 7
A login page, for example, can be modeled like:
1 2 3 4 5 6 7
This allows to express test intentions in a cleaner way:
1 2 3 4 5 6 7 8 9 10 11
You can check out more examples and instructions on how to plug it into your own projects here.
Try it out! We’re always looking for ways to improve the project. You can contribute by suggesting new features, fixing bugs, improving the documentation and working on the features from the wish list.