[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