以编程方式获取Golang代码覆盖率

8

在运行go测试时,go-cover或-coverprofile非常好用,并且可以以漂亮的HTML或纯文本形式显示。但是是否有API可以以编程方式访问它或处理文件?

2个回答

4

1
假设我们想从某个Git仓库动态获取项目,并将其存储在当前文件夹下的“_repos/src”中,以获得测试覆盖率百分比(作为float64)。输入应为典型的"go get"格式的项目。我们需要执行"go test -cover",设置正确的GOPATH变量,解析输出并提取测试覆盖率的实际百分比。使用当前的Go 1.9测试工具,以下代码可以实现此目的。
// ParseFloatPercent turns string with number% into float.
func ParseFloatPercent(s string, bitSize int) (f float64, err error) {
    i := strings.Index(s, "%")
    if i < 0 {
        return 0, fmt.Errorf("ParseFloatPercent: percentage sign not found")
    }
    f, err = strconv.ParseFloat(s[:i], bitSize)
    if err != nil {
        return 0, err
    }
    return f / 100, nil
}

// GetTestCoverage returns the tests code coverage as float
// we are assuming that project is a string
// in a standard "Go get" form, for example:
//     "github.com/apache/kafka"
// and, that you have cloned the repo into "_repos/src"
// of the current folder where your executable is running.
//
func GetTestCoverage(project string) (float64, error) {
    cmdArgs := append([]string{"test", "-cover"}, project)
    cmd := exec.Command("go", cmdArgs...)
    // get the file absolute path of our main executable
    dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    if err != nil {
        log.Println(err)
        return 0, err
    }
    // set the GOPATH for tests to work
    cmd.Env = os.Environ()
    cmd.Env = append(cmd.Env, "GOPATH="+dir+"/_repos/")

    var out []byte
    cmd.Stdin = nil
    out, err = cmd.Output()

    if err != nil {
        fmt.Println(err.Error())
        return 0, err
    }

    r := bufio.NewReader(bytes.NewReader(out))
    // first line from running "go test -cover" should be in a form
    // ok   <project>   6.554s  coverage: 64.9% of statements
    // split with /t and <space> characters
    line, _, err := r.ReadLine()

    if err != nil {
        fmt.Println(err.Error())
        return 0, err
    }

    parts := strings.Split(string(line), " ")
    if len(parts) < 6 {
        return 0, errors.New("go test -cover do not report coverage correctly")
    }
    if parts[0] != "ok" {
        return 0, errors.New("tests do not pass")
    }
    f, err := ParseFloatPercent(parts[3], 64)
    if err != nil {
        // the percentage parsing problem
        return 0, err
    }

    return f, nil
}

有趣。+1。我的回答是三年前写的,不过没必要踩它。 - VonC
没问题。我做了一个小修改。我仍然感谢您对这个老问题的贡献(使用Go 1.9)。 - VonC
我在我们的仓库标记子系统上遇到了这个问题。我使用“测试覆盖率”来检查学生是否进行了所需的测试覆盖率。axw/gocov 有点过度,而且它没有做我想要的事情 - 我只想要动态拉取的仓库中的测试覆盖率浮点数。 - marni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接