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
>
--