Practice for TDD
FizzBuzz
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
Sample output:
1
2
Fizz
4
Buzz
...
13
14
FizzBuzz
16
...
98
Fizz
Buzz
Setting up the environment
Generate a new project
- Create a new project
fizzbuzz$ mkdir fizzbuzz $ cd fizzbuzz $ go mod init fizzbuzz
Create an initial code
- Implement the function
fizzbuzzto make a string correspoind to an input number - The template of golang file
fizzbuzz.goto be implemented is ```go package main
func fizzbuzz(i int) string { // implementation here return “42” }
func main() { // implementation is not yet }
### Create a test code
- The template of test code `fizzbuzz_test.go` is
```go
package main
import "testing"
func TestFizzBuzz01(t *testing.T) {
str := fizzbuzz(1)
if str != "42" {
t.Error("Test01 is failed")
}
}
// Add test codes
Run the test code
- Run the test code
$ go test -v - The test success because the function
fizzbuzzreturns “42” for any input number.
Create Todo list
- List up the tasks to do for the program, e.g., creating the following markdown file
- [ ] Create the function `fizzbuzz`
- [ ] Return the string correspoindingt to a given int number.
- [ ] Return the string where 'Fizz' if the number is a multiple of 3.
- [ ] Return the string where 'Buzz' if the number is a multiple of 5.
- [ ] Return the string where 'FizzBuzz' if the number is a multiple of both 3 and 5.
TDD Cycle 1
Create test code
- Pick up a task to do and it moves to the lane Doing.
- Pick up
Return the string correspoindingt to a given int number.
- Pick up
- Consider a subtask for the task
- Consider a subtask
Return the string "1" when the argument is 1
- Consider a subtask
- Implement of a test code for a task/subtask as a test function
func TestFizzBuzz01(t *testing.T) { str := fizzbuzz(1) if str != "1" { t.Error("Test01 is failed") } } - Run all the tests (The status is Red)
go test -v
Implementation
- Implement a code to pass the test with minimum changes
func fizzbuzz(i int) string { return "1" } - Run all the tests (The status is Green)
Refactoring
- Consider the refactoring whenever the status becomes Green.
- In this case, we skip the refactoring though the code is not good.
TDD Cycle 2
Add test code
- Check the task is done or not
- The task is not done yet.
- Consider a subtask for the task
- A subtask
Return the string "2" when the argument is 2
- A subtask
- Add a test code for a task/subtask
func TestFizzBuzz02(t *testing.T) { str := fizzbuzz(2) if str != "2" { t.Error("Test02 is failed") } } - Run the tests. The status is Red.
go test
Implementation
- Implement a code to pass the test with minimum changes
- This code causes the failure of first test
func fizzbuzz(i int) string { return "2" } - For the time being, we implement to pass the test as short as we can (because we do not know the function from int to string)
func fizzbuzz(i int) string { if i == 1 { return "1" } else { return "2" } }
- This code causes the failure of first test
- Run all the tests (The status is Green)
Refactoring
- Consider the refactoring whenever the status becomes Green.
- The implementaion is not good clearly.
- We search the function of Go to change int to string.
- Change the body of codes while the status is kept Green. ```go import “strconv”
func fizzbuzz(i int) string { return strconv.Itoa(i) } ```
Point
Why do we change the body of codes while the status is kept Green?
- It takes much time to search the method from int to string, because it requires to learn how to use
import. - During searching it, anyone cannot touch the code, and the development completely stops.
-
Minimum changes mean the minimum time for Red.
- It had better to implement it with just the knowledge we know now.
TDD Cycle 3
Create test code
- The task
Return the string correspoindingt to a given int number.seems to be done.- Note: Definition of done of this task consists of two requirements written by test codes.
- Pick up the next task
This procedure continues until all the tasks are done.