Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle -outputdir flag #364

Merged
merged 14 commits into from
Jul 21, 2017
75 changes: 75 additions & 0 deletions ginkgo/run_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/onsi/ginkgo/ginkgo/interrupthandler"
"github.com/onsi/ginkgo/ginkgo/testrunner"
"github.com/onsi/ginkgo/types"
"io/ioutil"
"path/filepath"
)

func BuildRunCommand() *Command {
Expand Down Expand Up @@ -100,6 +102,18 @@ func (r *SpecRunner) RunSpecs(args []string, additionalArgs []string) {
runResult, numSuites = r.suiteRunner.RunSuites(randomizedRunners, r.commandFlags.NumCompilers, r.commandFlags.KeepGoing, nil)
}

if r.isInCoverageMode() {
if r.getOutputDir() != "" {
// If coverprofile is set, combine coverages
if r.getCoverprofile() != "" {
r.combineCoverprofiles(runners)
} else {
// Just move them
r.moveCoverprofiles(runners)
}
}
}

for _, runner := range runners {
runner.CleanUp()
}
Expand All @@ -121,6 +135,67 @@ func (r *SpecRunner) RunSpecs(args []string, additionalArgs []string) {
}
}

// Moves all generated profiles to specified directory
func (r *SpecRunner) moveCoverprofiles(runners []*testrunner.TestRunner) {
for _, runner := range runners {
_, filename := filepath.Split(runner.CoverageFile)
err := os.Rename(runner.CoverageFile, filepath.Join(r.getOutputDir(), filename))

if err != nil {
fmt.Printf("Unable to move coverprofile %s, %v\n", runner.CoverageFile, err)
return
}
}
}

// Combines all generated profiles in the specified directory
func (r *SpecRunner) combineCoverprofiles(runners []*testrunner.TestRunner) {

path, _ := filepath.Abs(r.getOutputDir())

fmt.Println("path is " + path)
os.MkdirAll(path, os.ModePerm)

combined, err := os.OpenFile(filepath.Join(path, r.getCoverprofile()),
os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)

if err != nil {
fmt.Printf("Unable to create combined profile, %v\n", err)
return
}

for _, runner := range runners {
contents, err := ioutil.ReadFile(runner.CoverageFile)

if err != nil {
fmt.Printf("Unable to read coverage file %s to combine, %v\n", runner.CoverageFile, err)
return
}

_, err = combined.Write(contents)

if err != nil {
fmt.Printf("Unable to append to coverprofile, %v\n", err)
return
}
}

fmt.Println("All profiles combined")
}

func (r *SpecRunner) isInCoverageMode() bool {
opts := r.commandFlags.GoOpts
return *opts["cover"].(*bool) || *opts["coverpkg"].(*string) != "" || *opts["covermode"].(*string) != ""
}

func (r *SpecRunner) getCoverprofile() string {
return *r.commandFlags.GoOpts["coverprofile"].(*string)
}

func (r *SpecRunner) getOutputDir() string {
return *r.commandFlags.GoOpts["outputdir"].(*string)
}

