Activity: Get started with TDD
(no submission)
Purpose:
- Introduce TDD process
- Practice TDD and test automation skills to develop a simple software
- Use test harnesses to guide the development process
Require: Java 8 (or higher), JUnit (you are recommended to use the latest version, JUnit 5).
Additional resources:
You may find class discussions on RIPR model,
test automation, and characteristics of good tests
helpful when designing and automating your tests.
Instruction:
You may work on this activity alone or with as many partners as you want
For this activity,
we will stop periodically
and do group work one step at a time with discussion between steps.
You are encouraged to work through the TDD process in your favorite IDE.
If you run into anything you are not sure about, post to Piazza,
or ask in class.
There are two goals here.
First, learning TDD is best accomplished by doing TDD.
Second, applying TDD to develop any software applications follows the same process,
except additional factors need to be taken into account when developing
large-scale or complex software.
Imagine we are playing a "Duh-Huh" game.
I will ask for
volunteers
(or randomly select
names from the roster).
Each volunteer will take turns saying the next number in sequence (starting from one),
"Duh,"
"Huh," or
"DuhHuh."
If the number is divisible by three, you will say "Duh."
If it is divisible by four, you will say "Huh."
If the number is divisible by three and four,
you will say "DuhHuh."
(This activity would be more fun if you put
your creativity + heart and soul into saying it!!)
Let's try!!
To make the "Duh-Huh" game simple,
let's write a program to pre-print what to say so that the players can simply read the pre-print strings.
Now, follow the TDD process, develop a program to pre-print what to say
(assume the number from 1 to 100).
Sample output:
1 2 Duh Huh 5 Duh 7 Huh Duh 10 11 DuhHuh 13 14 Duh Huh 17 Duh ... (up to 100)
Sample user story:
Imagine we are implementing a program to pre-print strings to help players
play a "Duh-Huh" game.
To play a "Duh-Huh" game, players will take turns saying the next number
in sequence (starting from one), "Duh," "Huh," or "DuhHuh."
If the number is divisible by three, the player will say "Duh."
If the number is divisible by four, the player will say "Huh."
If the number is divisible by three and four, the player will say "DuhHuh."
That is, to pre-print what to say from 1 to 100,
the program prints
"1, 2, Duh, Huh, 5, Duh, ..., 95, DuhHuh, 97, 98, Duh, Huh"
Alternative user stories:
User story #1:
A player will say the number in sequence (starting from one).
User story #2:
A player will say "Duh" if the number is divisible by three.
User story #3:
A player will say "Huh" if the number is divisible by four.
User story #4:
A player will say "DuhHuh" if the number is divisible by three and four.
User story #5:
The program prints "1, 2, Duh, Huh, 5, Duh, ..., 95, DuhHuh, 97, 98, Duh, Huh"
to say 1 to 100.
User story #6 (optional):
Players will take turns saying the next number
in sequence (starting from one), "Duh," "Huh," or "DuhHuh."
— [design decision] You need to decide whether this requirement must be implemented.
Step 1: Transform the user story into requirements,
and then requirements into tests.
In this step, you will transform the user story into requirements.
That is, you will decompose the user story into a list of
"requirements as tests" — things to verify
(not "requirements as tasks" — things to do)
Example requirement as test: (what should be done)
The string "Duh" is printed when the current number to say is divisible by three.
Example requirement as task: (what we should do)
Implement a program that prints the string "Duh" when the current number to say is divisible by three.
- List the requirements — focus on requirements as tests,
not requirements as tasks
- Choose the first requirement to work on
(you will work on all of your requirements; however, you will do one at a time).
- Transform the requirement into at least one test description.
- Test description is a concrete, executable, and example-like version of the requirement.
Example test description:
Evaluating a program to pre-print a string up to number 3 results in "1 2 Duh"
(That is, test input = 3, expected output = "1 2 Duh")
Key idea:
- Program by intention
- Restrict focus, don't worry about the whole system
- Keep the two properties of a good test: atomic and isolated
Step 2: Write a test (code)
- Choose a test from the previous step to automate
(you will automate all of your tests; however, you will work on one test at a time).
- Write a JUnit test.
Key idea:
- Choose the test that potentially leads to the most progress with the least effort
Step 3: Run the test
- Run your JUnit test.
- Observe what happens. Can it run? Does it pass?
Step 4: Write (Java) code to make the test pass
- Write "just enough" code to make the test run
- Write "just enough" code to pass the test
Key idea:
- Pass the test as quickly as possible with the least effort
Step 5: Repeat steps 3 and 4 until the test passes
Step 6: Refactor
- Consider the program being developed. Can the code be improved?
Does it need refactoring? Refactor it.
- Consider the test code (reminder: test code is also code).
Can the code be improved?
Does it need refactoring? Refactor it.
Key idea:
- Refactor to improve the quality of the code;
changing internal structure (of the current code)
without changing its external behavior
Step 7: Repeat steps 2-6 until
all tests associated with the chosen requirement have been covered.
Step 8: Repeat steps 1-7 until
all requirements have been fulfilled.
Note: to help you review the TDD concept, you should use the
TDD slides for reference.