Chapter 4: What is Test-Driven Development?

Richard Kenneth Eng
Learn How To Program
3 min readJun 4, 2017

--

Test-Driven Development (or TDD) is a software development process in which a very short development cycle is employed repeatedly. Software requirements are turned into specific test cases whereby any software you write must pass these tests. In this way, TDD encourages simple design and inspires confidence in the correctness and reliability of the software.

TDD is a great way to make Smalltalk programming every bit as safe and reliable as programming in statically typed languages like Java, C++, and Haskell. Robert C Martin argues this point very well in his article, “Type Wars.”

TDD works well with any other dynamically typed language such as Python and Ruby. Smalltalk takes credit for being the first language to practice and promote TDD. TDD has subsequently been adopted by Java, JavaScript, C#, C++, PHP, and so on.

To apply TDD in your programming activity, you follow these key steps:

  1. For each new feature, begin by adding a test that reflects the requirement. This test must be able to fail if it doesn’t meet the requirement.
  2. Run all tests in your program to ensure that your new test (and only your new test) fails because it doesn’t meet the requirement.
  3. Write the code that allows the test to pass.
  4. Re-run all tests in your program to ensure that everything still works, even with your new feature.
  5. Re-organize or “refactor” your program code so that it remains clean and sensible.
  6. Repeat steps #1 through #5 for each new feature or test, as you push forward the functionality of your program.

Let’s look at an example of how to create a test…

We will be using SUnit, a framework that supports the creation and deployment of tests. We will be testing the class #Set. The first step is to create the test class called #ExampleSetTest, which is a subclass of #TestCase.

TestCase subclass: #ExampleSetTest
instanceVariableNames: 'full empty'
classVariableNames: ''
poolDictionaries: ''
category: 'MySetTest'

This class defines the context within which the tests are run. The context is described by two instance variables, ‘full’ and ‘empty’, that represent a full and an empty set.

The second step is to initialize the test context:

ExampleSetTest»setUp
empty := Set new.
full := Set with: 5 with 6 "this creates set {5, 6}"

The third step is to write some test methods:

"test the includes: method of Set"
ExampleSetTest»testIncludes
self assert: (full includes: 5).
self assert: (full includes: 6)
"verify that the number of occurrences of 5 in the set is 1, even if we add another element 5 to the set"
ExampleSetTest»testOccurrences
self assert: (empty occurrencesOf: 0) = 0.
self assert: (full occurrencesOf: 5) = 1.
full add: 5.
self assert: (full occurrencesOf: 5) = 1
"test that the set no longer contains 5 after we've removed it"
ExampleSetTest»testRemove
full remove: 5.
self assert: (full includes: 6).
self deny: (full includes: 5)

Note: the names of test methods must start with ‘test’ so that SUnit can gather them together into test suites.

The fourth step is to run the tests. You do this by action-clicking (usually right-click on mouse) on the class and selecting “Run tests”. You can also use the Test Runner by clicking on World→Test Runner. With the Test Runner, you can execute groups of tests.

In the Test Runner, failing tests (assertion failures) are indicated in yellow, whereas tests that fail to execute normally are indicated in red (which means you’ll have to dig deeper to find out what’s wrong).

I encourage you to use Test-Driven Development for all of your programming. Hereafter, I shall assume that you are practicing TDD and that there’s no need for further mention.

--

--