func (r *SpecRunner) ComputeSuccinctMode(numSuites int) {
if config.DefaultReporterConfig.Verbose {
config.DefaultReporterConfig.Succinct = false
Expand Down
63 changes: 47 additions & 16 deletions ginkgo/testrunner/test_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type TestRunner struct {
goOpts map[string]interface{}
additionalArgs []string
stderr *bytes.Buffer

CoverageFile string
}

func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, timeout time.Duration, goOpts map[string]interface{}, additionalArgs []string) *TestRunner {
Expand Down Expand Up @@ -63,10 +65,10 @@ func (t *TestRunner) Compile() error {
func (t *TestRunner) BuildArgs(path string) []string {
args := []string{"test", "-c", "-i", "-o", path, t.Suite.Path}

if *t.goOpts["covermode"].(*string) != "" {
args = append(args, "-cover", fmt.Sprintf("-covermode=%s", *t.goOpts["covermode"].(*string)))
if t.getCoverMode() != "" {
args = append(args, "-cover", fmt.Sprintf("-covermode=%s", t.getCoverMode()))
} else {
if *t.goOpts["cover"].(*bool) || *t.goOpts["coverpkg"].(*string) != "" {
if t.shouldCover() || t.getCoverPackage() != "" {
args = append(args, "-cover", "-covermode=atomic")
}
}
Expand Down Expand Up @@ -298,7 +300,7 @@ func (t *TestRunner) runAndStreamParallelGinkgoSuite() RunResult {

os.Stdout.Sync()

if *t.goOpts["cover"].(*bool) || *t.goOpts["coverpkg"].(*string) != "" || *t.goOpts["covermode"].(*string) != "" {
if t.shouldCombineCoverprofiles() {
t.combineCoverprofiles()
}

Expand Down Expand Up @@ -380,7 +382,7 @@ func (t *TestRunner) runParallelGinkgoSuite() RunResult {
os.Stdout.Sync()
}

if *t.goOpts["cover"].(*bool) || *t.goOpts["coverpkg"].(*string) != "" || *t.goOpts["covermode"].(*string) != "" {
if t.shouldCombineCoverprofiles() {
t.combineCoverprofiles()
}

Expand All @@ -392,21 +394,24 @@ const CoverProfileSuffix = ".coverprofile"
func (t *TestRunner) cmd(ginkgoArgs []string, stream io.Writer, node int) *exec.Cmd {
args := []string{"--test.timeout=" + t.timeout.String()}

coverMode := *t.goOpts["covermode"].(*string)
coverPackage := *t.goOpts["coverpkg"].(*string)
cover := *t.goOpts["cover"].(*bool)
coverProfile := *t.goOpts["coverprofile"].(*string)
coverProfile := t.getCoverProfile()

if t.shouldCombineCoverprofiles() {

if cover || coverPackage != "" || coverMode != "" {
testCoverProfile := "--test.coverprofile="

coverageFile := ""
// Set default name for coverage results
if coverProfile == "" {
testCoverProfile += t.Suite.PackageName + CoverProfileSuffix
coverageFile = t.Suite.PackageName + CoverProfileSuffix
} else {
testCoverProfile += coverProfile
coverageFile = coverProfile
}

testCoverProfile += coverageFile

t.CoverageFile = filepath.Join(t.Suite.Path, coverageFile)

if t.numCPU > 1 {
testCoverProfile = fmt.Sprintf("%s.%d", testCoverProfile, node)
}
Expand All @@ -430,6 +435,30 @@ func (t *TestRunner) cmd(ginkgoArgs []string, stream io.Writer, node int) *exec.
return cmd
}

func (t *TestRunner) shouldCover() bool {
return *t.goOpts["cover"].(*bool)
}

func (t *TestRunner) shouldRequireSuite() bool {
return *t.goOpts["requireSuite"].(*bool)
}

func (t *TestRunner) getCoverProfile() string {
return *t.goOpts["coverprofile"].(*string)
}

func (t *TestRunner) getCoverPackage() string {
return *t.goOpts["coverpkg"].(*string)
}

func (t *TestRunner) getCoverMode() string {
return *t.goOpts["covermode"].(*string)
}

func (t *TestRunner) shouldCombineCoverprofiles() bool {
return t.shouldCover() || t.getCoverPackage() != "" || t.getCoverMode() != ""
}

func (t *TestRunner) run(cmd *exec.Cmd, completions chan RunResult) RunResult {
var res RunResult

Expand All @@ -452,7 +481,7 @@ func (t *TestRunner) run(cmd *exec.Cmd, completions chan RunResult) RunResult {
res.HasProgrammaticFocus = (exitStatus == types.GINKGO_FOCUS_EXIT_CODE)

if strings.Contains(t.stderr.String(), "warning: no tests to run") {
if *t.goOpts["requireSuite"].(*bool) {
if t.shouldRequireSuite() {
res.Passed = false
}
fmt.Fprintf(os.Stderr, `Found no test suites, did you forget to run "ginkgo bootstrap"?`)
Expand All @@ -464,7 +493,7 @@ func (t *TestRunner) run(cmd *exec.Cmd, completions chan RunResult) RunResult {
func (t *TestRunner) combineCoverprofiles() {
profiles := []string{}

coverProfile := *t.goOpts["coverprofile"].(*string)
coverProfile := t.getCoverProfile()

for cpu := 1; cpu <= t.numCPU; cpu++ {
var coverFile string
Expand Down Expand Up @@ -518,6 +547,8 @@ func (t *TestRunner) combineCoverprofiles() {
finalFilename = fmt.Sprintf("%s%s", t.Suite.PackageName, CoverProfileSuffix)
}

ioutil.WriteFile(filepath.Join(t.Suite.Path, finalFilename),
[]byte(finalOutput), 0666)
coverageFilepath := filepath.Join(t.Suite.Path, finalFilename)
ioutil.WriteFile(coverageFilepath, []byte(finalOutput), 0666)

t.CoverageFile = coverageFilepath
}
53 changes: 52 additions & 1 deletion integration/coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"os"
"os/exec"

"fmt"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
"fmt"
)

var _ = Describe("Coverage Specs", func() {
Expand Down Expand Up @@ -97,4 +97,55 @@ var _ = Describe("Coverage Specs", func() {
// Cleanup
os.RemoveAll(coverFile)
})

It("Appends coverages if output dir and coverprofile were set", func() {
session := startGinkgo("./_fixtures/combined_coverage_fixture", "-outputdir=./", "-r", "-cover", "-coverprofile=coverage.txt")

Eventually(session).Should(gexec.Exit(0))

_, err := os.Stat("./_fixtures/combined_coverage_fixture/coverage.txt")

Ω(err).ShouldNot(HaveOccurred())

// Cleanup
os.RemoveAll("./_fixtures/combined_coverage_fixture/coverage.txt")
})

It("Creates directories in path if they don't exist", func() {
session := startGinkgo("./_fixtures/combined_coverage_fixture", "-outputdir=./all/profiles/here", "-r", "-cover", "-coverprofile=coverage.txt")

defer os.RemoveAll("./_fixtures/combined_coverage_fixture/all")
defer os.RemoveAll("./_fixtures/combined_coverage_fixture/coverage.txt")

Eventually(session).Should(gexec.Exit(0))

_, err := os.Stat("./_fixtures/combined_coverage_fixture/all/profiles/here/coverage.txt")

Ω(err).ShouldNot(HaveOccurred())
})

It("Moves coverages if only output dir was set", func() {
session := startGinkgo("./_fixtures/combined_coverage_fixture", "-outputdir=./", "-r", "-cover")

Eventually(session).Should(gexec.Exit(0))

packages := []string{"first_package", "second_package"}

for _, p := range packages {
coverFile := fmt.Sprintf("./_fixtures/combined_coverage_fixture/%s.coverprofile", p)

// Cleanup
defer func (f string) {
os.RemoveAll(f)
} (coverFile)

defer func (f string) {
os.RemoveAll(fmt.Sprintf("./_fixtures/combined_coverage_fixture/%s/coverage.txt", f))
} (p)

_, err := os.Stat(coverFile)

Ω(err).ShouldNot(HaveOccurred())
}
})
})