One thing I'm trying out right now is (a) writing all of my business logic 
in module files; (b) breaking up that logic into small-ish classes that 
each seem to have with around 5-10 methods each; (c) injecting my 
dependencies as much as possible into the class in the __init__ method and 
then passing them from __init__ to the class methods. This seems to make it 
much easier to mock external dependencies. So, for example, rather than 
performing a db select in a method, I might do something like this:

class Myclass(object):

    def __init__(self, myrows=None, other_class_instance=None):
        if myrows is None:
            db = current.db
            myrows = db(db.mytable.id > 0).select()
        self.myrows = myrows

        if other_class_instance is None:
            other_class_instance = OtherClassInstance()
        self.other_class_instance = other_class_instance

    def my_method(self, target)

        person = self.myrows.find(lambda row: row.id ==  target)        
        bday = self.other_class_instance.get_birthday()

        if person.birthday = bday
            return 'Happy Birthday!'
        else:
            return 'No cake for you!'

In order to test this class all I have to provide is something that looks 
like a Rows object and something that looks like an instance of another 
class. If I pass those mocked objects at class instantiation, I override 
the default calls to db and the external class in __init__() and my class 
is effectively decoupled for testing. I can even run tests on this class 
(should I want to) without the web2py environment.

I should add that I've just been reading a lot about tdd and testing in 
general, so there's a good chance I'm passing on flawed advice here. :) But 
it's working for me so far. The dependency injection idea can be taken to 
extremes, with decorators and whole "frameworks" but for my purposes the 
simple approach taken here seems functional. The other advantage of this is 
that your classes and methods become much more abstract and so much easier 
to reuse in other projects. Or if (perish the thought) you someday wanted 
to refactor your app using Django or something you could use a class like 
this largely untouched, as long as you pass an alternative for db in to the 
class constructor.

Cheers,

Ian

On Wednesday, October 3, 2012 3:46:03 PM UTC-4, viniciusban wrote:
>
> Hi all. 
>
> I continue diving into unit-testing and I'd like to know how do you 
> organize your applications to be unit-tested. 
>
> Thin controllers? DAO classes? How do you decouple things in web2py to 
> make unit-testing easy? 
>
> -- 
> Vinicius Assef 
>

-- 



Reply via email to