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

Tung Wai Yip tungwaiyip at yahoo.com
Tue Mar 29 18:27:52 CEST 2011


Thank you. I'll look into both framework. Monkey patching is a good  
thinking. I have a specific pain point that is I want to execute the error  
handler at least once. Since there are many error checking everywhere, I  
want a solution that is handy. I'm hesitant to build a full mock object  
because in practice, the flow is lot more complex. And I have to build a  
parallel mock object with precise choreography in order to drive the  
execution to some point.

Wai Yip


> Hey Wai Yip!
> I think a Mock is exactly what you want. In fact I think your marker
> proposal is basically a specialized form of monkey patching in mocks
> that return specified values. The mocking library I reference below
> does a good job of this.
>
> In the example you've given it's sort of a pain in the butt to use a
> mock because you have to monkey patch my_processing in order to mock
> it out. If your function took the processing function as an argument
> you could very easily:
>
> def super_bogus_processing():
>     return None
> def bad_len_processing():
>     return ['list of length 1']
>
> def myfunc(processor_func=my_processing):
>     result = processor_func()
>     ...
>
> self.assertRaises(RuntimeException, myfunc, super_bogus_processing)
> self.assertRaises(RuntimeException, myfunc, bad_len_processing)
>
>
> super_bogus_processing exploits an unhandled exception in your sample.
> len of None raises TypeError.
>
> I think in this particular example, with code that's designed for it,
> mocking is really the way to go.
>
> A shameless plug for a mocking framework named ditto:
> http://code.google.com/p/ditto/. This one does a good job of Mocking
> existing classes and modeling their interface at runtime rather than
> creating some arbitrary interface that never fails when an unknown
> method or attribute is accessed.
>
> -Bob
>
>
>
> On Mon, Mar 28, 2011 at 4:52 PM, Tung Wai Yip <tungwaiyip at yahoo.com>  
> wrote:
>> 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
>> _______________________________________________
>> Baypiggies mailing list
>> Baypiggies at python.org
>> To change your subscription options or unsubscribe:
>> http://mail.python.org/mailman/listinfo/baypiggies


More information about the Baypiggies mailing list