End-to-end browser testing with docker
Update 2015/09/13⌗
As of, at least, docker 1.8.1 when you start a container the /etc/hosts
files inside other containers in the same environment get updated with a hostname making communication between containers much easier:
172.17.0.5 e2e-docker.bridge
172.17.0.5 e2e-docker
172.17.0.6 seleniumff
172.17.0.6 seleniumff.bridge
(Example is available on github).
Unless you want to install selenium in the same container as your app, which defeats the purpose of containers, you need some kind of bidirectional link - which is a problem as linking containers with --link
creates a source to recipient unidirectional link.
You could look up containers IP addresses, but you would need to look these up at runtime every time.
Docker’s new network interface is a solution as you can see in option 1 here. Unfortunately at the time of this blog post, this feature is still experimental and not available in the latest stable docker.
So, for now, a hassle free way of doing this is using the --net
flag with docker run
to join the two containers’ network stacks.
--net container:<container name|id>
will reuse another containers network stack.
See these slides on the --net
flag for a diagram of what is happening slideshare.net/allingeek/single-host-docker-networking.
docker run --name seleniumff -d -p 3030:3030 -p 4444:4444 -p 5900:5900 selenium/standalone-firefox-debug
docker run -it --name e2e-docker --net=container:seleniumff -v ${PWD}/:/usr/src/ -w /usr/src/ iojs:2.4.0 /bin/bash
In the code above all the ports that need to be published are done on the selenium container. 3030
that the app inside e2e-docker
will be running on, 4444
the port selenium is running on on the official selenium images, and 5900
is used to access the container with a vnc client if you would like to watch the browser in action vnc://<boot2docker-ip>:5900
see the selenium debugging documentation.
You can then start running end-to-end tests that are located in the application codebase:
client
.url('http://0.0.0.0:3030')
.isVisible('.button-collapse').then(function(isVisible) {
expect(isVisible).to.be.false;
})
.windowHandleSize({width: 800, height: 600})
.isVisible('.button-collapse').then(function(isVisible) {
expect(isVisible).to.be.true;
})