英文:
Testing a Function by Passing Input Multiple Times
问题
我正在学习使用测试编写Go程序。我在《Head First Go》第2章的结尾部分得到了下面的程序。
该程序给用户三次机会猜一个从1到10的数字:
guess.go
package main
import (
"fmt"
"math/rand"
"time"
"bufio"
"os"
"log"
"strconv"
"strings"
)
func generateRandomNumber() int {
rand.Seed(time.Now().Unix()) // 使用时间作为种子生成非确定性随机值
randomNum := rand.Intn(10) + 1 // 范围:[0, 10);即使没有使用Seed(),也会生成相同的值,即伪随机
return randomNum
}
func guess() int {
var success bool = false
target := generateRandomNumber()
fmt.Println("猜一个1到10之间的数字")
guess := bufio.NewReader(os.Stdin)
for attempts := 0; attempts < 3; attempts++ {
fmt.Println("你还有", 3-attempts, "次猜测机会")
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("恭喜你!!")
return answer
} else if answer > target {
fmt.Println("你猜的数字太大了")
} else if answer < target {
fmt.Println("你猜的数字太小了")
}
}
if !success {
fmt.Printf("很抱歉,你已经用完了所有的猜测机会... 正确的数字是 %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("猜测错误;随机数是 %d", want)
}
}
我该如何通过传入三个不同的输入来测试guess()
函数?
我想通过比较guess()
的返回值和generateRandomNumber()
的返回值来进行测试。
英文:
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()
.
答案1
得分: 2
你可以更改guess
函数以从输入中获取读取器,这样我们就可以传递任何我们想要的读取器:在主函数中,我们传递stdin
读取器,在测试中,我们传递模拟读取器:
guess.go
package main
import (
"bufio"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func generateRandomNumber() int {
rand.Seed(time.Now().Unix()) // 基于时间生成非确定性随机值的种子值
randomNum := rand.Intn(10) + 1 // 范围:[0, 10);在没有Seed()的情况下产生相同的值,即伪随机
return randomNum
}
func guess(reader *bufio.Reader) (int, error) {
target := generateRandomNumber()
fmt.Println("猜一个1到10之间的数字")
for attempts := 0; attempts < 3; attempts++ {
fmt.Println("你还有", 3-attempts, "次猜测机会")
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("恭喜你!!")
return answer, nil
} else if answer > target {
fmt.Println("你猜的数字太大了")
} else if answer < target {
fmt.Println("你猜的数字太小了")
}
}
fmt.Printf("很抱歉,你已经用完了所有的猜测机会... 正确的数字是 %d\n", target)
return target, fmt.Errorf("猜测次数已用完")
}
func main() {
reader := bufio.NewReader(os.Stdin)
guess(reader)
}
用于测试的代码:
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("猜测应该成功")
}
}
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
函数的返回值,因为不知道它何时成功或失败。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论