When I set myself a Q4 goal of getting a small suite of Mozilla’s WebQA tests running on Android I didn’t think it would be much work. The AndroidDriver has been around for some time, and from what I understood it was pretty mature – I had even run a couple of tests locally against it and they worked well. What I found was there were a couple of important gotchas…
The first was that the port forwarding that’s necessary to run tests on an Android emulator or device binds to localhost. This isn’t a problem so long as the test commands originate from the same machine as the emulator/device is attached to, however that doesn’t make it very useful for Selenium Grid, where we want to run several emulators/devices remotely.
I was suprised that this issue had not come up before… I didn’t think I could possibly be the first person to want to hook up an AndroidDriver to Selenium Grid..! After searching around for a solution I decided to leave things for a while to take care of other priorities. I was then pulled back into the problem when my fellow Mozillian Raymond Etornam came across the same issue and was looking for a solution.
Raymond and I approached Dounia Berrada, who heads up the AndroidDriver efforts at Google, and as a result of this discussion, Raymond raised an issue in the Selenium project. Dounia got to the bottom of the issue and found a very simple solution, using socat to listen on another port on all interfaces and forward traffic to the localhost bound port forward configured by ADB. The Selenium project’s wiki has been updated with the solution.
The second issue I had was registering the AndroidDriver with Selenium Grid. This is simply a case of posting the correct JSON to the server, and is something that’s done for you when launching a Selenium server. The quick solution would have been to just start a Selenium server with the details for the Android node. This feels like too much of a hack, plus I didn’t really want the server running constantly when it’s not really doing anything other than consuming resources.
I decided to write a very simple Python package that would take a few arguments, construct the necessary JSON and post it to the Selenium Grid. I’ve released this as FlynnID (there’s a reference to ‘The Grid’ if you look hard enough) and it’s available on PyPI, with the source code on github.
A more long term solution will be to have the AndroidDriver register with a Selenium Grid when it’s started. If anyone is keen to look into this please get in touch!
So with these issues resolved, I was able to finally put together the first mobile test suite. I migrated the Input tests to WebDriver, did a lot of cleaning up, and split them into desktop/mobile tests. There’s only one mobile test there at the moment, but now we have everything in place we can go full speed into test development! If you’re interested in helping us out to write more tests or improve our frameworks/infrastructure then the WebQA page on QMO is a great place to start.
Oh, I’ve also added a cute Android iconĀ
to Selenium Grid, which will be available from version 2.16.0.
Thanks for this info — I got the android emulator registered on the grid thanks to your flynnid python script.
I had one question about a comment you make here, though. Are you sure this is quick and easy:
The quick solution would have been to just start a Selenium server with the details for the Android node.
You want to tell grid where the android emulator is running, and the port is part of that equation. As far as I can see, if you start the selenium server and set the port parameter, it will also run on that exact same port. So there will be a conflict between the emulator running on port 8081 and the selenium server you’re trying to start on port 8081.
This is what I ran into before I started asking over in the IRC channel, and I just want to see if I’m missing something totally obvious.
The fix, it seems to me, would be to have the selenium server allow ports per browser definition. I tried setting port per browser, but it didn’t seem to change anything. I didn’t dive into the code to see if it should or shouldn’t work, but since it failed and there’s no mention of that feature anywhere I assumed it’s not actually a feature.
Here’s an example of what I’m describing:
https://gist.github.com/1587576
Hey stackedsax,
Good point. I’m sure I had this running locally, although I can’t see an obvious way around your issue. You could try starting an additional node with only the Android capability, and set the remoteHost property to match the actual host/port of the Android device/emulator. I believe this is what is sent to the hub when registering a node, and although it usually reflects the host/port properties for the node you should be able to override it.
Also, have you tried using FlynnID?
Cheers,
Dave
flynnid is what I’m using, yes. It threw some error with python 3.2, but was fine with 2.7.
I’ll try setting remoteHost in the json file and see if will work. Thanks for the suggestion.