多次传递输入来测试一个函数

huangapple go评论91阅读模式
英文:

Testing a Function by Passing Input Multiple Times

问题

我正在学习使用测试编写Go程序。我在《Head First Go》第2章的结尾部分得到了下面的程序。

该程序给用户三次机会猜一个从1到10的数字:

guess.go

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. "bufio"
  7. "os"
  8. "log"
  9. "strconv"
  10. "strings"
  11. )
  12. func generateRandomNumber() int {
  13. rand.Seed(time.Now().Unix()) // 使用时间作为种子生成非确定性随机值
  14. randomNum := rand.Intn(10) + 1 // 范围:[0, 10);即使没有使用Seed(),也会生成相同的值,即伪随机
  15. return randomNum
  16. }
  17. func guess() int {
  18. var success bool = false
  19. target := generateRandomNumber()
  20. fmt.Println("猜一个1到10之间的数字")
  21. guess := bufio.NewReader(os.Stdin)
  22. for attempts := 0; attempts < 3; attempts++ {
  23. fmt.Println("你还有", 3-attempts, "次猜测机会")
  24. userVal, err := guess.ReadString('\n')
  25. if err != nil {
  26. log.Fatal(err)
  27. }
  28. input := strings.TrimSpace(userVal)
  29. answer, err := strconv.Atoi(input)
  30. if err != nil {
  31. log.Fatal(err)
  32. }
  33. if answer == target {
  34. fmt.Println("恭喜你!!")
  35. return answer
  36. } else if answer > target {
  37. fmt.Println("你猜的数字太大了")
  38. } else if answer < target {
  39. fmt.Println("你猜的数字太小了")
  40. }
  41. }
  42. if !success {
  43. fmt.Printf("很抱歉,你已经用完了所有的猜测机会... 正确的数字是 %d\n", target)
  44. return target
  45. }
  46. return 0
  47. }
  48. func main() {
  49. guess()
  50. }

guess_test.go

  1. package main
  2. import (
  3. "testing";
  4. )
  5. func TestRandomNumber(t *testing.T) {
  6. want := generateRandomNumber()
  7. if 7 != want {
  8. t.Fail()
  9. t.Logf("猜测错误;随机数是 %d", want)
  10. }
  11. }

我该如何通过传入三个不同的输入来测试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

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;math/rand&quot;
  5. &quot;time&quot;
  6. &quot;bufio&quot;
  7. &quot;os&quot;
  8. &quot;log&quot;
  9. &quot;strconv&quot;
  10. &quot;strings&quot;
  11. )
  12. func generateRandomNumber() int {
  13. rand.Seed(time.Now().Unix()) // seed value based on time to generate non-deterministic random values
  14. randomNum := rand.Intn(10) + 1 // range: [0, 10); produces the same value without Seed(), i.e., pseudo-random
  15. return randomNum
  16. }
  17. func guess() int {
  18. var success bool = false
  19. target := generateRandomNumber()
  20. fmt.Println(&quot;Guess a number between 1 and 10&quot;)
  21. guess := bufio.NewReader(os.Stdin)
  22. for attempts := 0; attempts &lt; 3; attempts++ {
  23. fmt.Println(&quot;You have&quot;, 3-attempts, &quot;guesses left&quot;)
  24. userVal, err := guess.ReadString(&#39;\n&#39;)
  25. if err != nil {
  26. log.Fatal(err)
  27. }
  28. input := strings.TrimSpace(userVal)
  29. answer, err := strconv.Atoi(input)
  30. if err != nil {
  31. log.Fatal(err)
  32. }
  33. if answer == target {
  34. fmt.Println(&quot;Congratulations !!&quot;)
  35. return answer
  36. } else if answer &gt; target {
  37. fmt.Println(&quot;Your guess was HIGHER&quot;)
  38. } else if answer &lt; target {
  39. fmt.Println(&quot;Your guess was LOWER&quot;)
  40. }
  41. }
  42. if !success {
  43. fmt.Printf(&quot;Sorry, you&#39;ve run out of attempts... The correct value is %d\n&quot;, target)
  44. return target
  45. }
  46. return 0
  47. }
  48. func main() {
  49. guess()
  50. }

guess_test.go

  1. package main
  2. import (
  3. &quot;testing&quot;
  4. )
  5. func TestRandomNumber(t *testing.T) {
  6. want := generateRandomNumber()
  7. if 7 != want {
  8. t.Fail()
  9. t.Logf(&quot;Incorrect guess; The random number was %d&quot;, want)
  10. }
  11. }

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

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "math/rand"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "time"
  11. )
  12. func generateRandomNumber() int {
  13. rand.Seed(time.Now().Unix()) // 基于时间生成非确定性随机值的种子值
  14. randomNum := rand.Intn(10) + 1 // 范围:[0, 10);在没有Seed()的情况下产生相同的值,即伪随机
  15. return randomNum
  16. }
  17. func guess(reader *bufio.Reader) (int, error) {
  18. target := generateRandomNumber()
  19. fmt.Println("猜一个1到10之间的数字")
  20. for attempts := 0; attempts < 3; attempts++ {
  21. fmt.Println("你还有", 3-attempts, "次猜测机会")
  22. userVal, err := reader.ReadString('\n')
  23. if err != nil {
  24. log.Fatal(err)
  25. }
  26. input := strings.TrimSpace(userVal)
  27. answer, err := strconv.Atoi(input)
  28. if err != nil {
  29. log.Fatal(err)
  30. }
  31. if answer == target {
  32. fmt.Println("恭喜你!!")
  33. return answer, nil
  34. } else if answer > target {
  35. fmt.Println("你猜的数字太大了")
  36. } else if answer < target {
  37. fmt.Println("你猜的数字太小了")
  38. }
  39. }
  40. fmt.Printf("很抱歉,你已经用完了所有的猜测机会... 正确的数字是 %d\n", target)
  41. return target, fmt.Errorf("猜测次数已用完")
  42. }
  43. func main() {
  44. reader := bufio.NewReader(os.Stdin)
  45. guess(reader)
  46. }

用于测试的代码:

guess_test.go

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. )
  8. func TestRandomNumberOk(t *testing.T) {
  9. want := generateRandomNumber()
  10. msg := fmt.Sprintf("3\n4\n%d\n", want)
  11. reader := strings.NewReader(msg)
  12. r := bufio.NewReader(reader)
  13. _, err := guess(r)
  14. if err != nil {
  15. t.Errorf("猜测应该成功")
  16. }
  17. }
  18. func TestRandomNumberFail(t *testing.T) {
  19. want := generateRandomNumber()
  20. msg := fmt.Sprintf("3\n4\n%d\n", want+1)
  21. reader := strings.NewReader(msg)
  22. r := bufio.NewReader(reader)
  23. _, err := guess(r)
  24. if err == nil {
  25. t.Errorf("猜测应该失败")
  26. }
  27. }

