英文:
Get golang coverage programmatically
问题
go -cover或-coverprofile在运行go测试时非常好用,可以以HTML或纯文本的形式展示。但是是否有API可以以编程方式访问它或处理该文件呢?
英文:
The go -cover or -coverprofile is great when running go tests and can show nicely in html or plain text. But is there an api to access it programmatically or process the file?
答案1
得分: 4
你可以尝试使用axw/gocov
,它具有以下功能:
你可以看到像GoCov GUI这样的工具在convert_statements(s []*gocov.Statement, offset int)
中使用gocov.Statement
来构建一个小型的GUI:
英文:
You can try axw/gocov
, which:
- will run test with a
-coverprofile
argument - parse the results (
gocov/convert.go
)
You can see a tool like GoCov GUI uses gocov.Statement
in convert_statements(s []*gocov.Statement, offset int)
in order to build a small GUI:
答案2
得分: 1
假设我们想要从某个地方动态获取项目,并将其存储在当前文件夹下的"_repos/src"文件夹中,然后获取测试覆盖率百分比(作为float64)。输入将是项目的典型"go get"格式。我们需要执行"go test -cover"命令,并设置正确的GOPATH变量,解析输出,并提取测试覆盖率的实际百分比。使用当前的Go 1.9测试工具,下面的代码可以实现这一目标。
// ParseFloatPercent将带有数字%的字符串转换为浮点数。
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返回测试代码覆盖率作为浮点数
// 我们假设project是一个字符串
// 以标准的"go get"形式,例如:
// "github.com/apache/kafka"
// 并且,你已经将仓库克隆到当前文件夹下的"_repos/src"中。
//
func GetTestCoverage(project string) (float64, error) {
cmdArgs := append([]string{"test", "-cover"}, project)
cmd := exec.Command("go", cmdArgs...)
// 获取我们主可执行文件的绝对路径
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Println(err)
return 0, err
}
// 设置测试的GOPATH
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))
// 运行"go test -cover"后的第一行应该是以下形式
// ok <project> 6.554s coverage: 64.9% of statements
// 使用制表符和空格进行分割
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 {
// 百分比解析问题
return 0, err
}
return f, nil
}
以上代码可以实现从git仓库中获取项目,并计算测试覆盖率的百分比。
英文:
Let us assume that we want to obtain test coverage percentage (as float64) on a project that we dynamically fetch from a git repo from somewhere, and store in the current folder under "_repos/src". The input would be the project in a typical "go get" format. We need to execute "go test -cover", with the properly GOPATH variable set, parse the output, and extract the actual percentage of the test coverage. With the current Go 1.9 testing tool, the code below achieves that.
// 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论