Tag Archives: rack unit test

Working toward a testable Sinatra application

One of the prime goals I had when starting writing a simple Sintra application was to make sure unit testing was done from the start, a vague sort of TDD, given that I’m not  professional developer and I’m not mad about ideaology; I’d had made very little trying to build unit tests for Rails applications, especially when it comes to sessiosn and authentication. No testing, no application.

Even though Sinatra is a small footprint and quick to get going, I still found it very opaque and the Rack test library very secretive and deceptive. It took me 10 days trying to figure out 4 tests for my application, though, as painful as it was, I do have a better (and more coherent – never my strong point) application as a result.

Ultimately, however, I found it much easier to design the testing code for the transactions I wanted using curl because it is so much easier to figure out what is going on.  I really wanted to run a command that I *knew* was submitting data in the format I wanted so that I could sort the routing code around it. Something like,

curl -v http://localhost:4567/package-inventory/packages/new -H 'Content-Type: application/json' -d '{"hostname": "thisbox", "packages": {"first-package": "4.9.", "my-package": "1.2.", "your-package": "4.5.6-0."}}'

Once the server is reponding as expected, it can easily be added to an integration test with a snippet like

jdata = {}
 jdata[:hostname] = hostname
jdata[:packages] = {}
 ["first-package 4.9.0", "my-package 1.2.3", "your-package 4.5.6-0.1"].each do |pkg|
  jdata[:packages].merge! Hash[*pkg.chop.split(/ /)]

The submission can be completed using something like

 request = '/package-inventory/packages/new'
 headers = { 'CONTENT_TYPE' => 'application/json' }
 post request, jdata.to_json, headers
 assert last_response.ok?

On the receiving end of the POST we hve to remember that the incoming data is a SringIO object and as such is accessed like a file stream,

jd = request.body.read.to_s
 jdata = JSON.parse jd

I initially made the mistake of treating the request body as an array to be referenced several times and wondering why it had disappeared: assign it to a variable an be done with it! I also spent some time trying to access the submission through the params hash without realising that that only applies to symbolised references on the incoming request.

After parsing, we then have our data to do as we please. Based on an example, I maintained the return messages (for status or data return) as a hash finishing off each route with,


helping ensure that all inbound and outbound requests are in the same format.

I still wouldn’t say that I’m fully comfortable with the unit tests, but they do work mostly as expected, even for failure conditions.

But as a comparative exercise, I’m going to produce Python version of the same service using Flask and a unit test process, bearing in mind that this will be my first ever Python program; the early signs are quite promising.


I found the last comment at http://stackoverflow.com/questions/18449428/sinatra-unit-test-post-with-json-body (eventually) useful, but ignore the comment advising against using JSON to transfer data; such is the variability of the Stack.




Why so hard to do the right thing?

Just when I thought I’d found something really cool in Ruby that was going to produce simple applications and exploring a development lifecycle…

I really, really want to be able to write unit and integration tests for teh code I produce. With Rails, rspec is a nightmare, especially when combined with sessions and authentication.

So I take a step down to Sinatra and Rack. I get some simple code for a little service and the GET request for resource works as expected. But 3 days trying to get the unit test function to be able to post data is just too much. None of the official documentation mentions it never mind examples; so many variations on StackOverflow; verbatim copied code from blogs that has syntax errors.

It’s not even that my  server app can’t process POST data, it is that the unit test gem makes it impossible to debug the transfer, whether or not I’m a numpty.

This time I’ll abandon the project and the follow-up applications I had in mind for Sinatra and write it off as another Ruby dead-end. I’m sure people do get it working but I give up.