How to setup Angular end-to-end testing with Headless Chrome on Travis CI
Continuous integration has become a big part of modern software development. Continuous integration (CI) is a DevOps software development practice where developers regularly merge their code changes into a central repository, after which automated builds and tests are run. Main advantages which CI promises are:
- Improve developer productivity
- Find and address bugs quicker (usually by performing the tests on the CI).
- Deliver updates faster (see continuous deployment)
While running unit tests on the CI usually works rather easy, setting up end-to-end tests is often more complex because we need a real browser to run these tests. As Chrome is the most popular web browser, it makes sense to execute our tests against Chrome. I've previously written an article why end-to-end and testing in general is a crucial part of modern software development projects.
I assume you have some kind of JavaScript project using NPM or Yarn. In this tutorial, I will use Protractor as my end-to-end test framework, Jasmine as the testing assertion framework (used inside the test files) and Travis CI for running the automated tests. If you need a full example, then check out this repository on GitHub.
Setup Protractor for headless Chrome
If you do not have Protractor installed, then follow these short instructions to do so. Add the following to your protractor.conf.js file to allow Protractor to use Chrome for running the end-to-end tests. This will not change a lot for local development as running Chrome locally is easy. However, when we are running on a server, we cannot use normal web browsers like Chrome. Instead, we need to use a headless browser: a web browser without an UI. Fortunately, Chrome 60 introduced support for headless browsing so we can run our tests in Chrome. Now, we do not need workarounds like xvfb anymore. Puppeteer is a handy Node library made by Google to control Chrome via JavaScript API which we will need when we are running on CI. Stick with Chrome for headless testing and do not use PhantomJS: a headless browser which was pretty popular but it is now deprecated and outdated!
process.env.CHROME_BIN = process.env.CHROME_BIN || require('puppeteer').executablePath();
exports.config = {
...
chromeOptions:{
args:
binary: process.env.CHROME_BIN
}
}
Setup your CI configuration
If you are using other CI like GitLab or Jenkins, then you may need to modify the script a little. I am using Node.js (8.x) and I am doing the following (check my package.json below for the exact scripts):
- Installing the necessary dependencies: in this case, we especially need Puppeteer, Protractor and Jasmine.
- Running the unit tests (not necessary for this tutorial but you should do it nonetheless).
- Updating and starting the underlying Selenium server which is used by Protractor. You need Java in your CI because Selenium is built with Java. If you are using Travis CI like I do, then you should be already good to go.
- Running the end-to-end tests with Protractor which will perform the tests in Headless Chrome. If you want to run on localhost (e.g. because there is no deployed version), you need to run your web app in the background before running the end-to-end tests (e.g. for Angular: run ng serve)!
language: node_js
node_js:
- "8"
# Cache node_modules
cache:
directories:
- "node_modules"
install:
- npm install
script:
# run unit tests
- npm test
# update Protractor and Selenium including ChromeDriver
- npm run webdriver-update
# launch Selenium standalone in the background
- npm run webdriver-start
# run Protractor E2E tests
- npm run ci-e2e
This is how my package.json looks like. Pay attention to the & which makes the script run in the background: we need to do this as Selenium needs to be running before running the end-to-end tests.
"scripts": {
"webdriver-start": "webdriver-manager start &",
"webdriver-update": "webdriver-manager update",
"protractor": "protractor",
"ci-e2e": "protractor --capabilities.chromeOptions.args=--headless --capabilities.chromeOptions.args=--no-sandbox protractor.conf.js"
}
That’s it. Apply your changes and your CI should now run your tests on every commit to your repository.
Conclusion
Thanks for reading this tutorial about how to setup Protractor end-to-end testing on Travis CI using Puppeteer. As you've seen, setting up a CI which tests our application automatically is rather easy and it brings huge benefits especially for larger projects. As user interfaces of modern applications will only become more sophisticated, the need for end-to-end testing has never been higher. Let me know in the comments if this tutorial helped you.