Wednesday, December 11, 2013

Testing Rails apps when using DynamoDB


Once we decided to use Dynamoid to replace ActiveRecord in our Rails project, we needed to figure out how to test it.

First off, testing against Amazon's live DynamoDB is out of the question.  I'm not going to be limited to network speeds to run unit tests, nor be required to have an Internet connection in the first place.  Just a bad idea.

Mocking out every 'save' and 'create' request on each Event and Plan interaction would have severely undermined the usefulness of any model tests and even many controller tests.  When we mock a components behavior it's easy to make the wrong assumption about what it does.  The mock is unlikely to catch things like suddenly an integer field is being added instead of a string even if that change would cause the real storage engine to fail.

Fake_dynamo is what I found to use.  So far I'm really impressed by its accuracy in behaving the way Amazon DynamoDB does.  I haven't found it to either raise false negatives (fails when the live service succeeds) or false positives (succeeds when the live service fails).  Fake_dynamo can be used to run unit tests or just to run the Rails/DynamoDB system locally for development and ad-hoc testing.   I installed the gem on the system.  I did not include it in the Rails project because it's not called from anywhere in the project, it's run from the command-line to listen on a local port (default 4567).

At this point it would be helpful to point out a command-line option I found useful:

fake_dynamo -d fake_dynamo.fdb 

The -d option tells the gem which file to save to rather than the default.  Unit tests can therefore use a different file than ad-hoc tests.  This is nice because to do ad-hoc tests I might setup some long-lived data, whereas unit tests really only work well on a completely clean database rather than having dependencies between runs.

So to clear out the database between runs I issue a network command to the local port to delete the whole database.  I combine this in one line with running the tests:

curl -X DELETE localhost:4567 ; rake

I should probably clear out the old db as part of the internal automation of the test run itself but haven't bothered yet.

 The last challenge was really how to do fixtures or factory data.  I tested Rails fixtures, FactoryGirl and one other solution which I can't remember since this was over 2 months ago.  Dynamoid, unfortunately, did not work with any of them.  It turns out Dynamoid is missing too many ActiveRecord features to really work well with these systems yet.  So for example

Attendee.delete(attendee_id)
Attendee.find(attendee_id).delete


The first is supposed to work in ActiveRecord but doesn't work in Dynamoid; the second really does work in Dynamoid. Most of the time it's easy to replace the non-working syntax with one that works, but not when using helpers like fixtures/factory systems.

Summary: fake_dynamo good; Dynamoid shown to need more work.

Blog Archive

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.