shell - 在 Golang 中需要交互式输入的测试执行程序

标签 shell go exec fzf

我正在尝试使用 fzf在 Go 代码中。我引用了给出的示例 here由作者。当我尝试为该函数编写测试时,它卡住了,因为 fzf 需要交互式输入。

代码:

func withFilter(command string, input func(in io.WriteCloser)) []string {
    shell := os.Getenv("SHELL")
    if len(shell) == 0 {
        shell = "sh"
    }
    cmd := exec.Command(shell, "-c", command)
    cmd.Stderr = os.Stderr
    in, _ := cmd.StdinPipe()
    go func() {
        input(in)
        in.Close()
    }()
    result, _ := cmd.Output()
    return strings.Split(string(result), "\n")
}

func filter() []string {
    filtered := withFilter("fzf -m", func(in io.WriteCloser) {
        for i := 0; i < 10; i++ {
            fmt.Fprintln(in, i)
            time.Sleep(5 * time.Millisecond)
        }
    })

    return filtered
}

测试:

func TestFilter(t *testing.T) {
    assert.Equal(t, []string{"1", "2", "3"}, filter())
}

我尝试调试并注意到它卡在 cmd.Output() 处。通过更深入地挖掘,看起来该命令正在无限期地等待输入,但是我不确定如何以编程方式提供它。我尝试将 \n 写入 os.Stdin 但它没有用。

任何人的指点或解释将不胜感激。谢谢。

最佳答案

go 的优点:它的 io.Reader/io.Writer 接口(interface)。

您必须提供您的withFilter(以及扩展名filter)方法应该从哪里读取。因此,in 必须提供它。

// example

func readFrom(reader io.Reader) {
    r := bufio.NewScanner(reader)

    for r.Scan() {
        fmt.Println("got", r.Text())
    }

    fmt.Println("Done.")
}

func main() {
    const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n"

    readFrom(strings.NewReader(input))

    // okay, with stdin
    readFrom(os.Stdin)

}

如您所见,第一个 readFrom 是完全可测试的,您只需将 input 变量更改为您想要测试的任何值。第二个 readFrom 只会在 stdin 关闭时返回。

解决方案是写入os.Stdin。将 os.Stdin 视为操作系统中的实现细节,而不是必须包含在测试中的内容。

https://play.golang.org/p/D2wzHYrV2TM (os.Stdin 在 Playground 上关闭)

关于shell - 在 Golang 中需要交互式输入的测试执行程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54470127/

相关文章:

perl - 如何制作从 A 到 Z 的字母列表并在 shell 中迭代它们?

linux - 仅当 Linux bash 中存在子文件夹时,才获取带有文件名的当前目录(非完整路径)

phpwebsocket 不工作

powershell - 使用 powershell 在现有 CSV 中添加列 CSV

go - 如何让 filepath.IsAbs 正确识别绝对路径?

java - 运行时exec输出路径

github - 在 Golang 中实现 GitHub 徽章

go - 理解 Go 中的死锁

php - 带 nohup 的 Shell_exec php

multithreading - goroutine调用exec后主线程不运行?