Web Automation: WebdriverIO and Docker Selenium
Test automation is an essential part of delivering quality software faster. The benefits of automation are maximized when you choose the correct tools that enable easy adoption and faster development. Anyone who have tried at least once to write web automation tests knows how tricky can be to setup the environment and configure the browser drivers.
In this tutorial we’re going to present a solution that addresses the challenges of automation and let you focus on writing tests.
Before we dive in…
This article assumes you’re familiar or at least have some basic knowledge using:
- Node.js and npm
- Docker and docker-compose
- Visual Studio Code editor — if you follow the debugging section
$ git clone https://github.com/labs42io/web-automation.git
If you follow correctly the quick start instructions from the repository, a test report will be opened in your browser:
How It Works
The focus of this tutorial is to present a solution that lowers the learning curve of web automation. Let’s see what are tools and their roles used to achieve simplicity.
Selenium is a popular open-source web-based automation tool. It consists of hubs and nodes. Hubs distribute work to nodes, nodes execute browser instructions. Selenium is designed to support scaling. But, installing and configuring selenium locally is a lengthy process. To overcome that, we use …
Build once, run everywhere!
Docker is a famous tool that allows you to easily build and run environments with all you need. Thanks to docker-selenium team we can run selenium hub and nodes with docker and avoid any local installation and configuration required by selenium.
A Next generation of WebDriver test framework for Node.js.
Selenium automation works on top of WebDriver protocol which is implemented by W3C and supported by all major browsers. WebdriverIO is a Node.js library that implements the protocol and expose simple commands to interact with a browser.
- Bridges the gap between business and technical people
- Automates the software documentation that’s up to date and shareable
- Accelerates the development of automated tests
There are over 150 snippets that can be used in Gherkin feature files. A snippet look like a natural language sentence. Under the hood, there is a regular expression that matches it and maps to a function implemented in TypeScript.
By using TypeScript you get the full power of code completion, easy and discoverable WebdriverIO API. ESLint is right there to help you keep your code consistent and avoid common mistakes.
To sum up, our tech stack is composed of:
- Selenium — used to execute browser commands
- Docker — used to run selenium in containers
- Cucumber — used to write feature files and run the tests
- TypeScript and WebdriverIO — used to provide implementation for reusable Cucumber steps
A Cucumber test usually follows the pattern:
- Put the system into a particular state
- Interact with the system by executing the test steps
- Evaluate the final state of the system
To describe the above behavior, Gherkin syntax uses the following common keywords:
- Given — used to describe the initial state of the system before we start interacting with it
- When — used to describe the interaction with the system
- Then — used to make assertions and evaluate the expected outcome
You can learn more about Gherkin syntax and additional keywords using the official documentation.
Let’s see an example:
The feature file is self-explaining. It opens Google, types WebdriverIO in the search input, hits the Enter button and checks if the result box is available. As you can see, it is easy to read and doesn’t require any technical knowledge to explain what’s happening.
Each sentence that follows one of the Given, When and Then keywords is matched to a TypeScript implementation:
Thanks to Christian Bromann we have an extensive list of predefined snippets that are documented in this repository. Using the snippets, you can start writing feature files without the need to dig into Selenium and WebdriverIO documentation.
Web automation testing is more complex than unit testing. There could be a lot of external factors that might fail a test for the same environment and conditions — so called flaky tests.
In some cases, to implement a more complex feature file, or to find out why a test is failing you might want to see the test visually being executed in the browser. At the same time, you need the full debugging capabilities to be able to inspect the current state, and why not, even to inspect the browser rendering.
I hear what you’re saying now: “Wait! We run browser drivers with selenium in docker containers, there is no UI and no possibility to directly interact with it”. Well, it appears the awesome team behind the docker-selenium repository, built docker debug images that come with a pre-installed XVFB and VNC servers. And what is that?
- XVFB emulates a display in memory and allows you to run graphical applications (in our case, inside the running docker container) like for example a Chrome or a Firefox browser.
- VNC has two parts: on one side there is the server running inside the container, on the other side on your local machine, a program like VNC Viewer that allows to connect remotely.
Now that you understand the big picture, let’s try to debug and see the execution of the test that runs the Google search.
Selenium debug images
Before we begin, we need a running selenium infrastructure. The following command starts docker-selenium debug containers:
$ npm run selenium:vnc
To connect to a running VNC server inside a selenium container you need a program like VNC viewer.
You can connect either to the container running Chrome (127.0.0.1:5900) or Firefox (127.0.0.1:5901). Once connected, you should see the desktop that is rendered inside the container.
Now, let’s say we want to pause the execution at this step in the Gherkin feature file:
Then I expect that element "#search" becomes displayed
We cannot place breakpoints in
.feature files, but we can easily track the TypeScript function used to execute it:
Make the Gherkin feature file active in the editor (we use Visual Studio Code here). From the debug menu hit the “VNC Debug current test” option. Execution starts and shortly in the VNC viewer you see the browser executing the test steps.
Once the breakpoint is hit, in the editor you have your usual experience of debugging code, including navigation and inspection. At the same time, in your VNC session you’re free to interact and inspect the browser tab executing the test:
And that all without any local driver installation. If you want you can even configure the tests to run against a specific browser version. See the instructions for that in the referenced repository.
In case you want to skip debugging but still visually see the browser interaction, run the below command instead of starting the debugger:
$ npm run test:vnc
Being able to run and debug tests on your development machine is powerful. However, working in a (successful) team requires your web automation framework to be part of a CI process.
Running the selenium infrastructure is achieved with docker containers. Therefore, integration with a CI tool requires only that it supports running docker and docker-compose commands.
There is a Dockerfile to build an image with Node.js, npm and Cucumber tests. That means you can execute the tests even without local Node.js and npm installation, only docker!
docker-compose -f docker-compose.ci.yml up --abort-on-container-exit --exit-code-from node
Web automation is very powerful, however not every team and project adopts it due to the setup and configuration overhead.
In this article we presented a solution for easily writing tests with Cucumber and execute them in a browser running inside a docker selenium container. Despite running the tests in docker containers, we showed how you still can have full debugging capabilities and interact with the browser using a VNC viewer.
This article shows only the big picture. You might find more information on how to customize the framework in the referenced repository. Still need help or have a question? Write to us, we would like to hear from you.