Hi all.

I've been working on a project recently with a lot of moving parts
(eventmachine, rabbitmq, background worker processes, web server,
etc).

Predictably, testing it in a way that's aesthetically pleasing,
reliable, and fast has turned up a number of challenges.

For example, EM runs in a blocking event loop when you call EM.run;
AMQP will only run inside an EM.run loop. There are some (excellent)
options like moqueue and bunny for working around the latter, to an
extent, but integration tests running on the whole stack must either
run as a background thread or against a separate, already-running
server (both of which in turn require that rabbitmq-server and
postgres be running).

Add the need for repeatable test data to the mix, and you get the
choice of either using transactions (which are not visible between
threads, i.e. cause pain and/or death), or deleting data between tests. If a
backgrounded thread is still writing to a record you've deleted, bad
things tend to happen.

I could go on.

Anyway - after much suffering, I find myself arriving at some strange
conclusions recently, which I'm going to collectively dub something
snappy ending in 'DD', in the hope it makes me famous. If you have any
ideas for a name, chime in.

Here's the canon (WIP):

* The tests are more important than the application.

* The application should be refactored constantly to improve the
  quality of the tests.

* The tests should run as close to instantly as possible.

* The application's architecture should maximize the quality (speed,
  clarity, reliability) of the test suite.

* Tests should be structured like a pyramid: unit tests on the bottom,
  functional tests in the middle, integration tests on the top.

* If you can't unit test something without mocking the very laws of
  physics, scrap it.

* Use simpler data structures.

* If you must use classes rather than hashes, arrays or other
  primitives (things you can serialize to JSON):

** pay attention to their comparison / equality operators (==, ===,
   <=>, etc)

** make them able to import & export a more primitive version of
   themselves (eg. #to_json) for easier testing

* write custom matchers to make your unit tests beautiful. Use these
  in your cuke step definitions when it makes sense.

* make your code as ugly as you must to make the specs beautiful (but no
uglier).

* if you decide to use a library, you own it, and you'll end up seeing
  it naked. Try to make sure it's not suffering from either obesity or
  gangrene well before this happens. If you can avoid using it
  entirely without making your specs worse or adding code, do.

Now, much of this won't apply to most Rails projects. All of it is off the
top of my head and to be taken with unhealthy quantities of salt. I
just wanted to throw it out there and see what ideas / opinions other people
have.

so?

-- 
cheers,
David Lee

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
or Rails Oceania" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rails-oceania?hl=en.

Reply via email to