Thanks for all the active responses. I am grateful. Thank you very much. <br>Yes. It's very difficult for me, especially there is not enough support from education to show what is good or bad when it comes to testing code. So sad...<br>
<br>I am going to respond in this one email instead of separate email per response:<br><br>1. I think two things are gained from doing mocking:<br> (1) isolate dependices, make your system under test in vacuum state<br>
(2) when you patch out all the dependencies, you can run 100+ tests very quickly<br><br>When I don't patch out every dependence, tests are slow. They can take 4-5 seconds (wow big deal). But when you do patch all of them out, they can run in 1 second. I am probably amazed by such demonstration in some PyCon videos.<br>
<br><br>>> why kwargs is used?<br>There are two decorators applied to this function, but I left them out. The kwargs contains more than one key in the real code. But for demo purpose, I am showing only one.<br><br>>> break the code into small pieces<br>
My issue with breaking up this sample code
into two smaller pieces is that the the partitions are not always resuable.
It makes reading harder (you'd jump to another function to find out
what's going there). As straightforward as it is, I personally think
this function can stay as it is. If it's 3-lines, and all it does it read the path, open the file, return the content, do we still break into two parts? I think that's not really a good idea. I think you guys are merely showing me that sometimes we can break down a function into smaller parts. I try to do that as much as possible :)<br>
<br>2. I understand that patching everything out is bad,especially pure Python std functions such as `open`, or `os.path.join`. <br>So is this what we should do?<br><br>Suppose the sample code is:<br>def readfile(*args, **kwargs):<br>
local = kwargs.get('local', os.getcwd())<br>
filename = args[0]<br>
f_path = os.path.join(local, filename)<br>
with open(f_path, 'r') as f:<br>
return f.read()<br><br>Let's have three tests<br><br>@patch.object('os.path', 'join')<br>def test01_local_is_used(self, mk_join):<br> kwargs = {'local': 'LOCAL'}<br> mk_join.return_value = 'full path'<br>
readfile('filename', **kwargs)<br> assert mk_join.call_args_list == [call('LOCAL', 'filename')]<br><br>Another test will tests that `open` is called with f_path and `r` ?<br>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?<br>
<br>Thanks.<br><br><br><br>def test01_local_is_used:<br> read<br><br><br><div class="gmail_quote">On Wed, Jul 18, 2012 at 10:18 AM, Ned Batchelder <span dir="ltr"><<a href="mailto:ned@nedbatchelder.com" target="_blank">ned@nedbatchelder.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><div class="im">
On 7/18/2012 12:58 AM, John Wong wrote:<br>
<blockquote type="cite">Hi guys,<br>
<br>
Here is a simple function.<br>
<br>
def readfile(*args, **kwargs):<br>
local = kwargs.get('local', os.getcwd())<br>
filename = args[0]<br>
f_path = os.path.join(local, filename)<br>
with open(f_path, 'r') as f:<br>
return f.read()<br>
<br>
<br>
Now here is just ONE case of the readfile test code. For
readabilty, I will put in <a href="http://pastebin.com" target="_blank">pastebin.com</a><br>
<a href="http://pastebin.com/P45uc2TV" target="_blank">http://pastebin.com/P45uc2TV</a><br>
<br>
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).<br>
<br>
</blockquote></div>
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.<br>
<br>
If you are checking call_args_list, then .called or .call_count is
redundant, so remove those lines from the test.<br>
<br>
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?<span class="HOEnZb"><font color="#888888"><br>
<br>
--Ned.<br>
<br>
</font></span><blockquote type="cite"><div class="im">
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<br>
<br>
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...<br>
So if there are 10 functions, each 5 lines, I can end up with 1000
lines of test code....<br>
<br>
Last question, I find my patching is really really long and
inconvince. How should I patch (say they all come from os
package)?<br>
<br>
Thanks.<br>
John<br>
<br>
<fieldset></fieldset>
<br>
</div><div class="im"><pre>_______________________________________________
testing-in-python mailing list
<a href="mailto:testing-in-python@lists.idyll.org" target="_blank">testing-in-python@lists.idyll.org</a>
<a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">http://lists.idyll.org/listinfo/testing-in-python</a>
</pre>
</div></blockquote>
<br>
<br>
</div>
</blockquote></div><br>