[英]How to test the main package functions in golang?
我想測試我的主包中包含的一些函數,但我的測試似乎無法訪問這些函數。
我的示例 main.go 文件如下所示:
package main
import (
"log"
)
func main() {
log.Printf(foo())
}
func foo() string {
return "Foo"
}
我的 main_test.go 文件看起來像:
package main
import (
"testing"
)
func Foo(t testing.T) {
t.Error(foo())
}
當我運行go test main_test.go
我得到
# command-line-arguments
.\main_test.go:8: undefined: foo
FAIL command-line-arguments [build failed]
據我了解,即使我將測試文件移到其他地方並嘗試從 main.go 文件導入,我也無法導入它,因為它是package main
。
構建此類測試的正確方法是什么? 我應該從main
包中刪除所有內容,除了一個簡單的主函數來運行所有內容,然后在自己的包中測試這些函數,還是有辦法讓我在測試期間從主文件中調用這些函數?
在命令行上指定文件時,必須指定所有文件
這是我的運行:
$ ls
main.go main_test.go
$ go test *.go
ok command-line-arguments 0.003s
請注意,在我的版本中,我在命令行上同時運行了main.go和main_test.go
此外,您的_test文件不太正確,您需要將測試函數稱為TestXXX並指向測試.T
這是修改過的verison:
package main
import (
"testing"
)
func TestFoo(t *testing.T) {
t.Error(foo())
}
和修改后的輸出:
$ go test *.go
--- FAIL: TestFoo (0.00s)
main_test.go:8: Foo
FAIL
FAIL command-line-arguments 0.003s
單元測試只到目前為止。 在某些時候,你必須實際運行該程序。 然后你測試它是否與實際輸入一起工作,從真實來源,產生實際輸出到真實目的地。 真的。
如果你想對單元進行單元測試,請將其移出main()。
這不是 OP問題的直接答案,我總體上同意先前的答案和評論,敦促main
應該是打包函數的調用者。 話雖這么說,這是我發現有用的測試可執行文件的方法。 它使用log.Fataln
和exec.Command
。
main.go
,該函數調用log.Fatalln()以在返回之前將消息寫入stderr。 main_test.go
,使用exec.Command(...)
和cmd.CombinedOutput()
來運行程序,並選擇參數來測試某些預期結果。 例如:
func main() {
// Ensure we exit with an error code and log message
// when needed after deferred cleanups have run.
// Credit: https://medium.com/@matryer/golang-advent-calendar-day-three-fatally-exiting-a-command-line-tool-with-grace-874befeb64a4
var err error
defer func() {
if err != nil {
log.Fatalln(err)
}
}()
// Initialize and do stuff
// check for errors in the usual way
err = somefunc()
if err != nil {
err = fmt.Errorf("somefunc failed : %v", err)
return
}
// do more stuff ...
}
在main_test.go
,測試應該導致somefunc
失敗的錯誤參數可能如下所示:
func TestBadArgs(t *testing.T) {
var err error
cmd := exec.Command(yourprogname, "some", "bad", "args")
out, err := cmd.CombinedOutput()
sout := string(out) // because out is []byte
if err != nil && !strings.Contains(sout, "somefunc failed") {
fmt.Println(sout) // so we can see the full output
t.Errorf("%v", err)
}
}
請注意,來自CombinedOutput()
err
是來自log.Fatalln對os.Exit(1)
調用的非零退出代碼。 這就是我們需要用out
來從somefunc
提取錯誤消息的somefunc
。
exec
包還提供cmd.Run
和cmd.Output
。 對於某些測試,這些可能比cmd.CombinedOutput
更合適。 我還發現有一個TestMain(m *testing.M)
函數可以在運行測試之前和之后進行設置和清理。
func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags
os.Mkdir("test", 0777) // set up a temporary dir for generate files
// Create whatever testfiles are needed in test/
// Run all tests and clean up
exitcode := m.Run()
os.RemoveAll("test") // remove the directory and its contents.
os.Exit(exitcode)
main
並斷言退出代碼@MikeElis 的回答讓我成功了一半,但是缺少 Go 自己的 flag_test.go 幫助我弄清楚的主要部分。
您本質上想要運行您的應用程序並測試正確性。 因此,請隨意標記此測試並將其歸檔在該類別中。 但值得嘗試這種類型的測試並看到好處。 特別是如果您正在編寫 CLI 應用程序。
這個想法是像往常一樣運行go test
,並且
go test
制作的應用程序的測試版本在子流程中“自己”運行單元測試(參見第86行)main
並導致測試以main
的退出代碼退出的代碼部分: if os.Getenv(SubCmdFlags) != "" { // We're in the test binary, so test flags are set, lets reset it so // so that only the program is set // and whatever flags we want. args := strings.Split(os.Getenv(SubCmdFlags), " ") os.Args = append([]string{os.Args[0]}, args...) // Anything you print here will be passed back to the cmd.Stderr and // cmd.Stdout below, for example: fmt.Printf("os args = %v\\n", os.Args) // Strange, I was expecting a need to manually call the code in // `init()`,but that seem to happen automatically. So yet more I have learn. main() }
注意:如果 main 函數沒有退出,測試將掛起/循環。 // get exit code. got := cmd.ProcessState.ExitCode() if got != test.want { t.Errorf("got %q, want %q", got, test.want) }
注意:在此示例中,如果返回預期退出代碼以外的任何內容,則測試會從子進程中輸出 STDOUT 和/或 STDERR,以幫助調試。在此處查看完整示例: go-gitter:測試 CLI
因為你只為測試設置了一個文件,所以不會使用其他的go文件。
運行go test
而不是go test main_test.go
。
TestFoo(t *testing.T)
測試函數簽名Foo(t testing.T)
更改為TestFoo(t *testing.T)
。
在兩個來源中將包名稱從main更改為foobar。 在src / foobar下移動源文件。
mkdir -p src/foobar
mv main.go main_test.go src/foobar/
確保將GOPATH設置為src / foobar所在的文件夾。
export GOPATH=`pwd -P`
測試它
go test foobar
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.