Sooner or later, in any company, regardless of its size, it becomes important to deploy only fully tested applications in production. To save human resources on manual testing of the whole application, it is necessary to focus on unit testing, which ensures the correct operation of each component separately. But if you want to test the whole application — e2e (end-to-end) tests are an answer.
There are tons of testing frameworks: Nightwatch, CasperJS, Protractor. I personally recommend Protractor for Angular and AngularJS. In this article, I will cover basic principles of e2e test code writing that will make your code easy to read and maintain. But only you can decide to fallow them or not.
- Strongly typed
- Autocomplete in VSCode and many other IDE
- It implements many concepts of OOP (inheritance, polymorphism, encapsulation …)
Let get to work!
The structure of the test folders should coincide with the structure of the site (or be approximate to it). For example, if you have a blog that has post list and post page with structure /blog, /blog/post/1, then a folder with a test for the post page has to be in the blog’s test folder.
Test file types
For convenient work your code should be separated by code blocks with different types:
- *.spec.ts — test description for pages or components
- *.page.ts — describe all objects on page and function to interact with them.
- *.object.ts — describe a separate object that is repeated on several pages and functions to work with it.
This structure makes it easy to maintain tests. Even if you change the layout, you just need to change bindings on page.ts or object.ts and your tests will work.
Use this priority of functions to select elements on the page:
- by.model or by.binding
Never use XPath, because, you will ruin test with the slightest change of page structure. And try not to select element by text. Who knows, when it may changes.
If you have any complex component that used on different pages (for example shop item), you can describe it like this:
After select card list you can access card elements with the help of locator() function:
Functions in *.page.ts and *.object.ts
It is good practice to move all interaction function that has more than one line of code from specs to *.page.ts and *.object.ts. That makes the code more readable:
In these files, we are describing not only elements but methods to interact with them.
Name function in camelCase. It has to be easy to understand what function is doing or returning from its name. For example, if it returns boolean use “is” prefix:
For each function, it is necessary to set augments and return types. This way compiler will check types error even before you build your app and show them in IDE:
If your app or website has shared components on different pages, you have to make shared tests in your test app. For this, create “Shared” folder in your project and put the component folder with *.spec.ts inside it. Then in your page test just import component description
or even run a test:
Sometimes you have to use the same function in different specs, like getFirstVisible(), that shows first visible element in an array. These functions you should put in the separate file (utils.spec).
In the next article, we will create a test project, configure web pack build and write our first e2e tests.
Translated from: https://alariblog.com/blogpost/e2e-test