TDD Python & Python Test – Part 01

Let’s walk through TDD Python. Doing a Python test is very easy. I have written unit tests in Python, Java and C++, utilizing Google Test, Google Mock, JUnit, TestNG, Mockito and Powermock (Powermock+mockito). Python 3 is the easiest to test of them all. Python 3 being batteries included, comes with both a unit testing framework and a mocking framework. Let’s do some Test-Driven Development with Python 3.

TDD Python & Python Test – Oh! I failed my test

Test-driven development is a powerful missile launcher in every developer’s weapons arsenal. Also, the advantages it brings are simply awesome.

Test-driven Development (TDD) Advantages

Let’s take a look at why you need to have some TDD Python under your belt.

  • Firstly, It allows you to design the system with a more dependency injection oriented approach.
  • Secondly, The code you write is more testable. Simple functions and simple classes makes it easier to test, understand and refactor code base.
  • Most importantly, 100% code coverage. (For new projects or new classes/modules)
  • If you are using an Agile practice such as Scrum you can add 100% coverage for new code to the DoD (Definition of Done).
  • If you are writing an API, framework or a library: Your tests will act as samples for users.
  • Finally, test driven development with Python can be used as a starting point to begin Lean Software Development.

We are going to get started with a simple project.

Python 3 Testing Project – Propers

Gimme the Introduction

  • Project name: propers
  • Parse Java properties like config files.
  • We are not going to implement the full specification. Instead we will only develop a subset of features. With some added features.
  • Source code:

What are the Requirements of v0.1.0?

  • Firstly, all properties are in a single line. Format: key=value.
  • Secondly, Comments starts with a #
  • Additionally, Lines with properties cannot have comments. If such comment exists, then it will be used as part of the key or value.
  • A key must be present to make a valid property. (If other parts are missing an empty string will be assigned)
  • Both key and value is stripped of spaces.
  • Previously defined properties can be used in properties with $key or ${key} notation. $$ will be converted to $ when string interpolation is completed.

Awesome, Can we get started?

Let’s do a little bit of analysis of the requirements.

Python 3 Testing Requirement Analysis
Python 3 Testing Requirement Analysis

I have separated nouns, verbs and special notations from the requirements. Can you guess which are nouns and which of them are verbs ? (You are right, yellow color ones are nouns, green color ones are verbs and cyan color ones are special notations)

Nouns and verbs? I came here for Python 3 testing?

Calm down. First of all, we need to have some idea about what our little library will contain. We will be using the nouns for classes and fields and verbs for functions.

Python Test – TDD Style

Ah, I’ve create a failing test

# -*- coding: utf-8 -*-
import unittest

class PropertiesTestCase(unittest.TestCase):
    def test_property_creation(self):
        prop = Property("a=b")
        self.assertTrue(prop is not None)

There is a standard and battle tested way to write TDD test cases. That is the Red-Green-Refactor cycle.

Python Testing TDD Red-Green-Refactor
Python Testing TDD Red-Green-Refactor

What the hello-world is Red-Green-Refactor Cycle?

A project created with TDD will always be in a state that it’s code coverage is 100% (or more if you have a failing test).

  1. Red – First of all, we are going to write a small failing test.
  2. Green – Secondly, we make the minimum change to make the test pass.
  3. Refactor – Thirdly, Refactor the code base and test code base before writing another test. (Tests must still pass after refactoring. You can also commit the project after refactoring process.)

Alas! we are going on this cycle throughout this tutorial. You are in for a fun ride.

# -*- coding: utf-8 -*-

class Property(object):
    def __init__(self, line):

We have fixed the test case with simplest possible change. (Yes, you need to add the import statement to test as well.)

In this situation, the code is too small to be refactored, so we are going to continue.

def test_key_split(self):
    prop = Property("a=b")
    self.assertEqual(prop.key, "a")

We wrote the above failing test, now we are going to make it pass.

class Property(object):
    def __init__(self, line):
        self.line = line
        self.key = "a"

As you can see we did a simple change to make the test pass. We hard coded “a” here to make the test pass. (I know this looks dumb)

def test_key_split_2(self):
    prop = Property("x = y")
    self.assertEqual(prop.key, "x")

I’ve added a new test case. Now we need to make it pass.

class Property(object):
    def __init__(self, line):
        self.line = line
        self.key = line.split("=")[0].strip()

Since we cannot keep the hard-coded key, I decided to perform a simple string split. Now, I saw something we can refactor in the test suite. We have two simple functions to test key splitting. We can refactor it to one function.

def test_key_split(self):
    tests = (
        ("a=b", "a"),
        ("x = y", "x")
    for line, expected in tests:
        prop = Property(line)
            prop.key, expected,
                .format(repr(line), repr(expected)))

This way we can add more examples and edge cases easily to the test case.

That Is It for Part 01

In the next tutorial, we will be learning more about test driven development with Python.

Next Tutorial :: Python Test & TDD – Part 02 – TDD Python Some More

Looking for more Python Tutorials? We have Python tutorials for beginners. We also have more interesting programming tutorials that you might like! Also check out our Tips and Tricks section for programming tips that will help you get stuff done! And while you’re here don’t forget to get the scoop on the latest tech news we’ve got just for you.

Like what you see? Subscribe to our email list and hit us with a like on our Facebook page to get the latest news updates and tutorials straight to your newsfeed!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.