After I left the Bureau approximately a month ago I’ve taken up a new role with Infoxchange Australia. My first project here is working on a rewrite of an application using Django.
People here are really into behaviour driven testing, and we’re using Lettuce to do it (using a branch with better Django integration).
I sort of dislike this sort of testing, because it creates an annoying abstraction layer on top of the code, with a poorly defined, quasi-real language. It’s like a bad knock off of Applescript. Anyway, I got sick of defining steps per model, so I put together some generic steps for manipulating Django models (that I’ll have to contribute back).
Anyway they look like this (examples of the step in the docstrings):
# build a hash of model verbose names to models # this is used by get_model() def _models_generator(): for model in get_models(): yield (model._meta.verbose_name, model) yield (model._meta.verbose_name_plural, model) MODELS = dict(_models_generator()) def get_model(model): """ Convert a model's verbose name to the model class. This allows us to use the models verbose name in steps. """ name = model.lower() model = MODELS.get(model, None) assert model, "Could not locate model by name '%s'" % name return model def create_models(model, hashes): for hash_ in hashes: model.objects.create(**hash_) def models_exist(model, hashes): for hash_ in hashes: assert \ model.objects.filter(**hash_).exists(), \ "Object does not exist" @step(r'I have ([a-z][a-z0-9_ ]*) in the database:') def create_models_generic(step, model): """ And I have admin field values in the database: | name | value | | project_type | Twine | The generic method can be overridden for a specific model by defining a function create_badgers(step), which creates the Badger model. """ try: globals()['create_%s' % model](step) except KeyError: model = get_model(model) create_models(model, step.hashes) @step(r'(?:Given|And|Then) ([A-Z][a-z0-9_ ]*) with ([a-z]+) "([^"]*)" has ([A-Z][a-z0-9_ ]*) in the database:') # noqa def create_models_for_relation(step, rel_model_name, rel_key, rel_value, model): """ And project with name "Ball Project" has goals in the database: | description | | To have fun playing with balls of twine | """ lookup = {rel_key: rel_value} rel_model = get_model(rel_model_name).objects.get(**lookup) for hash_ in step.hashes: hash_['%s_id' % rel_model_name] = rel_model.id create_models_generic(step, model) @step('(?:Given|And|Then) ([A-Z][a-z0-9_ ]*) should be present in the database') def step_models_exist(step, model): """ And objectives should be present in the database: | description | | Make a mess | """ model = get_model(model) models_exist(model, step.hashes) @step(r'There should be (\d+) ([a-z][a-z0-9_ ]*) in the database') def model_count(step, count, model): """ Then there should be 0 goals in the database """ model = get_model(model) assert_equals(model.objects.count(), int(count))