Space Vatican

Ramblings of a curious coder

Unit Testing Core Data Iphone Apps

This is probably obvious, but in the interest of saving someone else the few minutes I spent scratching my head on this one…

Your app probably has some code that looks like

1
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]

If you pass nil then the main bundle is searched. When your an iphone app, that is the app itself - no surprises there. But when you are a unit test bundle, you are no longer the main bundle (the test rig application is). You need to tell CoreData to look inside your unit test bundle, with something along the lines of

1
2
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:
[NSArray arrayWithObject:[NSBundle bundleWithIdentifier:@"com.yourcompany.unittests"]]] retain];

For this to work you also need your data model to be present in your unit test bundle. For some reason, unlike your .m files the inspector doesn’t show you a list of targets the model should be included in - you need to drag the data model file into the compile source build phase of your unit test target.

Ruby Openssl and Client Side Certificates

I recently needed to deal with ssl connection using client side certificates. The ruby openssl bindings are fairly impenetrable, here’s what worked for me (at least in part as a note for myself in the future)

1
2
3
4
5
ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = OpenSSL::X509::Certificate.new("mycert.cer")
ctx.key = OpenSSL::PKey::RSA.new("mykey.pem")
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.connect

If the key you’ve got is a .p12 file (which is what the key chain utility on the mac exports) then you’ll need to convert it like so

openssl pkcs12 -in key.p12  -nocerts -nodes -out key.pem

Fun With Ruby Http Clients

Quite a few people have written about the performance failings of Net::HTTP, but until recently, to be honest, I never really cared a lot. Most of my http request needs have been fairly meagre, often not much more than hitting a url and checking the result code.

I’ve been playing with couchdb recently, and so my app does a fair amount of http requests. I’ve been using RelaxDB which uses net/http, so Net::HTTP’s performance has started to matter.

Net::HTTP is not the only game in town. I spent some time recently playing with rfuzz, eventmachine and taf2-curb and came to largely the same conclusion as Paul Dix.

Leaning on a mature library such as libcurl gives taf2-curb a huge advantage. While eventmachine was on par speed wise, neither of the 2 http clients it includes are a complete implementation of the HTTP protocol. For example HttpClient will tell the remote server that it speaks HTTP/1.1, yet it does not support chunked encoding (mandatory part of the spec). HttpClient2 does understand chunked encoding, but doesn’t let you set headers or a body to the request. Fine for just pinging a url, but not up to the task of working with couchdb. Something to do with couchdb’s chunk encoded also seemed to confuse rfuzz.

taf2-curb does the job very nicely. On my dumb benchmark, 1000 requests for a static html page hosted on the same machine (ie we’re pretty much only testing overhead) the numbers are:

1
2
3
4
5
6
7
8
9
10
11
12
13
Benchmark.bmbm(5) do |x|
  x.report 'net/http' do
    u = URI.parse('http://docs.local/')
    1000.times {Net::HTTP.get u}
  end

  x.report 'curb' do
    1000.times do
      c = Curl::Easy.new 'http://docs.local/'
      c.perform
    end
  end
end
               user     system      total        real
net/http   0.560000   0.270000   0.830000 (  1.065960)
curb       0.310000   0.170000   0.480000 (  0.696188)

On the other extreme, these numbers corresponds to ~1 meg of data pulled from couchdb (benchmark code the same apart from the urls, and I did 100 iterations rather than 1000).

               user     system      total        real
net/http  17.400000   8.900000   2.630000 (  32.067821)
curb       0.700000   1.300000   2.000000 (  29.586022)

curb comes up squarely on top. Another thing of note during this test is cpu usage (as you might expect from the difference in user time). With Net::HTTP the ruby process running this was taking up 60-70% (on a 2.4GHz core duo), with curb it used around 5% of cpu.

The commit to switch RelaxDB from net/http to taf2-curb is here for those interested - really very straightforward stuff. There may well be more to be had by fiddling with libcurl options, I haven’t tried yet.

A Teeny Tiny Plugin for Working With Others

If you work with designers or getting to grip with a new codebase you may find yourself frequently answering the question ‘What template generates this bit of html’. This smidgen of code adds comments to your html with the path to the templates used. For example the template

1
2
Hello
 <%= render :partial => 'some_partial' -%>

might generate

1
2
3
4
5
6
<!-- TEMPLATE: views/dummy/index.html.erb -->
Hello
<!-- TEMPLATE: views/dummy/_some_partial.erb -->
Here is a partial
<!-- ENDTEMPLATE: views/dummy/_some_partial.erb -->
<!-- ENDTEMPLATE: views/dummy/index.html.erb -->

You can grab the code from github. Original idea from this thread on rails-talk

Make Your Tests Run a Little Quicker for Free

It’s a good thing when tests run quickly. You get a shorter feedback cycle, you’re unlikely to move on to something else while your tests are running. Another good thing is ruby-debug: a fast debugger for ruby, worth its weight in gold when you need it. As of Rails 2.1 ruby-debug is always loaded and active during tests.

Having the debugger there does have some overhead. Not much, but it’s still there. You’re incurring that overhead whether your tests need it or not. On your CI server, it’s pure wasted time for example. Even running locally it’s frequently unecessary - most of the time when I run the tests I’m just running the tests, not using the debugger to try to understand a test failure.

So, without further ado I present this:

1
2
3
unless ENV['DEBUGGER']
  Debugger.stop if defined?(Debugger)
end

Stick it in your test_helper.rb, just below where it says

1
require 'test_help'

Run your tests again, and hey presto, faster! It does very from app to app, on some of the smaller apps I have the difference is pretty marginal, on the bigger apps I’ve got gains of up to 20-30%. I expect that on the smaller ones loading the Rails environment, setting up fixtures etc… dominates actual test runtime. And the day you do need to run the tests under the debugger it’s as easy as

1
rake DEBUGGER=true

if you’re using rake to run your tests or

1
DEBUGGER=true ruby -Itest test/unit/some_test.rb

if you’re running an individual test (this might change according to what shell you use). In fact most of the time you won’t even need to do this, as calling debugger calls Debugger.start for you.