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

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

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 (
	&quot;fmt&quot;
	&quot;math/rand&quot;
	&quot;time&quot;
	&quot;bufio&quot;
	&quot;os&quot;
	&quot;log&quot;
	&quot;strconv&quot;
	&quot;strings&quot;
)

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(&quot;Guess a number between 1 and 10&quot;)
	guess  := bufio.NewReader(os.Stdin)

	for attempts := 0; attempts &lt; 3; attempts++ {
		fmt.Println(&quot;You have&quot;, 3-attempts, &quot;guesses left&quot;)
		userVal, err := guess.ReadString(&#39;\n&#39;)
		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(&quot;Congratulations !!&quot;)
			return answer
		} else if answer &gt; target {
			fmt.Println(&quot;Your guess was HIGHER&quot;)
		} else if answer &lt; target {
			fmt.Println(&quot;Your guess was LOWER&quot;)
		}
	}

	if !success {
		fmt.Printf(&quot;Sorry, you&#39;ve run out of attempts... The correct value is %d\n&quot;, target)
		return target	
	}
	return 0
}

func main() {
	guess()
}

guess_test.go

package main
import (
&quot;testing&quot;
)
func TestRandomNumber(t *testing.T) {
want := generateRandomNumber()
if 7 != want {
t.Fail()
t.Logf(&quot;Incorrect guess; The random number was %d&quot;, 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 (
&quot;bufio&quot;
&quot;fmt&quot;
&quot;log&quot;
&quot;math/rand&quot;
&quot;os&quot;
&quot;strconv&quot;
&quot;strings&quot;
&quot;time&quot;
)
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(&quot;Guess a number between 1 and 10&quot;)
for attempts := 0; attempts &lt; 3; attempts++ {
fmt.Println(&quot;You have&quot;, 3-attempts, &quot;guesses left&quot;)
userVal, err := reader.ReadString(&#39;\n&#39;)
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(&quot;Congratulations !!&quot;)
return answer, nil
} else if answer &gt; target {
fmt.Println(&quot;Your guess was HIGHER&quot;)
} else if answer &lt; target {
fmt.Println(&quot;Your guess was LOWER&quot;)
}
}
fmt.Printf(&quot;Sorry, you&#39;ve run out of attempts... The correct value is %d\n&quot;, target)
return target, fmt.Errorf(&quot;attempts is over&quot;)
}
func main() {
reader := bufio.NewReader(os.Stdin)
guess(reader)
}

for testing:

guess_test.go

package main
import (
&quot;bufio&quot;
&quot;fmt&quot;
&quot;strings&quot;
&quot;testing&quot;
)
func TestRandomNumberOk(t *testing.T) {
want := generateRandomNumber()
msg := fmt.Sprintf(&quot;3\n4\n%d\n&quot;, want)
reader := strings.NewReader(msg)
r := bufio.NewReader(reader)
_, err := guess(r)
if err != nil {
t.Errorf(&quot;guess must successfull&quot;)
}
}
func TestRandomNumberFail(t *testing.T) {
want := generateRandomNumber()
msg := fmt.Sprintf(&quot;3\n4\n%d\n&quot;, want+1)
reader := strings.NewReader(msg)
r := bufio.NewReader(reader)
_, err := guess(r)
if err == nil {
t.Errorf(&quot;guess must unsuccessfull&quot;)
}
}

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:

确定