Suppose we want to get the percentage of test coverage (like float64) in the project, which we dynamically extract from the git repository somewhere and save it in the current folder in the "_repos / src" section. The input will be a project in the typical "get get" format. We need to run "go test -cover", with the appropriate set of GOPATH, analyze the output and extract the actual percentage of test coverage. With the current Go 1.9 testing tool, the code below achieves this.
// 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 }
marni source share