Categories

Testing ajax heavy apps

The project I’ve been working on recently is a web app with a rich UI, using lots of ajax calls. This has caused a lot of problems with selenium tests, which need to wait for ajax calls to finish before finding elements in the DOM to assert against.

Taking the classic shopping cart example, when you add a product to your shopping cart, you expect that the content of your cart will be updated. The chosen item was sent to the server using an ajax call, and on success the shopping cart gets refreshed with a second ajax call. Because those calls are asynchronous, it is hard to know when they have both finished so selenium can confidently make the assertion that the item is added to the cart.

We are using jQuery quite heavily, and all of the ajax calls use jQuery’s $.ajax function. A colleague of mine showed me a couple handy events that jQuery fires, .ajaxStart and .ajaxStop. The ajaxStart event fires when the first ajax call starts, and the ajaxStop doesn’t fire until the last ajax call in the chain has finished.

Here is how we are using it

  1. <html>
  2. <body>
  3.     <input id="ajaxing" type="hidden" value="running"/>
  4.     …..
  5.     <script>
  6.     $("#ajaxing").ajaxStart(function() {
  7.         $(this).val("running");
  8.     });
  9.     $("#ajaxing").ajaxStop(function() {
  10.       $(this).val("stopped");
  11.     }
  12.      // ajax calls here.
  13.     </script>
  14. </body>
  15. </html>

Now when you need to make sure that all the ajax calls have finished, you can poll the hidden input field. The example here is written in scala, but it should be trivial to port to your preferred language.

  1. def waitForAjax = {
  2.  
  3.   while (driver.findElement(id("ajaxing")).getAttribute("value").equals("running")) {
  4.     Thread.sleep(50)
  5.   }
  6.  
  7. }

You may want to set a timeout on this so you are not potentially waiting forever, but I’ll leave that as an exercise for the reader.

HTML 5 Canvas game

Ninja Pirate Zombie Robot

I’ve been busy for the last month, working with a couple of friends to put together an online version of Ninja Pirate Zombie Robot. This was initially going to be an iPhone app, written in Objective C, but after further consideration, we decided to write it using HTML 5 canvas.

The libraries we are using for our JavaScript card game are JSUnitTest, event.simulate.js and JS Prototype. The choices here are largely due to our experience of writing test driven, object oriented code as our day jobs. This was our first game, so this post may not reflect the very best way to write an HTML5 game, so if there are things we could improve on, please let me know.

Test first

This article will just cover our initial set up. I’ll write a subsequent article on tips and tricks we learnt along the way. First we set up a test case using JSUnitTest. This comprised of 3 files.

HTML web page which runs and displays the results of the tests

  1.  
  2. <html>
  3. <head>
  4.   <title>JavaScript unit test file</title>
  5.   <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  6.   <script src="../lib/jsunittest.js" type="text/javascript"></script>
  7.   <script src="../lib/prototype.js" type="text/javascript"></script>
  8.   <script src="../lib/event.simulate.js" type="text/javascript"></script>
  9.   <script src="../src/game.js" type="text/javascript"></script>
  10.   <link rel="stylesheet" href="unittest.css" type="text/css" />
  11. </head>
  12. <body>
  13.  
  14. <div id="content">
  15.  
  16.   <div id="header">
  17.     <h1>Ninja Pirate Zombie Robot unit test file</h1>
  18.   </div>
  19.   <!– Log output (one per Runner, via {testLog: "testlog"} option)–>
  20.   <p>
  21.     Running <strong>test_game.js</strong>.
  22.   </p>
  23.   <div id="game"></div>
  24.     <script src="test_game.js" type="text/javascript"></script>
  25.   </body>
  26. </html>
  27.  

The TestCase

  1.  
  2. new Test.Unit.Runner({
  3.     setup: function() {
  4.         this.game = new Game()        
  5.     },
  6.    
  7.     teardown: function() {
  8.         this.game = null
  9.     },
  10.  
  11.     testGameStartsWith2Players: function() { with(this) {
  12.         assertEqual(2, game.players.length)
  13.     }},
  14. }, { testLog: "game"} )
  15.  

And the bare minimum initial game code

  1.  
  2. var Game = Class.create({
  3.     initialize: function(options) {
  4.         this.players = []
  5.     },
  6. })
  7.  

This was our starting point for our game, which yielded one failing test. We decided to build the rules of the game first, before dealing with the rendering and computer player components. Given that we wouldn’t have the chance to pair on most of the code, we wanted to get the central domain model for the game sorted, so we could then work on other parts in parallel.

In my next post, I’ll cover defining the game domain model, which encapsulates all the rules of the game.

Scala JSON Generator

I am working with Scala more and more at the moment. I find it a really powerful and fun language to work in. One of the recent tasks has been to translate various tab delimited data files into a common JSON format. In java land, I’ve used Jackson to great effect, but it really doesn’t feel very Scala. My colleague and I were busy following the Jackson route and had a working implementation, but it just didn’t feel clean, simple and Scala idiomatic. That’s when we decided to define how we thought the api should work.

One of the great things about using Scala, is it’s a fantastic language for creating DSLs. When I really don’t like the way the code that solves a specific problem looks, I like to write the pseudo code that feels right, and then figure out how to make that work. With Scala, I have had a great deal of success in this approach. We started off defining a JSON generator DSL that looked like this:-

  1. def mapToJson(myMap: Map[String, String]) = {
  2.   val json = jsonObject {
  3.     field("cheese", myMap.get("name")
  4.     jsonObject("Score") {
  5.       field("aroma", myMap.get("smell")
  6.       field("flavor", myMap.get("taste")
  7.       field("texture", myMap.get("squidginess")
  8.     }
  9.     jsonArray("servedOn") {
  10.       jsonObject {
  11.         field("cracker", myMap.get("crackerType")
  12.         field("maker", myMap.get("crackerMaker")
  13.       }
  14.     }
  15.     jsonArray("sampledOn") {
  16.       value(myMap.get("firstTried")
  17.       value(myMap.get("secondTried")
  18.       value(myMap.get("thirdTried")
  19.     }
  20. }

There was another case for jsonArray, which doesn’t involve having a field name, i.e. jsonArray { … }. Whilst attempting to find a way to implement the DSL that would satisfy this, we had to make a small compromise. The call jsonObject {…} and jsonObject(“fieldName”) {…} caused problems because the signatures of the DSL methods were indistinguishable when using them. The compromise we struck on was jsonObject() {…} and jsonObject(“fieldName”) {…}, i.e. just adding the empty parenthesis. This then is the resulting syntax, and the implementation can be found here.

This is a first cut, but as this library was introduced to solve a problem in our production app. It will be tweaked and maintained so any bugs or extra features will quickly get incorporated.

Stubserver 0.1 released

I’ve released a python stub webserver, described in an earlier blog post, on pypi. The features include support for any method (i.e. PUT, POST, DELETE, GET, RHUBARB …), handles chunked encoding, and supports capturing data passed for later assertions.

Because it’s on pypi, you can install using:-

pip install stubserver

or

easy_install stubserver

The verification model is very simplistic, each registered expectation is only expected to occur once. To get more details, please refer to the documentation.

Testing against a Stub Web Server

I wrote recently about improving the way I usually create a stub web server for testing my applications that call out to external web services. This is a particularly common occurrence where I work (Point2) because we have separated out our core services which are interacted with through REST apis. As I’ve mentioned before, this was what started the Django REST models open source project.

Well, I’ve written the code to effectively support the previously described testing api. It is currently part of the above project, and can be found here. It has already proved handy in adding a much needed functional test capability for Django REST models, which has already exposed a bug in the awkward to test rest_client code. As an example, here is the test:-

  1. class FunctionalTest(unittest.TestCase):
  2.     def setUp(self):
  3.         self.server = StubServer(8998)
  4.         self.server.run()
  5.        
  6.     def tearDown(self):
  7.         self.server.stop()
  8.         self.server.verify()
  9.        
  10.     def test_get_with_file_call(self):
  11.         self.server.expect(method="GET", url="/address/\w+$").and_return(mime_type="text/xml", content="<address><number>12</number><street>Early Drive</street><city>Calgary</city></address>")
  12.         address = Address.objects.get(city="Calgary")
  13.         self.assertEquals("Early Drive", address.street)
  14.  

With the expanding usage of REST services, and a growing number of Python applications written against those services, this project is starting to gather pace again.

Why I write Python

I read an interesting thread asking why do you use Python. I’ve been using several languages recently, including Python, and this has been a recurring question. There is much commonality in the responses of others

  • It makes me more productive by removing boiler-plate code.
  • There are many good libraries for Python which are very consistent, making it easy to produce complex applications with few lines of code.
  • Meta programming techniques such as missing method and metaclasses make producing sophisticated frameworks easy.

These are all interesting points, but none of these things are the real reason I write Python code in preference to Java, Scala, Groovy or Ruby. The primary reason for me, is that I really enjoy writing Python applications. I think in a Pythonic way, so writing Python applications is intuitive and enjoyable. I rarely need to battle with the language to acheive what I want to do. A common question that gets asked is “What can Python do that you can’t do in Language X?”. The answer is usually “Nothing, provided you are prepared to write enough code, you can solve all the same problems. It’s just I enjoy writing Python, which means I am more engaged in solving the business problem, and therefore able to consistently get the job done faster, better, and with a greater level of satisfaction in the solution”.

I know this isn’t a scientific answer to the question, but writing software is a job done by people who aren’t mechanised robots. People need to be motivated in order to produce the best results and that includes being able to choose the tools they use based on what makes them happy. Recently it’s been my pleasure to spread a little Python love around my team mates. It’s been great to see the enthusiasm with which they have taken to using it, and the stunned awe when the see just how powerful this ‘Scripting Language’ really is. This has increased the motivation of the team, and as a result we are completing more work, to a higher standard, in a shorter time than we were previously while working in C# .NET

Writing Scala code in IntelliJ IDEA

Just read that IntelliJ IDEA 9 will be split into a Community Edition, and an Ultimate Edition. The Community Edition will be open sourced, and allows the Scala plugin. I’ve been writing Scala code for a few months now, and using IDEA in the office, and TextMate at home. I’m really hoping that I’ll be able to use the open sourced version at home so I don’t have to context switch so much. I’ve tried the Scala plugin for NetBeans, but it is so far off ready, that I prefer using TextMate. I know the scala plugin for IDEA 8.1 works really well, but it doesn’t work in the IDEA 9.0 early access release yet. I hope this gets fixed soon so I can play with scala at home more.

NOTE: I don’t recommend using maven with Scala on the Mac, because it just doesn’t play nicely. Don’t know why, but it’s broken to the point that I no longer even try to use Maven to build my scala code.

Stubbing a REST api in Python

For the last few jobs I’ve had, Service Oriented Architecture has been a strong theme. Having services presenting REST apis that consume and produce XML has been the regular approach. When it comes to testing consumers of those services, I have found Python to be an extremely useful and convenient tool. It’s quick and easy to throw an HTTP server up in Python, and hard code the values that it returns. The problem is though, that I have ended up just adding code to the do_GET / do_POST methods as I add tests that handle different expectations. This ends up separating the expectations and return values from the test, and making maintaining the stub code harder than it should be.

To resolve this, I’d like to add expectations of the stub http server in the same way as with defining mocks. The syntax would look something like this

  1.    server.expect(method="GET", url="/address/\d+$").
  2.         and_return(mime="text/xml", file_content="path/to/response.xml")
  3.     capture = {}
  4.     server.expect(method="PUT", url="/address/\d+$", data_capture=capture).
  5.         and_return(reply_code=201)
  6.     server.expect(method="POST", url="address/\d+/inhabitant", data=‘<inhabitant name="Chris"/>’).
  7.         and_return(reply_code=204)
  8.     server.expect(method="GET", url="/monitor/server_status$").
  9.         and_return(content="<html><body>Server is up</body></html>", mime_type="text/html")
  10.     # execute system under test
  11.     self.assertEquals("<expected><xml/></expected>", capture["body"])
  12.  

So, over the next couple of weeks I’ll be putting this together, which should among other things allow me to improve the end to end testing story for djangoRESTModel.

Spell Checker for the dyslexic

My wife is dyslexic and has long ago accepted that she can’t spell. She has given up on spell checkers, which due to her extraordinary inability to get even close to the right spelling have also long since given up on her. I thought it worthy of mention, that Google is her preferred spell checker when other spell checkers just can’t cope. This is especially useful for names of people such as authors. So, dyslexics don’t despair when your spell checker doesn’t understand you. Google will usually be able to ‘Suggest‘ what you really meant.

Django REST models

Making external XML REST apis more pythonic

At work we have a Django web application where the models are backed by a Java XML REST api. The application is read only, so there is no requirement to write back to the REST api.

We started with copying the data into a local DB, and using regular Django DB models, and we wanted something that would feel very similar, but use an XML REST backend. We wrote an xml_models library, which allowed us to map our models to the XML data, using a declarative style similar to the Django DB models. The library has been open sourced and can be found on sourceforge.

Here is a simple example:-

Suppose there was an API http://myaddressbook.com/addresses/{addressID} that returns the following XML

  1. <address id="123" num="3301">
  2.   <street>8th Street</street>
  3.   <city>Saskatoon</city>
  4.   <province>SK</province>
  5.   <country>Canada</country>
  6. </address>

The model might be defined as

  1. class Address(xml_models.Model):
  2.   id = xml_models.IntField(xpath="/address/@id")
  3.   num = xml_models.IntField(xpath="/address/@num")
  4.   street = xml_models.CharField(xpath="/address/street")
  5.   city = xml_models.CharField(xpath="/address/city")
  6.   province = xml_models.CharField(xpath="/address/province")
  7.   country = xml_models.CharField(xpath="/address/country")
  8.  
  9.   finders = { (id,): "http://myaddressbook.com/addresses/%s" ,
  10.                     (num,street): "http://myaddressbook.com/addresses/num/%s/street/%s"}
  11.  

And using the finder method would be like this

  1. address = Address.objects.get(id=123)

That’s the basics. We are mapping much more complex relationships with collection fields, date fields and more. Take a look and let me know what you think.