Skip to content

Commit

Permalink
run tests in parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensayshi committed May 11, 2021
1 parent 3615d9a commit 7e51472
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ All the output from the `go test -v` command is shown.

Reports each test (package) being ran.

### Parallel: -p
`Run test in parallel`

Run multiple test (packages) in parallel, similar to `go test -p`.

# Output
Courtney will fail if the tests fail. If the tests succeed, it will create or
overwrite a `coverage.out` file in the current directory.
Expand Down
2 changes: 2 additions & 0 deletions courtney.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func main() {
enforceFlag := flag.Bool("e", false, "Enforce 100% code coverage")
verboseFlag := flag.Bool("v", false, "Verbose output")
reportFlag := flag.Bool("r", false, "Print each package being tested")
parallelFlag := flag.Int("p", 1, "Run multiple tests in parallel")
shortFlag := flag.Bool("short", false, "Pass the short flag to the go test command")
timeoutFlag := flag.String("timeout", "", "Pass the timeout flag to the go test command")
outputFlag := flag.String("o", "", "Override coverage file location")
Expand Down Expand Up @@ -54,6 +55,7 @@ func main() {
setup := &shared.Setup{
Env: env,
Paths: patsy.NewCache(env),
Parallel: *parallelFlag,
Enforce: *enforceFlag,
Verbose: *verboseFlag,
ReportTestRun: *reportFlag,
Expand Down
1 change: 1 addition & 0 deletions shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
type Setup struct {
Env vos.Env
Paths *patsy.Cache
Parallel int
Enforce bool
Verbose bool
ReportTestRun bool
Expand Down
58 changes: 55 additions & 3 deletions tester/tester.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tester

import (
"context"
"crypto/md5"
"fmt"
"io/ioutil"
Expand All @@ -9,6 +10,7 @@ import (
"path/filepath"
"regexp"
"strings"
"sync"

"github.com/dave/courtney/shared"
"github.com/dave/courtney/tester/logger"
Expand All @@ -29,6 +31,7 @@ func New(setup *shared.Setup) *Tester {
type Tester struct {
setup *shared.Setup
cover string
mu sync.Mutex
Results []*cover.Profile
}

Expand Down Expand Up @@ -60,14 +63,60 @@ func (t *Tester) Test() error {
excludes[s] = true
}

ctx, closeCtx := context.WithCancel(context.Background())

// run parallel worker routines to process dirs
parallel := t.setup.Parallel
if parallel < 1 {
parallel = 1
}
work := make(chan string, len(t.setup.Packages))
done := make(chan error, parallel)
for i := 0; i < parallel; i++ {
go func() {
for {
select {
case <-ctx.Done():
done <- nil
return

case dir := <-work:
// when channel is empty and closed we'll get a zero value
if dir == "" {
done <- nil
return
}

if err := t.processDir(dir); err != nil {
done <- err
return
}
}
}
}()
}

for _, spec := range t.setup.Packages {
if !excludes[spec.Path] {
if err := t.processDir(spec.Dir); err != nil {
return err
}
work <- spec.Dir
}
}

// close work channel, the worker routines can continue reading but will get a zero value when out of work
close(work)

// wait for all workers to be done, if any of them error then we return the first error received
for i := 0; i < parallel; i++ {
err := <-done
if err != nil {
// close ctx to prevent the worker routines from processing anymore
closeCtx()
return err
}
}

closeCtx()

return nil
}

Expand Down Expand Up @@ -284,6 +333,9 @@ func (t *Tester) processDir(dir string) error {
}

func (t *Tester) processCoverageFile(filename string) error {
t.mu.Lock()
defer t.mu.Unlock()

profiles, err := cover.ParseProfiles(filename)
if err != nil {
return err
Expand Down

0 comments on commit 7e51472

Please sign in to comment.