Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #2200 (closed defect: fixed)

Opened 10 years ago

Last modified 10 years ago

[Patch] The base test case for the models is not useful enough (ModelTest proposed)

Reported by: jorge.vargas Owned by: jorge.vargas
Priority: normal Milestone: 2.0b6
Component: TurboGears Version: trunk
Severity: normal Keywords:
Cc:

Description (last modified by jorge.vargas) (diff)

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"ignuc...@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"ignuc...@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"ignuc...@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?

Original discussion here  http://groups.google.com/group/turbogears-trunk/browse_thread/thread/4585fbcfc5b32fd8/5a59d99991562d96?lnk=gst&q=ModelTest#5a59d99991562d96

Attachments

testmodel.patch Download (4.9 KB) - added by jorge.vargas 10 years ago.
some failing tests due to group missing

Change History

comment:1 Changed 10 years ago by jorge.vargas

  • Owner changed from faide to jorge.vargas

Changed 10 years ago by jorge.vargas

some failing tests due to group missing

comment:2 Changed 10 years ago by jorge.vargas

please note that testmodel.patch is also getting rid of a lot of cruft left by the original pylons testing module. The new version is a lot cleaner.

comment:3 Changed 10 years ago by jorge.vargas

commited in r6320, feedback is welcome.

comment:4 Changed 10 years ago by mramm

  • Status changed from new to closed
  • Resolution set to fixed

comment:5 Changed 10 years ago by Gustavo

  • Summary changed from new default unittest class ModelTest to [Patch] The base test case for the models is not useful enough (ModelTest proposed)

Jorge, please next time write at least a brief description of the issue, not just put a link and a vague title. This is really helpful when you're searching for a non-recent issue -- I was searching for this one and it took more than it should to find it. Thanks in advance! :)

comment:6 follow-up: ↓ 7 Changed 10 years ago by jorge.vargas

  • Description modified (diff)

Sorry about that Gustavo, I ran this rather fast to see if I was able to get the feature into tg2 final :D, most of my tickets are well written.

comment:7 in reply to: ↑ 6 Changed 10 years ago by Gustavo

Thanks, Jorge!

Replying to jorge.vargas:

most of my tickets are well written.

I know, that's for sure. I just wanted to make sure that the person who deals the most with tickets is not getting bored of this task ;-)

Note: See TracTickets for help on using tickets.