[TIP] 5 lines of code equals 30+ lines of single test

Ned Batchelder ned at nedbatchelder.com
Wed Jul 18 20:40:51 PDT 2012


On 7/18/2012 2:46 PM, John Wong wrote:
> Suppose the sample code is:
> def readfile(*args, **kwargs):
>     local = kwargs.get('local', os.getcwd())
>     filename = args[0]
>     f_path = os.path.join(local, filename)
>     with open(f_path, 'r') as f:
>         return f.read()
>
> Let's have three tests
>
> @patch.object('os.path', 'join')
> def test01_local_is_used(self, mk_join):
>     kwargs = {'local': 'LOCAL'}
>     mk_join.return_value = 'full path'
>     readfile('filename', **kwargs)
>     assert mk_join.call_args_list == [call('LOCAL', 'filename')]
>
> Another test will tests that `open` is called with f_path and `r` ?
> Only patch the function that your test is actually depending on? In 
> the first time, we want to know local is used, and the immediate use 
> of this `local` variable is os.path.join. So patching out os.path.join 
> seems reasonable?
>
No, in my opinion, you never need to patch os.path.join to test this 
function.  You don't care whether os.path.join was called.  You only 
care that it opened the right file.  So test that.

--Ned.

> Thanks.
>
>
>
> def test01_local_is_used:
>      read
>
>
> On Wed, Jul 18, 2012 at 10:18 AM, Ned Batchelder 
> <ned at nedbatchelder.com <mailto:ned at nedbatchelder.com>> wrote:
>
>     On 7/18/2012 12:58 AM, John Wong wrote:
>>     Hi guys,
>>
>>     Here is a simple function.
>>
>>     def readfile(*args, **kwargs):
>>         local = kwargs.get('local', os.getcwd())
>>         filename = args[0]
>>         f_path = os.path.join(local, filename)
>>         with open(f_path, 'r') as f:
>>             return f.read()
>>
>>
>>     Now here is just ONE case of the readfile test code. For
>>     readabilty, I will put in pastebin.com <http://pastebin.com>
>>     http://pastebin.com/P45uc2TV
>>
>>     I am verifying how many times X Y C dependencies are called and
>>     what parameters are passed to them. I think these are necessary
>>     to check (what if one of the dependency functions called with the
>>     wrong variable).
>>
>     You definitely don't have to mock os.path.join.   You don't care
>     that it called that function, you care that it opened the right
>     path, and you already have a check for that. You're over-testing
>     the implementation of the function. Focus on the
>     externally-observable behavior.
>
>     If you are checking call_args_list, then .called or .call_count is
>     redundant, so remove those lines from the test.
>
>     BTW: the function itself is a bit odd.  Why use **kwargs if you
>     only use one keyword, and *args if you only use the first element?
>
>     --Ned.
>
>>     But is this really the nature of unittest? I've read many tests
>>     code and they all seen to be 5-20 lines..... I faint when I am
>>     reading my test code.............. SIGH
>>
>>     I have some 10 lines function and it took 50 lines to test! Let
>>     alone for each of these functions, I need to write a a few tests
>>     for each branch case...
>>     So if there are 10 functions, each 5 lines, I can end up with
>>     1000 lines of test code....
>>
>>     Last question, I find my patching is really really long and
>>     inconvince. How should I patch (say they all come from os package)?
>>
>>     Thanks.
>>     John
>>
>>
>>     _______________________________________________
>>     testing-in-python mailing list
>>     testing-in-python at lists.idyll.org  <mailto:testing-in-python at lists.idyll.org>
>>     http://lists.idyll.org/listinfo/testing-in-python
>
>
>


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20120718/2a738116/attachment.htm>


More information about the testing-in-python mailing list