我不得不更改你的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

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;fmt&quot;
  5. &quot;log&quot;
  6. &quot;math/rand&quot;
  7. &quot;os&quot;
  8. &quot;strconv&quot;
  9. &quot;strings&quot;
  10. &quot;time&quot;
  11. )
  12. func generateRandomNumber() int {
  13. rand.Seed(time.Now().Unix()) // seed value based on time to generate non-deterministic random values
  14. randomNum := rand.Intn(10) + 1 // range: [0, 10); produces the same value without Seed(), i.e., pseudo-random
  15. return randomNum
  16. }
  17. func guess(reader *bufio.Reader) (int, error) {
  18. target := generateRandomNumber()
  19. fmt.Println(&quot;Guess a number between 1 and 10&quot;)
  20. for attempts := 0; attempts &lt; 3; attempts++ {
  21. fmt.Println(&quot;You have&quot;, 3-attempts, &quot;guesses left&quot;)
  22. userVal, err := reader.ReadString(&#39;\n&#39;)
  23. if err != nil {
  24. log.Fatal(err)
  25. }
  26. input := strings.TrimSpace(userVal)
  27. answer, err := strconv.Atoi(input)
  28. if err != nil {
  29. log.Fatal(err)
  30. }
  31. if answer == target {
  32. fmt.Println(&quot;Congratulations !!&quot;)
  33. return answer, nil
  34. } else if answer &gt; target {
  35. fmt.Println(&quot;Your guess was HIGHER&quot;)
  36. } else if answer &lt; target {
  37. fmt.Println(&quot;Your guess was LOWER&quot;)
  38. }
  39. }
  40. fmt.Printf(&quot;Sorry, you&#39;ve run out of attempts... The correct value is %d\n&quot;, target)
  41. return target, fmt.Errorf(&quot;attempts is over&quot;)
  42. }
  43. func main() {
  44. reader := bufio.NewReader(os.Stdin)
  45. guess(reader)
  46. }

for testing:

guess_test.go

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;fmt&quot;
  5. &quot;strings&quot;
  6. &quot;testing&quot;
  7. )
  8. func TestRandomNumberOk(t *testing.T) {
  9. want := generateRandomNumber()
  10. msg := fmt.Sprintf(&quot;3\n4\n%d\n&quot;, want)
  11. reader := strings.NewReader(msg)
  12. r := bufio.NewReader(reader)
  13. _, err := guess(r)
  14. if err != nil {
  15. t.Errorf(&quot;guess must successfull&quot;)
  16. }
  17. }
  18. func TestRandomNumberFail(t *testing.T) {
  19. want := generateRandomNumber()
  20. msg := fmt.Sprintf(&quot;3\n4\n%d\n&quot;, want+1)
  21. reader := strings.NewReader(msg)
  22. r := bufio.NewReader(reader)
  23. _, err := guess(r)
  24. if err == nil {
  25. t.Errorf(&quot;guess must unsuccessfull&quot;)
  26. }
  27. }

I had to change your guess return value, because it's unknown when it's successful or not

huangapple
  • 本文由 发表于 2022年2月12日 12:39:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/71089020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定