免责声明:祝你圣诞快乐,我希望我的问题不会打扰你!
sample.go:
package main
import(
"fmt"
"os"
)
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Println("Error: something is wrong!")
os.Exit(1)
} else {
fmt.Println("May the force be with you!")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: something is wrong!
// exit status 1
我做了很多关于如何在golang测试中使用接口的研究。但到目前为止,我还是无法彻底解决这个问题。至少我无法看到界面如何帮助我,当我需要“模拟”(道歉使用这个词)golang std。库包如“fmt”。
我提出了两种情况:
我不喜欢这两种情况:
这里的实际问题:还有另一种(更好/更简单/惯用)方式吗? 注意:我想在纯golang中执行此操作,我对下一个测试框架不感兴趣。
cli_test.go:
package main
import(
"os/exec"
"testing"
)
func TestCli(t *testing.T) {
out, err := exec.Command("go run sample.go").Output()
if err != nil {
t.Fatal(err)
}
if string(out) != "May the force be with you!\nError: this is broken and not useful!\nexit status 1" {
t.Fatal("There is something wrong with the CLI")
}
}
答案 0 :(得分:9)
Kerningham's Book的第11章为这个问题提供了一个很好的解决方案。 诀窍是将对fmt.Printline()的调用更改为调用 fmt.Fprint(out,...)其中out初始化为os.Stdout
这可以在测试工具中覆盖到new(bytes.Buffer)允许 测试以捕获输出。
见https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo.go和 https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo_test.go
由OP编辑... sample.go:
package main
import(
"fmt"
"os"
"io"
)
var out io.Writer = os.Stdout // modified during testing
var exit func(code int) = os.Exit
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Fprint(out, "Error: something is wrong!\n")
exit(1)
} else {
fmt.Fprint(out, "May the force be with you!\n")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: this is broken and not useful!
// exit status 1
cli_test.go:
package main
import(
"bytes"
"testing"
)
func TestUsefulPositive(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
s := sample{42}
s.useful()
if out.(*bytes.Buffer).String() != "May the force be with you!\n" {
t.Fatal("There is something wrong with the CLI")
}
}
func TestUsefulNegative(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
code := 0
osexit := exit
exit = func(c int) { code = c }
defer func() { exit = osexit }()
s := sample{0}
s.useful()
if out.(*bytes.Buffer).String() != "Error: something is wrong!\n" {
t.Fatal("There is something wrong with the CLI")
}
if code != 1 {
t.Fatal("Wrong exit code!")
}
}
答案 1 :(得分:2)
我在这里遗漏了什么,或者你在谈论testable examples?
基本上,它的工作原理如下:在*_test.go
文件中,您需要遵守惯例Example[[T][_M]]
,其中T
是该类型的占位符,M
a您想要将可测试示例显示为Godoc中的示例代码的方法的占位符。如果该函数只是调用Example()
,则代码将显示为包示例。
在示例代码的最后一行下方,您可以添加如下评论
// Output:
// Foo
现在go test
将确保 完全 的可测试示例函数将// Output:
下面的所有内容(包括空格)放出,或者它会生成测试失败。
以下是可测试示例的实际示例
func ExampleMongoStore_Get() {
sessionId := "ExampleGetSession"
data, err := ms.Get(sessionId)
if err == sessionmw.ErrSessionNotFound {
fmt.Printf("Session '%s' not found\n", sessionId)
data = make(map[string]interface{})
data["foo"] = "bar"
ms.Save(sessionId, data)
}
loaded, _ := ms.Get(sessionId)
fmt.Printf("Loaded value '%s' for key '%s' in session '%s'",
loaded["foo"],
"foo", sessionId)
// Output:
// Session 'ExampleGetSession' not found
// Loaded value 'bar' for key 'foo' in session 'ExampleGetSession'
}