views:

117

answers:

2

I'm new to unit tests for my own projects, so this is my first attempt to write a unit test from scratch. I'm using python, and the unittest module. The TodoList class being tested here is a wrapper for actual lists, with a few extra methods for stuff like saving to disc. It also defines a few methods for getting items by their ID in the list (which isn't the same as the list index).

Tests (I've cut out a few helper methods, and a good few tests for the sake of not having people to scroll forever):

class TodoListTests(unittest.TestCase):

    def setUp(self):
        self.testdata = open("./testdata.json", "r")
        self.testdata_text = self.testdata.read()
        self.testdata.close()

    def tearDown(self):
        try:
            os.remove("./todo.json")
        except OSError:
            # File not created, no need to delete.
            pass

    def create_todolist_and_safe_list(self):
        self.create_data_file()
        self.todolist = todolist.TodoList("./todo.json")
        self.list = json.loads(self.testdata_text)

    def create_data_file(self):
        datafile = open("./todo.json", "w")
        datafile.write(self.testdata_text)
        datafile.close()

    # Snip out a few more helper methods

    def test_loop(self):
        self.create_todolist_and_safe_list()
        test_list = []
        for item in self.todolist:
        test_list.append(item)

        self.assertEquals(test_list, self.list)


    def test_save(self):    
        self.create_todolist_and_safe_list()
        self.todolist.save()
        newfile_text = self.get_data_file_as_string()
        self.assertEquals(newfile_text, self.testdata_text)

    # Snip out the rest of the tests.

Full link to source

+2  A: 

I think that you are going in the right way. But I will send some suggestions;

  • Move the self.testdata.close() from setUp() to the tearDown() function.
  • Surround the others open/close with try/finally blocks. So, if a file didn't open with success it will be closed.

    try:
        file.open()
    finally:
        file.close()

  • Organize better your test folders. I suggest you to create a folder named _tests and inside this folder you should put the tests module (at your case you only have one module). Then, for each module create a folder with the name of the module and puts the files used by the tests of a module inside this folder.

To know more about TDD and tests you should read the book Test Driven Development: By Example

Pedro Ghilardi
+1  A: 

No, it doesn't quite look like you are. Unit tests should be small, fast, and uncomplicated. Doing 'complicated' tests (anything that relies on an external database, file system, configuration, environment, or really anything outside the test itself and the code being tested) is valuable, but shouldn't be a part of your "core unit tests". Unit tests should validate that the code follows the spec. One test should validate that with the correct input, you get the expected output. Another unit test should exist to validate proper behaviour on incorrect input. This often repeats for different kinds of correct or incorrect input, but there are usually a lot more tests for incorrect input than anything. Still, without a spec you don't really have much to unit test. The usual problem is a lack of technical specification (the spec) that tells you what a correct or incorrect input is and what to do in each case.

Besides the fact that you're hitting the file system though, your tests look good.

Task