2014-07-09 119 views
6

go -cover或-coverprofile在运行go测试时非常出色,并且可以在html或纯文本中很好地显示。但有没有一个API来以编程方式访问它或处理文件?以编程方式获得golang覆盖

回答

1

让我们假设我们想要获得一个项目的测试覆盖百分比(作为float64),我们从某个地方从git仓库动态获取并存储在当前文件夹下的“_repos/src”下。输入将是典型的“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 
} 
+0

有趣。 +1。我的答案是三年前写的。没有必要downvote。 – VonC

+0

没问题。我做了一个小小的编辑。我仍然感谢你对这个老问题的贡献(用Go 1.9)。 – VonC

+0

我已经偶然发现了我们的回购标记子系统。我使用“测试覆盖率”来检查学生是否需要测试覆盖。 axw/gocov有点矫枉过正,而且它没有做我想做的 - 我只是想让测试覆盖率浮动,并且在回收库中动态调整。 – marni

相关问题