Now that I’ve finished re-building my house (almost) I’ve got two or three years of programming projects to catch up on. One of the most pressing is updating the Motif.org.au site with the new reading tests that have been developed and normed for ‘phase 2’.
My problem is that I’ve been working on the site on-and-off over the last two years, there’s a version on staging which has completed UAT but it took so long that I’ve had to modify the live site with content updates. My old PC died so I’ve lost my old dev environment. I’ve switched from SVN to Git in one dependency. The live site has had a year of traffic too, so the staging database is way out of date. I feel extremely nervous about pulling all this together and re-launching the staging version, before going ahead with the queue of subsequent changes.
Automation to the rescue!
I’ve used Selenium IDE and RC before for full-stack UAT testing, and done a lot of unit testing and UAT scenario testing via PHPUnit so I thought it would be pretty easy to pull together some tests to ensure the site and the language tests are all still working properly while I finish off a list of integrations, package updates and refactoring I want to do before launch. The site isn’t huge and it’s well structured but the language tests have to work perfectly. It would be a pretty serious consequence to be mis-diagnosing children’s learning abilities, due to a software bug. This site really does affect people’s lives.
So I started confidently pulling together a testing environment mostly copied from previous projects but decided to start writing the tests from scratch and use the latest patterns. I came very quickly unstuck, and found the Selenium 2 documentation for both the server, Web Driver and phpunit-selenium to be quite mysterious.
I spent days feeling like I was missing something – I thought it was the proper documentation! In fact I had quite a few major misunderstandings about Selenium and phpunit-selenium. I was doing it wrong.
So partly for my own memory, partly to help anyone else who is diving a little deeper into Selenium testing, I’m going to document my learnings here.
The first main problem was Selenium v1 verses Selenium v2. There’s so much mixing of help and tutorials on the web, it’s easy to get the wrong advice. Even on Stack Overflow almost every question has a mix of right and wrong answers, the wrong ones often in v1 syntax when answering a v2 question. One of the underlying causes I believe is that there’s some helpfully intended but obscure backwards compatibility out there which some people (like me!) don’t know they’re using.
e.g. on the phpunit-selenium readme it says:
“This package contains a base Testcase Class that can be used to run end-to-end tests against Selenium 2 (using its Selenium 1 backward compatible Api).”
Now I’m not sure whether the “it’s” refers to this package or the server, but someone is providing a v1 API! (It’s actually both.) In the case of phpunit-selenium:
- PHPUnit/Extensions/SeleniumTestCase.php – if you inherit from this you use Selenium1 (RC) API
- PHPUnit/Extensions/Selenium2TestCase.php – this implements the Selenium2 API (Web Driver, via the Json wire protocol)
So that should be pretty clear right? Except for the fact the v1 test case is just called TestCase, (which is a mistake we all make when making the first version of anything!) you are in control of which API you use when you make the inheritance choice. However I spent the last two weeks at work updating our hundreds of tests thinking I was using Selenium 2 – because a) we are using Selenium 2 server which is automatically started by Bamboo so I didn’t really get involved, b) all of our test cases extend from our common base class so you don’t see the inherited API class in your face, c) he Selenium HQ website’s attempts at explaining the differences between 1 and 2 make your head spin!
The best documentation for the Selenium 1 API doesn’t seem to be linked from the Selenium HQ website! Luckily Sebastian Bergmann provides it in his brief intro to phpunit-selenium.
The best documentation for the Selenium 2 API is also not on the HQ site! They’ve not finished the docs yet, but seem to be only writing guides and intros not documenting the API itself.
- https://code.google.com/p/selenium/w/list – index
- https://code.google.com/p/selenium/wiki/JsonWireProtocol – what phpunit-selenium implements
OK so that’s that cleared up. But I’m not talking REST to Selenium2, I’m a developer writing phpunit tests! I want to know which classes and methods to call when I’m trying to achieve test tasks. I don’t want to know about REST and HTTP and Java types – it all sounds irrelevant to my interests, but in reality it’s just three steps of abstraction away from where I sit.
Indeed the wiki warns testers away and sends them back to HQ, presumably so they’ll find the client language SDK they’ll actually be coding against. Sadly phpunit-selenium isn’t mentioned on the HQ site, but for PHP developers they point out several implementations of the WebDriver bindings, including the Facebook one, which again confused me to begin with. Although it’s related and implementing the same upstream API, the code samples around the web don’t directly help me write my PHPUnit tests!
So back to phpunit-selenium: where is the best documentation for fighting with Selenium v2 from this class-base?
- Firstly check out the PHPUnit site’s page on Selenium (already mentioned), but ignore the section on PHPUnit_Extensions_SeleniumTestCase which is v1. It’s easy to scroll down the page in a hurry and start reading the wrong stuff!
- This links you off to the Test Cases for phpunit-selenium itself as the main reference. At first this confused the hell out of me, and my head almost imploded in a recursion of unit testing. But I can see why Sebastian and Giorgio are doing this – they’re still working diligently on implementing the v2 API and in true TDD style, the tests of a system are the best functional spec!
- Thirdly the code documentation in the TestCase2 class, these are the droids you are looking for. Well this is where things aren’t really finished, and are partly scuppered by the generalisation of the calling process (using _call for most API commands). There’s a bunch of @method statements in the main classes intro, some of which don’t compile in some documentors (they don’t work for me in PHPStorm for example) and some aren’t linked to the sub-classes which perform the actual work.
- There’s also some relevant API command documentation in other classes such as:
- [UPDATE] Someone has kindly run apigen and hosted the resulting documentation for phpunit-selenium, although I’m not sure what version it is.
- [UPDATE] Check SystemicPlural’s comment at this tutsplus.com tutorial how-to-use-selenium-2-with-phpunit
So at the end of the day, there IS plenty of documentation for using phpunit-selenium with Selenium 2 Server, but it’s just not all been tied together yet. The phpunit-selenium codebase is organised in a very different way from the actual Selenium 2 WebDriver API so it’s really hard to find a one-to-one mapping when using the latter as a reference while coding in the former.
I’m hoping that once I understand it all myself, I will get some time to help out writing some noob-developer-friendly documentation and actually contribute to the huge effort these teams have been putting into providing these amazing tools.
The only problem is, once I’ve learned it all I may forget what it was I didn’t know!