fix for progress printing with concurrency mode
Этот коммит содержится в:
родитель
0d22f34c56
коммит
652eedf03a
3 изменённых файлов: 71 добавлений и 23 удалений
|
@ -15,6 +15,7 @@ func init() {
|
|||
}
|
||||
|
||||
func progressFunc(suite string, out io.Writer) Formatter {
|
||||
steps := 0
|
||||
return &progress{
|
||||
basefmt: basefmt{
|
||||
started: timeNowFunc(),
|
||||
|
@ -22,35 +23,37 @@ func progressFunc(suite string, out io.Writer) Formatter {
|
|||
out: out,
|
||||
},
|
||||
stepsPerRow: 70,
|
||||
lock: new(sync.Mutex),
|
||||
steps: &steps,
|
||||
}
|
||||
}
|
||||
|
||||
type progress struct {
|
||||
basefmt
|
||||
sync.Mutex
|
||||
lock *sync.Mutex
|
||||
stepsPerRow int
|
||||
steps int
|
||||
steps *int
|
||||
}
|
||||
|
||||
func (f *progress) Node(n interface{}) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Node(n)
|
||||
}
|
||||
|
||||
func (f *progress) Feature(ft *gherkin.Feature, p string, c []byte) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Feature(ft, p, c)
|
||||
}
|
||||
|
||||
func (f *progress) Summary() {
|
||||
left := math.Mod(float64(f.steps), float64(f.stepsPerRow))
|
||||
left := math.Mod(float64(*f.steps), float64(f.stepsPerRow))
|
||||
if left != 0 {
|
||||
if f.steps > f.stepsPerRow {
|
||||
fmt.Fprintf(f.out, s(f.stepsPerRow-int(left))+fmt.Sprintf(" %d\n", f.steps))
|
||||
if *f.steps > f.stepsPerRow {
|
||||
fmt.Fprintf(f.out, s(f.stepsPerRow-int(left))+fmt.Sprintf(" %d\n", *f.steps))
|
||||
} else {
|
||||
fmt.Fprintf(f.out, " %d\n", f.steps)
|
||||
fmt.Fprintf(f.out, " %d\n", *f.steps)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(f.out, "")
|
||||
|
@ -79,43 +82,43 @@ func (f *progress) step(res *stepResult) {
|
|||
case pending:
|
||||
fmt.Fprint(f.out, yellow("P"))
|
||||
}
|
||||
f.steps++
|
||||
if math.Mod(float64(f.steps), float64(f.stepsPerRow)) == 0 {
|
||||
fmt.Fprintf(f.out, " %d\n", f.steps)
|
||||
*f.steps++
|
||||
if math.Mod(float64(*f.steps), float64(f.stepsPerRow)) == 0 {
|
||||
fmt.Fprintf(f.out, " %d\n", *f.steps)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *progress) Passed(step *gherkin.Step, match *StepDef) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Passed(step, match)
|
||||
f.step(f.passed[len(f.passed)-1])
|
||||
}
|
||||
|
||||
func (f *progress) Skipped(step *gherkin.Step, match *StepDef) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Skipped(step, match)
|
||||
f.step(f.skipped[len(f.skipped)-1])
|
||||
}
|
||||
|
||||
func (f *progress) Undefined(step *gherkin.Step, match *StepDef) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Undefined(step, match)
|
||||
f.step(f.undefined[len(f.undefined)-1])
|
||||
}
|
||||
|
||||
func (f *progress) Failed(step *gherkin.Step, match *StepDef, err error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Failed(step, match, err)
|
||||
f.step(f.failed[len(f.failed)-1])
|
||||
}
|
||||
|
||||
func (f *progress) Pending(step *gherkin.Step, match *StepDef) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.basefmt.Pending(step, match)
|
||||
f.step(f.pending[len(f.pending)-1])
|
||||
}
|
||||
|
|
8
run.go
8
run.go
|
@ -61,6 +61,14 @@ func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool
|
|||
if useFmtCopy {
|
||||
fmtCopy = formatterFn()
|
||||
suite.fmt = fmtCopy
|
||||
|
||||
// sync lock and steps for progress printing
|
||||
if sf, ok := suite.fmt.(*progress); ok {
|
||||
if rf, ok := r.fmt.(*progress); ok {
|
||||
sf.lock = rf.lock
|
||||
sf.steps = rf.steps
|
||||
}
|
||||
}
|
||||
} else {
|
||||
suite.fmt = r.fmt
|
||||
}
|
||||
|
|
37
run_test.go
37
run_test.go
|
@ -275,3 +275,40 @@ func TestFeatureFilePathParser(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSucceedWithConcurrencyOption(t *testing.T) {
|
||||
output := new(bytes.Buffer)
|
||||
|
||||
opt := Options{
|
||||
Format: "progress",
|
||||
NoColors: true,
|
||||
Paths: []string{"features"},
|
||||
Concurrency: 2,
|
||||
Output: output,
|
||||
}
|
||||
|
||||
expectedOutput := `...................................................................... 70
|
||||
...................................................................... 140
|
||||
...................................................................... 210
|
||||
....................................... 249
|
||||
|
||||
|
||||
60 scenarios (60 passed)
|
||||
249 steps (249 passed)
|
||||
0s`
|
||||
|
||||
status := RunWithOptions("succeed", func(s *Suite) { SuiteContext(s) }, opt)
|
||||
if status != exitSuccess {
|
||||
t.Fatalf("expected exit status to be 0, but was: %d", status)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out := strings.TrimSpace(string(b))
|
||||
if out != expectedOutput {
|
||||
t.Fatalf("unexpected output: \"%s\"", out)
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче