【问题标题】:how do you test golang command line output [duplicate]你如何测试golang命令行输出[重复]
【发布时间】:2017-03-09 05:29:22
【问题描述】:

我想测试一个 golang 命令行应用程序的输出,但我不太确定如何使用 go 的测试库来做到这一点。

假设我有一个这样的程序:

package main

import (
    "flag"
    "fmt"
)

func main() {
    const (
        cityDefault = "San Francisco"
        cityDoc     = "the city you want the forecast for"
    )
    var city string
    flag.StringVar(&city, "city", cityDefault, cityDoc)
    flag.StringVar(&city, "c", cityDefault, cityDoc)
    flag.Parse()

    fmt.Println(city)
}

我想测试这两个:

$ ./myapp -c "Los Angeles"
$ ./myapp -city "Los Angeles"

...输出Lost Angeles。所以,我想问题是,你如何对 golang 命令行应用程序的输出进行集成测试?

【问题讨论】:

  • @TheHippo 我的问题并不是关于如何测试标志本身。我给出的例子可以归结为这一点,但主要是因为它是一个微不足道的例子。想象一个更复杂的应用程序,其中有许多其他功能被单独测试。我想对使用这些部分的应用程序的输出进行集成测试。

标签: testing go


【解决方案1】:

这是解析命令行参数的一个不好的例子,但它显示了我用来在我的应用程序中测试命令行参数的框架。

ma​​in.go

package main

import (
    "log"
    "os"
)

func main() {
    var city string
    parseFlags(&city, os.Args)

    log.Println(city)
}

func parseFlags(result *string, args []string) {
    cityDefault := "San Francisco"

    switch len(args) {
    case 3:
        *result = args[2]
    default:
        *result = cityDefault
    }
}

ma​​in_unit_test.go

package main

import (
    "log"
    "testing"
)

// TestParseFlags - test our command line flags
func TestParseFlags(t *testing.T) {
    var parseFlagsTests = []struct {
        flags    []string // input flags to the command line
        expected string   // expected
    }{
        {[]string{"/fake/loc/main"}, "San Francisco"},
        {[]string{"/fake/loc/main", "-c", "Los Angeles"}, "Los Angeles"},
        {[]string{"/fake/loc/main", "--city", "Los Angeles"}, "Los Angeles"},
    }

    for _, tt := range parseFlagsTests {
        var output string
        parseFlags(&output, tt.flags)
        if output != tt.expected {
            t.Errorf("expected: %s, actual: %s", tt.expected, output)
        }
    }
}

我通常使用this package 来解析我所有应用程序中的命令行参数。我将按如下方式构建我的代码(未显示测试,但它们通常遵循上面显示的测试的要点):

ma​​in.go

package main

import (
    "log"
    "os"

    "myDir/cli"
)

func main() {
    // Grab the user inputed CLI flags
    cliFlags := cli.FlagsStruct{}
    cliErr := cli.StartCLI(&cliFlags, os.Args)
    if cliErr != nil {
        log.Println("Error grabbing command line args")
        log.Fatal(cliErr)
    }

    // Do stuff ...
}

/myDir/cli.go

package cli

import "github.com/urfave/cli"

// FlagsStruct - holds command line args
type FlagsStruct struct {
    MyFlag string
}

// StartCLI - gathers command line args
func StartCLI(cliFlags *FlagsStruct, args []string) error {
    app := cli.NewApp()
    app.Action = func(ctx *cli.Context) error {
        MyFlag := ctx.GlobalString("my-flag")

        // build the cli struct to send back to main
        cliFlags.MyFlag = MyFlag
        return nil
    }
    app.Authors = []cli.Author{
        {
            Email: "my@email.com",
            Name:  "Adam Hanna",
        },
    }
    app.Flags = []cli.Flag{
        cli.StringFlag{
            Name:  "my-flag, f",
            Usage: "My flag usage goes here",
            Value: "myDefault",
        },
    }
    app.Name = "myAppName"
    app.Usage = "My App's Usage"
    app.Version = "0.0.1"
    return app.Run(args)
}

【讨论】:

    【解决方案2】:

    test "$(./myapp -c "Los Angeles")" = "Los Angeles" 怎么样? -city 也是如此。这与 Go 无关,只需让您的集成测试套件进行测试即可。

    【讨论】:

    • 当然,这是有道理的。我想我希望你能就如何做这件事得到更多的指导。但我想对于 Stack Overflow 的响应来说,这最终会变得有点过于开放,因为它会演变成一个固执己见的工具链讨论(天堂禁止)。但是,我认为这为我指明了正确的方向。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 2018-11-04
    • 2014-10-26
    相关资源
    最近更新 更多