[TIP] structure of a testing talk

Andrea Crotti andrea.crotti.0 at gmail.com
Wed Oct 3 11:50:01 PDT 2012


10/03/2012 05:59 PM, Mark Sienkiewicz wrote:
>
>
> The buzzword is "Design for Test", and it is a big deal in hardware.  
> I suggest you give it a top-level bullet point in your presentation.  
> Instead of mentioning it at the end, mention it at the beginning and 
> use it in your examples.  You want to be talking about something else 
> and then then say "by the way, see how this thing I am testing was 
> designed to be easy to test?".
>
> If you can, include at least one example where the software would be 
> hard to test, except that it has a specific test featurein it. (Yes, 
> it's hard to make a simple theb.t.w.  In your outline, the one thing 
> that stands out for me is "Side effects, and why they are bad".  I 
> think you might lose a lot of C programmers by saying it that way, 
> because a lot of C code exists _specifically_ _for_ the side effects.  
> write() is only useful because of the side-effect, for example, and we 
> have exactly the same function in python.  Saying "side effects are 
> bad" may turn off your audience and make them less able/willing to 
> listen to the rest of what you have to say.
>
> In your presentation, funcs.silly_function() appears to generate 
> blocks of serial numbers (though you are only asking for blocks 
> containing 1 serial number in your example).  Can you explain to a C 
> programmer what exactly is bad about a function that returns a unique 
> serial number every time you call it?  I wouldn't bother talking about 
> a singleton serial number object, because a C programmer will 
> immediately recognize that as the same thing.
>
> Instead, I think you want to talk about appropriateness of side 
> effects.  It can be easy to pack weird side-effects into all your 
> functions; then you have a system that is hard to understand. 
> Narrowly, carefully, and clearly defined side effects are good; 
> random, arbitrary, or confusing side effects are bad.
>
> You can integrate this idea into the design-for-test model.  When you 
> have side effects, you have to have a way to determine if they 
> happened.  This means both an interface to peek into <whatever> to see 
> if the side effect happened, and a clear definition of what was 
> _supposed_ to happen.  You can be motivated to write more purely 
> functional code because it will be so much easier to understand and to 
> test.
>
> Mark S.


Thanks a lot for the feedback, I will write more about this tomorrow..
But in general I think side effects are bad also in C, of course it's 
harder but in my projects
I tried to be as functional as possible, and my code was much easier to 
test and debug later.

So sure in C it makes less sense, but for me side effects are always 
bad, and they can actually
be avoided or encapsulated in a lot of cases..

By the way I created a target in the makefile and now every time I 
rebuild the slides
they get synced with this public file, so actual slides are visible here:

https://dl.dropbox.com/u/3183120/talks/unit_slides/unit.html

for the side effect function I did a simple read from disk:

def read_from_disk():
     """Read a file from disk and return a list with its content
     """
     assert path.isfile(FNAME), "File %s does not exist" % FNAME
     res = []
     for line in open(FNAME):
         res.append(line.strip())

     return res


And show how I can test it increasing the smartness


def test_read_from_disk():
     old_fname = with_side_one.FNAME
     with_side_one.FNAME = TMP

     open(TMP, 'w').write(TEXT)
     assert with_side_one.read_from_disk() == DESIRED

     remove(TMP)
     with_side_one.FNAME = old_fname

# using unittest

class TestReadFromDisk(unittest.TestCase):
     def setUp(self):
         self.old_fname = with_side_one.FNAME
         with_side_one.FNAME = TMP
         open(TMP, 'w').write(TEXT)

     def tearDown(self):
         with_side_one.FNAME = self.old_fname
         remove(TMP)

     def test_read_from_disk(self):
         res = with_side_one.read_from_disk()
         self.assertEqual(res, DESIRED)


# using unittest and mock
@patch('with_side_one.FNAME', new=TMP)
class TestReadFromDiskMocked(unittest.TestCase):
     def setUp(self):
         open(TMP, 'w').write(TEXT)

     def tearDown(self):
         remove(TMP)

     def test_read_from_disk(self):
         res = with_side_one.read_from_disk()
         self.assertEqual(res, DESIRED)





More information about the testing-in-python mailing list