Test Driven Development

TDD in Python and PyCharm

PyCharm encourages TDD

PyCharm TDD

Example of a unit test:

    def test_parse_input(self):
        self.assertDictEqual(self.expected_parse, self.data_packer.parse_input())
        self.assertEqual(self.expected_parse["T"], self.data_packer.T)
        self.assertListEqual(self.expected_parse["challenges"], self.data_packer.challenges)

Google Code Jam's Data Packing problem

Input:

Number of challenges, followed by file and disc size info.

3
3 100
10 20 70
4 100
30 40 60 70
5 100
10 20 30 40 60

Output:

The number of discs needed to store the files.

Case #1: 2
Case #2: 2
Case #3: 3

First Try: Just write the code. Test at the end.

Solution 1

Summary

  • Time: 75 minutes (40 minutes spent debugging monster function)
  • Cyclomatic complexity: worst method had 9 and a B grade
  • Coding style: ugly. Will be hard to understand next week.

Second Try: Follow strict TDD

TDD Unit Tests for Solution 2

Solution 2 code

  • Time: 45 minutes (almost no time spent debugging)
  • Cyclomatic complexity: worst method had 6 and got straight A's for all methods
  • Coding style: very good. Compartmentalized design will make it easy to understand and refactor. Unit tests will catch any future issues that could arise from new requirements.

Some useful unittest constructs:

  • setUp(): Let's you keep access any data that you want to keep around for all (or most of) the tests.
  • tearDown(): The opposite of setUp()
  • fail(): Force a test to fail. Useful in TDD when you're still in the process of writing your tests.
  • various asserts:
    • assertEquals()
    • assertIsNone()
    • assertListEquals()
    • assertDictEquals()
    • assertRaises()
    • many more

Some more advanced techniques:

  • Mocking and patching
  • BDD