[Baypiggies] Unittest magic -- how to get into that exception handler?

Tung Wai Yip tungwaiyip at yahoo.com
Tue Mar 29 01:52:25 CEST 2011


In my code there is a lot of result checking and exception handling code,  
e.g.


def myfunc():
     result = my_processing()
     if len(result) != 2:
         raise RuntimeException("Result not right, len=%s" % len(result))

     # verified result is a sequence of len 2 as documented
     ...


Normally, this exception handling code is never run because the error  
condition does not happen. But it is never a good idea to ship code that  
has never been run. Many times I get embarrassing problem like the error  
message's formating string does not match the parameter or just typo.  
Instead of helping, the checking code creates further complication. This  
is even more problematic for a dynamic language like Python with less  
compile time checking.

So I really want to get the code to run, using automatic unit testing or  
other means. The conventional way to handle this is to create mock object  
for things like `my_processing`. I'm not a big fan of mock object. First  
of all I have a lot of those situations and thus a lot of things to mock.  
I don't like the extra layer of indirection and I find mock object are  
often very hackish. Plus it creates a lot of maintenance issue. When I  
refactor the logic, I also have to take care of the mock object or they  
will be the first to break.

I have some idea that is to use annotation to inject code to push the  
execution into some path. That requires some language magic I wonder if it  
is feasible. For example, I'm thinking of introducing some marker like  
@unittest_magic.


def myfunc():
     result = my_processing()
     @unittest_magic(name="my_processing_result_validation")
     if len(result) != 2:
         raise RuntimeException("Result not right, len=%s" % len(result))

     # verified result is a sequence of len 2
     ...


Then elsewhere I can invoke it and specified it to take on any arbitrary  
variable value when the execution has reached the point by:

   run_test(myfunc, "my_processing_result_validation", result=["dummy"])


I think this is fairly lightweight and localized magic compares to mock  
object. What do you think? Is it feasible? Or do you have other strategy  
to handle those situation?


Wai Yip


More information about the Baypiggies mailing list