Saturday, March 1, 2014

Setting Up Jasmine + Selenium + PhantomJS

I've started a new project as a means to develop skills working with Jasmine, Selenium, Karma, AngularJS, MongoDB and whatever incidental tidbits of cool webdev technologies crop up along the way.

My very first story was to create the landing page for my app which will have a status header on it.  As the first story, the header content is static -- because no way of changing it has been developed yet.  Despite being static, I still want a test for it and set about creating a test in Jasmine which would use Selenium to confirm the existence of this header and text within it.*

Surprising challenges stemming from an all-JavaScript environment and a non-Mocha choice in testing frameworks arose which made this far more time-consuming than expected.

So, for posterity, I present the steps required to get started.

Installing the Tools

Starting from my code on "the outside" of the environment, I first needed the Jasmine test framework in which to work:
bower install jasmine
Installing jasmine using Bower

A core aspect of testing this behavior is loading up a browser and verifying that the header is indeed present. This means bringing in Selenium bindings that I can use within my Jasmine tests.
npm install selenium-webdriver
Installing selenium-webdriver with NPM

Theoretically one can leverage selenium-webdriver from a client page, however I will want to incorporate this into my automated testing and see no reason to avoid it. All of that is to say that I needed a Jasmine test runner for node.
npm install -g jasmine-node
Installing jasmine-node globally with NPM

FYI, in order to install this I needed to reconfigure my npm repository to http.

I have really come to enjoy using Koding for my development, because it lets me maintain my workspace across any machine with Internet access and a modern browser. However, as a hosted terminal-only VM, having Selenium try to pop open Firefox and Chrome won't exactly work.  So I brought in PhantomJS for headless browser testing.
npm install -g phantomjs
Installing PhantomJS globally with NPM


Notes on the Tests

Working with selenium-webdriver is pretty frustrating at times, because it often fails in complete silence leaving you floundering for answers.

Here are the critical items I found this way:
  • The documentation shows three styles of test writing: one in Java, a second using continuation passing (i.e. callbacks) and a third using promises. Promises in selenium-webdriver are apparently not fluency sugar, promises are required! Expect a long, but readable, chain of "then" methods.
  • findElement does not pass undefined if nothing is found, it instead "rejects" the promise and flows to the error handler.
  • Tip: instead of "expecting false to be true" in order to force a failed expectation in the error handler, I suggest "expecting the error not to be defined." This has the added benefit of outputting the error object's contents in the test log.

Get it Running

Lastly fire up Selenium and set jasmine-node loose on the tests. For bonus points, it can be set it to automatically rerun the tests when changes are detected in the specs (i.e. the tests) or the code file(s).

java -jar selenium-server-standalone-2.40.0.jar &
jasmine-node --autotest tests/ --watch index.html

The Future

While selenium-webdriver is capable of launching the stand-alone server from code, I have yet to figure it out and am living with one additional command (OH NOOOES!).


*It "appearing" constitutes a behavior which adds value according to a user story, and so it should be protected against regression.

3 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete

Note: Only a member of this blog may post a comment.