【问题标题】:Get golang coverage programmatically以编程方式获取 golang 覆盖率
【发布时间】:2017-09-25 05:14:47
【问题描述】:

go -cover 或 -coverprofile 在运行 go 测试时非常有用,并且可以很好地显示为 html 或纯文本。但是是否有 api 可以以编程方式访问它或处理文件?

【问题讨论】:

    标签: go code-coverage


    【解决方案1】:

    你可以试试axw/gocov,其中:

    您可以看到像GoCov GUI 这样的工具在convert_statements(s []*gocov.Statement, offset int) 中使用gocov.Statement 来构建一个小型GUI:

    【讨论】:

      【解决方案2】:

      让我们假设我们想要获得一个项目的测试覆盖率(作为 float64),我们从某个地方动态地从 git repo 获取,并存储在“_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
      }
      

      【讨论】:

      • 有趣。 +1。我的答案是三年前写的。不过,没有必要投反对票。
      • 没问题。我做了一个小的编辑。我仍然感谢您对这个老问题的贡献(使用 Go 1.9)。
      • 我在我们的 repo 标记子系统中偶然发现了这一点。我使用“测试覆盖率”来检查学生是否进行了所需的测试覆盖率。 axw/gocov 有点矫枉过正,而且,它没有做我想要的 - 我只是想要测试覆盖率浮动,在我们动态拉取的 repos 上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2011-01-10
      • 2021-05-10
      • 2014-12-10
      • 2012-02-27
      • 2015-04-07
      • 2018-08-26
      相关资源
      最近更新 更多