proposal: new default model test class

1 view
Skip to first unread message

Jorge Vargas

unread,
Oct 20, 2008, 4:03:12 PM10/20/08
to turbogea...@googlegroups.com
Hi,

I have been writing a lot of unittests lately. And I have stumble upon
the problem of writing a basic model test class. Chris Perkins told me
he had the same situation and provide me some code for a "ModelTest"
class. And I have been using that for a while. I consult with him and
he agreed we could release it and hopefully make it the standard for
TG2 model tests, as long as I sat down and write the docs for it :)
The code is simple yet powerful. The whole class consist of 5 methods
and it's build to be sub-classed of course. The only thing I'll like
to add is a custom error exception because If you run it as
"nosetests" it will just error out on the ModelTest class, given no
clue as to which test is failing. Although if you run it as "nosetests
-v" it will indeed show the test class that is failing which will clue
you in. So let the code speak by itself. Here is the current default
model test converted over to ModelTest.

class ModelTest():
klass = None
attrs = {}

def setup(self):
try:
new_attrs = {}
new_attrs.update(self.attrs)
new_attrs.update(self.do_get_dependencies())
self.obj = self.klass(**new_attrs)
DBSession.save(self.obj)
DBSession.flush()
return self.obj
except:
DBSession.rollback()
raise

def do_get_dependencies(self):
return {}

def test_create_obj(self):
pass

def test_query_obj(self):
print self.klass
obj = DBSession.query(self.klass).one()
for key, value in self.attrs.iteritems():
eq_(getattr(obj, key), value)

def teardown(self):
DBSession.rollback()

class TestUser(ModelTest):
"""Test case for the User model."""
klass = User
attrs = dict(user_name = u"ignucius", email_address =
u"ignu...@example.org")
def test_obj_creation_username(self):
"""The obj constructor must set the user name right"""
eq_(self.obj.user_name, u"ignucius")

def test_obj_creation_email(self):
"""The obj constructor must set the email right"""
eq_(self.obj.email_address, u"ignu...@example.org")

def test_no_permissions_by_default(self):
"""User objects should have no permission by default."""
eq_(len(self.obj.permissions), 0)

def test_getting_by_email(self):
"""Users should be fetcheable by their email addresses"""
him = User.by_email_address(u"ignu...@example.org")
eq_(him, self.obj)

As you can see you get a default instances created for each class and
it will warn when a model object has changed and it's test hasn't by
setup failing, it will also check that everything SA is working by
test_query_obj it allows for complex object maps to be tested with
do_get_dependencies, and it provides a std. way to check for proper
parameters and such with test_create_obj.

So basically with this base test class the average model test implies two steps:
1- set the klass and attrs atributes to sane defaults.
2- write test method's for your models methods and properties.

We also discuss the (rare) possibility where you need more than one
instance to test the class and this could be done by subclassing
ModelTest and will be documented properly.

so what do you all think? will this be a good addition?

Lukasz Szybalski

unread,
Dec 9, 2008, 8:04:00 PM12/9/08
to turbogea...@googlegroups.com

It sounds like a good addition. I wonder if you could write an example
on how to test the "wiki code" we have in a tutorials.

Lucas

Mark Ramm

unread,
Dec 9, 2008, 8:22:08 PM12/9/08
to turbogea...@googlegroups.com
I'd love to see this as a standard recipe in TG2, and would even
support moving it into the TG2 quickstart template.

--Mark Ramm
--
Mark Ramm-Christensen
email: mark at compoundthinking dot com
blog: www.compoundthinking.com/blog
Reply all
Reply to author
Forward
0 new messages