NSStringinfying enums

Making sense of enum values in C is too difficult. Usually sooner rather than later while debugging you need to see what's inside an enum value, but C provides no introspection tools. You just get an integer value, no mapping to the original symbolic name. That's why every enum should be accompanied by a stringifying function, but that requires manual labor. Few programmers are happy to write those functions and fewer are going to update them. Automation to the rescue.

I'm working in the context of Objective-C, and so is Wolf Rentzsch, who recently blogged his script for generating NSStringFromEnumName functions. I have used a very similar solution for a long time, and I expect so have many others.

But you don't have to be jwz to doubt the wisdom of parsing C with a bunch of ad hoc regexps. I was always unhappy with it and knew there were various not-so-corner cases I wasn't handling properly. Using a real C parser seemed like the right thing to do, but it hasn't really been feasible until pretty recently, after the advent of libclang.

So, here it is, using Python and clang, my most recent take on NSStringFromEnum. It might not be any better for being based on libclang, but it's different.

ZeroMQ, iOS and Python

I wrote some example code for you.

Background: last week a coworker asked me what's the flavor du jour in two-way communication between a network server and an iOS app, should he just go with BSD sockets or is there something better? I suggested he should take a look at ZeroMQ. Not that I actually knew very much at all about it, but I had heard the name and seen that some people were pretty enthustiastic about it.

Turns out he had deadlines and wasn't too keen on building the library with an outdated zsh script that didn't seem to work.

I started fiddling with it myself on the weekend to have some idea about what I'm talking about. True enough that the script provided on the web page wasn't up to date, and once I fixed it I got only an ARM binary which isn't very useful in development when you want to test on the iPhone Simulator. After some more poking I finally managed to massage a working fat library out of it. And objc-zmq provided a nice simple Objective-C wrapper around the C API.

Not satisfied with playing with just one unknown technology, I thought I'd do the server in Clojure. After shaving the JNI yak for a couple of hours, trying to build a working version if the Java binding, I decided it wasn't worth it. Python was an easy fallback, but to keep things at least moderately exciting I used gevent which was also something I hadn't tried before.

It worked out pretty nice. The Python server is extremely simple and the iOS app isn't complex either. This hardly counts as a strenuous test of ZeroMQ, but at least from the code perspective it was really pleasant to work with. No hassle with buffers, just complete messages from an extremely simple API that enables the most common communication patterns with a couple of keywords. They wisely keep out of the marshalling business, telling people to use Protocol Buffers or something else for defining message formats.

The example project is available on Bitbucket. It works on my computer at the moment; see the Bitbucket page for details about the bits it requires.

Enjoy.

Unit testing Cocoa code with MacRuby

Announcing RCRunner, a GUI test runner for MacRuby and Cocoa.

Cocoa unit testing can be a pain. In addition to the usual difficulties of writing tests for user interface heavy code, the Apple sanctioned solution, SenTestingKit, can isn't the greatest testing framework around and the default way of using it rules out debugger.

GHUnit helps somewhat. It's a GUI test runner with additional testing methods. However, with it you are still writing your tests in Objective-C. On the plus side it's the same language you're probably writing your app in. On the minus side Objective-C can be verbose and sometimes, especially when writing test code, brevity would be welcome.

Enter MacRuby. You get the conciseness of Ruby with full access to your Objective-C classes. And Ruby probably has the greatest density of testing frameworks per active programmer among all the languages in popular use today.

There's a nice article about TDD, Objective-C and MacRuby on the MacRuby site. However, the approach taken in it still uses a Xcode build phase script to accomplish testing. That makes debugging hard and you have to hunt through the build logs for your errors.

RCRunner is a separate GUI program you run. You tell it names of Ruby modules and it uses any test cases it finds[1]. You can breakpoint your code and thanks to Ruby, reload the test code. You can inspect errors and log output test by test.

Enjoy.

[1] At the moment it supports only MiniTest but adding support for other frameworks isn't difficult.

© Juri Pakaste 2024