Table of Contents
My Tale of Woe
When I graduated from university and had my first job as a software engineer at Harman Becker Automotive Systems GmbH I should do the parental leave cover for a colleague. He showed me his project, gave me some info e.g. contact person and went off to Canada.
Literally on the second day he was away, the phone started to ring. The OEM had a A++ blocker issue found in the software and everything pointed to the component I was now maintaining
Scavenger hunt
I tried to reproduce the issue manually but no chance: I couldn’t find the right stimuli on my test bench to make my software run into that issue.
TCE for the rescue
The framework team had a beta version of a tool called Test Case Editor. With that tool I was able to set up a test which produced the same log output as the error traces we got from the car and – voila! – my software component produced this issue. Thanks to debugging I could figure out the root cause (just a missing “else” clause) and fix it within minutes.
After that episode I knew: Automated tests are my friends!
Test Driven Development and Test First
Test driven development or TDD is a methodology or mindset for developing software. In its purest form there should be no change to your code base without adding, changing or deleting corresponding test cases simultaneously or -even better- before. So the test drives your development.
Wording: instead of succeeding or failing test we often say “the test is green” or “the test is red”
Test cycle
A cycle of writing software in a test driven way looks like this
- 0 – Check that all test cases which already exists run!
- 1 – Write a test and assert the expectation of what your software should be doing e.g. assert that a function returns a specific value. The test result should be red at first to ensure that you are really adding the functionality which the test asks for
- 2 – Write your implementation until the specific test case becomes green
- 3 – Make sure that all test cases which were already there are still green as well
- 4 – Refactor your implementation as long as all test cases stay green
Anatomy of a TestCase
For easy understanding I chose a unittest fixture from Python
from unittest import TestCase class WebAppTest(TestCase): def setUp(self) -> None: self.client = app.test_client() def test_index_page(self): rv = self.client.get('/index') self.assertEqual(rv.status_code, 200) def test_index_page_content(self): rv = self.client.get('/index') self.assertEqual(rv.data, b"Hello Index Page") def tearDown(self) -> None: pass
Heuristics for brownfield projects
- Every new feature gets a test case
- Every fix for a severe bug gets a test case