unit-testing - 通过多次传递输入来测试函数

标签 unit-testing go user-input

我正在通过测试学习 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())       // 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)
    }
}

如何通过传入三个不同的输入来测试 guess()

我想通过比较 guess()generateRandomNumber() 的返回值来执行测试。

最佳答案

您可以更改 guess 函数以从输入中获取读取器,这样我们就可以将其传递给我们想要的任何读取器:在 main 中我们传递 stdin 读取器,在测试中我们通过模拟阅读器:

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)
}

用于测试:

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")
    }
}

我不得不更改你猜测的返回值,因为它何时成功与否是未知的

关于unit-testing - 通过多次传递输入来测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71089020/

相关文章:

c# - 通知用户无效输入的常见做法是什么?

javascript - Angular 2 自定义验证器 : check if the input value is an integer?

c - 如何一次输入二维字符串的所有元素?

javascript - 注入(inject) $stateParams 以使用 karma 进行 Angular 单元测试测试

vba - 使用 Rubberduck 单元测试,我如何找出多个断言中的哪一个失败?

unit-testing - java.lang.IllegalStateException : Failed to load ApplicationContext in JUNIT 错误

opencv - gocv : how to cut out an image from blue background using opencv

golang递归函数如何检查返回值?

java - Go 的多线程和 pthread 或 Java 线程有什么区别?

reactjs - 使用 Jest 在 React Native 中模拟 Child