[Tutor] Using unittest module for Test Driven Development
Alex Kleider
akleider at sonic.net
Mon Aug 25 05:20:26 CEST 2014
Thank you very much, Steven. This is just the help I needed.
Forgive me for causing confusion- I pared down my code for presentation
but not enough and also left the names which now out of context, don't
make sense. In line explanations provided below although it would
probably
be of little interest. You did ask so I feel I owe you an explanation.
Gratefully,
Alex
On 2014-08-24 18:57, Steven D'Aprano wrote:
> On Sun, Aug 24, 2014 at 05:23:35PM -0700, Alex Kleider wrote:
>> Given
>> $ cat compare.py
>> #!/usr/bin/env python3
>> import os
>> import sys
>>
>> def get_args():
>> try:
>> args = sys.argv[1:]
>> except IndexError:
>> return
>> return [arg for arg in args if os.path.isfile(arg)]
>
> The try...except block is redundant, because you are taking a slice,
> not
> an index, it cannot fail. If the bounds are outside of the actual list,
> the empty list is returned:
>
> py> [1, 2][100:1000]
> []
This I did not know. Good to know.
>
>
> By the way, is there significance to the name "compare.py"? Because
> it's
> not really doing any comparisons...
That's the ultimate goal of the script but I've a ways to go before that
is evident!
>
>
>> if __name__ == "__main__":
>> print(get_args())
>>
>> How can one unittest get_args()?
>> It seems to me that 'unittest'ing only works to test functions and
>> methods, not programs.
>
>
> Well, technically "unit testing" refers to testing individual "units"
> (that is, classes, functions, modules etc.) of a program, not the
> entire
> program all at once. But it's also flexible enough to test the entire
> program.
That's good to hear.
>
> To test get_args() alone, I would do something like this:
>
>
> import sys
> import unittest
> import compare
>
> class Test_Get_Args(unittest.TestCase):
> def setUp(self):
> # Create some known files.
> open('/tmp/aaa', 'w').close()
> open('/tmp/bbb', 'w').close()
> # Make sure another file doesn't exist.
> if os.path.exists('/tmp/ccc'):
> os.unlink('/tmp/ccc')
>
> def tearDown(self):
> # Clean up once we're done.
> for file in ('/tmp/aaa', '/tmp/bbb'):
> if os.path.exists(file):
> os.unlink(file)
>
> def test_existing_files(self):
> sys.argv = ['testing', '/tmp/aaa', '/tmp/bbb']
> result = compare.get_args()
> self.assertEqual(result, ['/tmp/aaa', '/tmp/bbb'])
>
> def test_nonexisting_files(self):
> sys.argv = ['testing', '/tmp/ccc']
> result = compare.get_args()
> self.assertEqual(result, [])
>
> def test_not_files(self):
> sys.argv = ['testing', '/tmp', '/']
> result = compare.get_args()
> self.assertEqual(result, [])
>
>
> The paths I used are suitable for Unix, Linux or Mac. You will need to
> adapt them for Windows.
M$ Windows is of little interest to me:-)
>
> To avoid having to write to sys.argv, give your get_args function an
> optional argument:
>
> def get_args(args=None):
> if args is None:
> args = sys.argv[1:]
> return [arg for arg in args if os.path.isfile(arg)]
>
> then in your tests, just pass the list directly to the function.
>
>
>
>> Here's my attempt at a testing module:
>> $ cat testing.py
>> #!/usr/bin/env python3
>> import unittest
>> import compare_sizes
>
> What's compare_sizes ?
>
OOPS! In editing for presentation to the list I forgot to change this
instance of compare_sizes to compare. The ultimate goal is to compare
file sizes and so I am trying to do TDD of compare_sizes.py which I
forgot
to rename to 'compare' in the import statement.
>
>> class CompareTesting(unittest.TestCase):
>>
>> def setUp(self):
>> pass
>
> If you're not doing anything in setUp, just don't override the method.
> The default method does nothing, so you don't need this.
I stuck it in as a place holder expecting to soon need it.
Should have removed it for presentation.
>
>
>> def test_nothing(self):
>> self.assertEqual(not False, True)
>
> What is the purpose of this test? How is it testing *your* code? That
> would be necessary as a test of Python's built-ins.
>
Since I'm learning I wanted to start with a test that I 'knew' shouldn't
fail.
I should have deleted it for presentation- sorry.
>
>> def test_get_file_param(self):
>> self.assertTrue(compare_sizes.get_args() == ['file1',
>> 'file2'])
>
> You should use assertEqual(a, b) rather than assertTrue(a == b).
>
Thanks for this tip. I remember reading about that.
>> if __name__ == '__main__':
>> unittest.main()
>>
>> Is there a way that I can provide the file name command line
>> parameters
>> to compare.py so that its get_args function can be tested?
>
> sys.argv is writeable, or better still, provide get_args() an optional
> argument to use instead of sys.argv.o
I don't understand what you mean by "sys.argv is writeable".
Thks again
ak
More information about the Tutor
mailing list