Keep Selenium tests in the same workspace and run them using Mocha
In this article, we will study how to use Selenium with Angular. More specifically, we are going to do the following:
- set up Selenium by using
npmto install Selenium’s WebDriver and the required browser drivers
- create a second project to keep tests in the same workspace with the application under test
- create a running command to run selenium tests using Mocha
- create and run an example selenium test for a demo application
- review the generated report
So, let’s get started!
Disclaimer: This article focuses mainly on how to set up and use Selenium in an Angular project. Some familiarity with Selenium and its terminologies is preferable but not mandatory.
Firstly, we need to install the required dependencies for Selenium by running:
npm install --save-dev selenium-webdriver @types/selenium-webdriver mocha @types/mocha mochawesome @types/mochawesome mochawesome-report-generator chai @types/chai chromedriver geckodriver
This will install the following dev dependencies in our project:
- Selenium WebDriver is the API we will program against to script and automate a browser.
- mochawesome and mochawesome-report-generator are useful packages for generating test reports.
- Browser drivers allow the respective browser to be automated, such as chromedriver for Chrome and geckodriver for Firefox. The driver for Safari is already installed in macOS.
There are more ways to install the drivers, but in our case, using
npm is the easiest one.
All these packages are installed as development dependencies and will appear as part of
devDependencies in the
package.json file. Tests won’t be included in the production bundle. Therefore, these packages are only necessary during the development phase.
Next, we create a new TypeScript project that will host our tests. We create the following base directory structure. We are going to enhance this project in future parts of this series.
For now, let’s explain the hierarchy of the project.
e2e/tsconfig.jsonis a file indicating that the current directory is the root directory of a TypeScript project. That makes
e2ethe root folder (duh).
srccontains all the source code.
src/commoncontains common utility classes.
.page.tsfiles, which are page object model classes based on the Page Object Design Pattern. We are creating classes that represent the different pages of the application. Then, we define re-usable methods that represents a user’s actions on the associated page.
.spec.tsfiles, which are the actual tests.
Our next step is to add a custom script to the
scripts property in the
Great! Now we can run our tests by typing
npm run e2e.
Don’t be intimidated by the length of this command. Let’s break it down and explain it piece by piece.
&&can be translated as “run the first command and, only if it succeeds, run the second command.”
mocha dist/e2e/testswill run the tests using Mocha (provided the compilation is completed successfully).
--reporter mochawesomeis for setting the reporter we want to be used.
--reporter-options code=false,autoOpen=falseis for setting the reporter’s options. For example,
code=falsemeans “don’t display test code in the report” and
autoOpen=falsemeans “don’t open the report automatically after test execution is over.”
We saved the best for last. It’s time for an example!
We are going to use the demo application from our previous article. Here is what the application looks like:
Long story short, the user can save personal information using this form. The form supports manual saving and auto-saving. Each time new information is saved, a new history log is created. The user can also clear the logging history.
For brevity’s sake, we will only walk through a single scenario, clearing the logging history. We picked this scenario as it showcases more things than the other scenarios included in the demo.
Before we start writing our test, we must take care of a few things.
1. Draft a scenario
Firstly, we need to draft a scenario in our head. Selenium tests are end-to-end (e2e) tests. It’s as if a real user was interacting with the application. Instead, we are programming a “robot” to do these interactions automatically.
To come up with a scenario, think about what you would, as a person, do to test the feature at hand. In our example, given that there are logs, we would simply press the clear button and make sure no logs are visible afterward.
Note that this is just a demo. So, we are going to create the required data in our test. In real-life applications, we would never do this. E2e tests are “expensive” in terms of execution time. Therefore, we would ideally set up the required data differently before the test execution.
2. Make elements identifiable
Secondly, we need Selenium to identify the elements on the page uniquely.
A person can tell where to click because s/he can see the elements. Similarly, Selenium uses ids, classes, attributes, and other things to locate elements.
We simply assign an id for unique elements such as the clear history button. For repetitive elements such as the logs, we attach
3. Create the Page Object class
Lastly, we need to create the Page Object class we talked about earlier. The methods correspond to re-usable actions that can be performed on that page.
4. Write the test
All right! Now we’re ready to write our test.
describe() defines a test suite.
it() defines a test in our test suite.
this.timeout(0) disables the default mocha timeout, which is two seconds.
after are hook methods.
You probably must be wondering what is this
CommonDriver class. This is a wrapper utility class that initializes a
WebDriver instance and sets some specific options.
Other than this, the rest are pretty self-explanatory. If something isn’t that clear, don’t worry. We will see more examples in the next parts of the series.
Before we run our tests, we start the application with
npm run start. After the application has launched, we execute
npm run e2e.
Another thing to remember is that if you’re running your tests in a container, you won’t be able to see them run live. Containers support only
headless mode, in which case you’ll need to uncomment the option in the
The following console messages should be printed when test execution is complete.
All of our tests passed successfully. Yay!
If you found that the console messages weren’t as user-friendly, don’t worry. We’ve got you covered. We’ve set up the mochawesome reporter, remember?
Every time you run your tests, an “awesome” report is generated for you. The report is saved under the
mochawesome-report directory located at the same level as your application and e2e projects.
Here is what a report typically looks like:
You can find the source code in this GitHub repository.
In the next part, we will create a framework and a screenshot utility class for our test suite. The framework will perform global initializations. The screenshot utility will save screenshots of the app the moment a test fails for easier debugging.
In this article, we presented how we can set up Selenium in Angular.
We started by installing all required dependencies. Then created a separate project to host our tests under the same workspace with the Angular application. Next, we added a running command for our convenience. We drafted a test scenario, implemented it, and saw how to run it using Mocha. Finally, we presented the generated report from the test execution.
I hope you enjoyed this article and that you’ve learned something new.
Thanks for reading. Stay tuned for more.