Question

I am trying to get into unit testing with python (though my question is not specific to python). I want to add a test for function I already have - I know I should do it the other way round, but here I am, in need for unit tests for existing code.

Here is my function:

def my_function(value):
    """
    value: tuple or string
    """
    is_tuple = False
    my_value = value
    if isinstance(value, tuple):
        my_value = value[0]
        is_tuple = True
    return(is_tuple, my_value)

Here is my test

import unittest
class TestMyFunction(unittest.TestCase):
    def test_my_function(self):
        sv_tupel = my_function(('foo','bar'))
        sv_tupel_res = (True, 'foo')
        sv_single = my_function('foo bar')
        sv_single_res = (False, 'foo bar')
        self.assertEqual(sv_tupel, sv_tupel_res)
        self.assertEqual(sv_single, sv_single_res)

Now I have tested two cases of input, but there are of course a lot more. I could maybe also test if the function fails if the input is not what it is expected to be.

So my question is, what is the general practice/good practice to get a thorough test coverage. In this example the input and output is rather simple and so is the result, but a tested unit could be more complex. So I wonder how to write a test that gets all the possible corner cases and input variants without manually listing them explicitly. Or is that just the way it has to be? Do people in general just pick a few corner cases, and add more if it turns out the test was not thorough enough?

Also, for the two cases that I tested, should I write two tests, or is it just one since it tests one function?

EDIT I found a partial answer to my question, which helps to build tests that are broader in scope. E.g. you might not need to find all corner cases, but the suite will do it for you: https://hypothesis.readthedocs.org/en/latest/quickstart.html (Thanks to Raymond Hettinger for tweeting this)

Was it helpful?

Solution

There's no magic formula for thoroughly testing your code. I imagine even for a trivial function, like stringReverse() you can come up with a plethora of edge cases, lots of time thinking/writing tests:

  • What if the string is null?
  • What if the string is empty?
  • What if the string is huge and takes up a large portion of available memory?
  • What if the string's length is larger than Max Integer? This causes problems on some systems.
  • What if the string has non-ASCII characters, or indeed the null character in the middle?
  • Does it preserve case? etc.

The difficulty of completely testing every possible part of your application increases substantially when you consider integration tests.

It's a bit of an art to find the balance between paranoia and apathy here. If you want to test the living hell out of your code, that's really good and laudable. However, even if I told you some sure-fire formula for the "right" degree of code coverage, I'm willing to bet that lack of time or difficulty of testing would cause you to deviate a bit (everyone does).

All that being said, there are guidelines that one could follow. A lot has been written proselytizing how your code should be tested. A good start might be this link: Introduction to Test Driven Development (TDD)

Licensed under: CC-BY-SA with attribution
scroll top