[Tutor] Newbie & Unittest ...

Steven D'Aprano steve at pearwood.info
Fri May 7 04:05:31 CEST 2010


On Thu, 6 May 2010 10:37:20 am Damon Timm wrote:


> class TestFiles(unittest.TestCase):
>
>     # this is the basic test
>     def test_values(self):
>         '''see if values from my object match what they should
>         match''' 
>         for file in FILES:  
>             for k, v in TAG_VALUES:
>                 self.assertEqual(self.file.tags[k], v)
>
> This test works, however, it only runs as *one* test (which either
> fails or passes) 

That is correct, because you have written it as one test. In 
unit-testing, a single test can be arbitrarily complex. In your case, 
you've created a single test which makes 12 different comparisons, and 
fails if *any* of them fail.

Here is an analogy... suppose you are comparing the two strings for 
equality. Python does this:

* If the lengths are different, return False (the test fails);
* If the first characters differ, return False;
* If the second characters differ, return False;
* If the third characters differ, return False;
* ... and so on ...
* return True (the test passes)

The data that you feed are the strings "abcd" and "abce". Is that five 
tests, with the first four passing and the last failing? Well, yes, but 
not in any meaningful sense. Even if it is useful to see *where* the 
strings differ, it would be silly to treat each comparison as a 
separate test.


> and I want it to run as 12 different tests (three 
> for each file type) and be able to see which key is failing for which
> file type.  I know I could write them all out individually but that
> seems unnecessary.

Unfortunately, if you really want them to be twelve individual tests, 
then you need to write them out individually as twelve separate tests.

As for the second question, to see where the failure is, you can pass an 
extra argument to assertEqual:

self.assertEqual(self.file.tags[k], v, 
"fails for file %s with tag %s and value %s" % (file, k, v))

Alternatively, you can take a separate approach. Since you have four 
different file types, I would test each type separately, using 
inheritance to reduce the amount of work needed.

# Untested.
class TestMP3(unittest.TestCase):
    filename = 'data/lossy/04 - Christmas Waltz (MP3-79).mp3'
    filetype = MP3File
    def __init__(self):
        self.file = self.filetype(self.filename)
    def test_title(self):
        self.assertEquals(self.file.tags['title'], 'Christmas Waltz')
    def test_artist(self):
        self.assertEquals(self.file.tags['artist'], 'Damon Timm')
    def test_album(self):
        self.assertEquals(self.file.tags['album'], 'Homemade')


class TestFLAC(TestMP3):
    filename = 'data/lossless/01 - Christmas Waltz.flac'
    filetype = FLACFile

class TestOGG(TestMP3):
    filetype = OGGFile
    filename = 'data/lossy/01 - Christmas Waltz (OGG-77).ogg'

class TestMP4(TestMP3):
    filetype = MP4File
    filename = 'data/lossy/06 - Christmas Waltz (M4A-64).m4a'


And you're done, 12 separate tests with hardly any extra typing. And now 
you can easily add specific tests, e.g. testing that FLAC actually is 
lossless:


class TestFLAC(TestMP3):
    filename = 'data/lossless/01 - Christmas Waltz.flac'
    filetype = FLACFile
    def test_lossless(self):
        raw = open('raw sounds.wav', 'r').read()
        data = self.file.convert_to_wav()
        self.assertEquals(raw, data)




-- 
Steven D'Aprano


More information about the Tutor mailing list