I'm learning Go with tests. I ended up with the below program from the end of chapter 2 in "Head First Go".
It gives the user three attempts to guess a number from 1 to 10:
guess.go
package main
import (
"fmt"
"math/rand"
"time"
"bufio"
"os"
"log"
"strconv"
"strings"
)
func generateRandomNumber() int {
rand.Seed(time.Now().Unix()) // seed value based on time to generate non-deterministic random values
randomNum := rand.Intn(10) + 1 // range: [0, 10); produces the same value without Seed(), i.e., pseudo-random
return randomNum
}
func guess() int {
var success bool = false
target := generateRandomNumber()
fmt.Println("Guess a number between 1 and 10")
guess := bufio.NewReader(os.Stdin)
for attempts := 0; attempts < 3; attempts++ {
fmt.Println("You have", 3-attempts, "guesses left")
userVal, err := guess.ReadString('\n')
if err != nil {
log.Fatal(err)
}
input := strings.TrimSpace(userVal)
answer, err := strconv.Atoi(input)
if err != nil {
log.Fatal(err)
}
if answer == target {
fmt.Println("Congratulations !!")
return answer
} else if answer > target {
fmt.Println("Your guess was HIGHER")
} else if answer < target {
fmt.Println("Your guess was LOWER")
}
}
if !success {
fmt.Printf("Sorry, you've run out of attempts... The correct value is %d\n", target)
return target
}
return 0
}
func main() {
guess()
}
guess_test.go
package main
import (
"testing"
)
func TestRandomNumber(t *testing.T) {
want := generateRandomNumber()
if 7 != want {
t.Fail()
t.Logf("Incorrect guess; The random number was %d", want)
}
}
How can I test guess() by passing in three different inputs?
I would like to perform a test by comparing the return value of guess() with generateRandomNumber().
You can change guess function to get reader from input, by this we able to pass it any reader we want: in main we pass stdin reader and in test we pass mock reader:
guess.go
package main
import (
"bufio"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func generateRandomNumber() int {
rand.Seed(time.Now().Unix()) // seed value based on time to generate non-deterministic random values
randomNum := rand.Intn(10) + 1 // range: [0, 10); produces the same value without Seed(), i.e., pseudo-random
return randomNum
}
func guess(reader *bufio.Reader) (int, error) {
target := generateRandomNumber()
fmt.Println("Guess a number between 1 and 10")
for attempts := 0; attempts < 3; attempts++ {
fmt.Println("You have", 3-attempts, "guesses left")
userVal, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
input := strings.TrimSpace(userVal)
answer, err := strconv.Atoi(input)
if err != nil {
log.Fatal(err)
}
if answer == target {
fmt.Println("Congratulations !!")
return answer, nil
} else if answer > target {
fmt.Println("Your guess was HIGHER")
} else if answer < target {
fmt.Println("Your guess was LOWER")
}
}
fmt.Printf("Sorry, you've run out of attempts... The correct value is %d\n", target)
return target, fmt.Errorf("attempts is over")
}
func main() {
reader := bufio.NewReader(os.Stdin)
guess(reader)
}
for testing:
guess_test.go
package main
import (
"bufio"
"fmt"
"strings"
"testing"
)
func TestRandomNumberOk(t *testing.T) {
want := generateRandomNumber()
msg := fmt.Sprintf("3\n4\n%d\n", want)
reader := strings.NewReader(msg)
r := bufio.NewReader(reader)
_, err := guess(r)
if err != nil {
t.Errorf("guess must successfull")
}
}
func TestRandomNumberFail(t *testing.T) {
want := generateRandomNumber()
msg := fmt.Sprintf("3\n4\n%d\n", want+1)
reader := strings.NewReader(msg)
r := bufio.NewReader(reader)
_, err := guess(r)
if err == nil {
t.Errorf("guess must unsuccessfull")
}
}
I had to change your guess return value, because it's unknown when it's successful or not
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With