Use multiple formatters in the same test run

Этот коммит содержится в:
Viacheslav Poturaev 2021-05-30 22:11:44 +02:00
родитель 60e2e2f4df
коммит 9d4b221f7a
2 изменённых файлов: 174 добавлений и 32 удалений

133
internal/formatters/fmt_multi.go Обычный файл
Просмотреть файл

@ -0,0 +1,133 @@
package formatters
import (
"io"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/storage"
"github.com/cucumber/messages-go/v10"
)
// MultiFormatter passes test progress to multiple formatters.
type MultiFormatter struct {
formatters []formatter
repeater repeater
}
type formatter struct {
fmt formatters.FormatterFunc
out io.Writer
close bool
}
type repeater []formatters.Formatter
type storageFormatter interface {
SetStorage(s *storage.Storage)
}
// SetStorage passes storage to all added formatters.
func (r repeater) SetStorage(s *storage.Storage) {
for _, f := range r {
if ss, ok := f.(storageFormatter); ok {
ss.SetStorage(s)
}
}
}
// TestRunStarted triggers TestRunStarted for all added formatters.
func (r repeater) TestRunStarted() {
for _, f := range r {
f.TestRunStarted()
}
}
// Feature triggers Feature for all added formatters.
func (r repeater) Feature(document *messages.GherkinDocument, s string, bytes []byte) {
for _, f := range r {
f.Feature(document, s, bytes)
}
}
// Pickle triggers Pickle for all added formatters.
func (r repeater) Pickle(pickle *messages.Pickle) {
for _, f := range r {
f.Pickle(pickle)
}
}
// Defined triggers Defined for all added formatters.
func (r repeater) Defined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
for _, f := range r {
f.Defined(pickle, step, definition)
}
}
// Failed triggers Failed for all added formatters.
func (r repeater) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition, err error) {
for _, f := range r {
f.Failed(pickle, step, definition, err)
}
}
// Passed triggers Passed for all added formatters.
func (r repeater) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
for _, f := range r {
f.Passed(pickle, step, definition)
}
}
// Skipped triggers Skipped for all added formatters.
func (r repeater) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
for _, f := range r {
f.Skipped(pickle, step, definition)
}
}
// Undefined triggers Undefined for all added formatters.
func (r repeater) Undefined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
for _, f := range r {
f.Undefined(pickle, step, definition)
}
}
// Pending triggers Pending for all added formatters.
func (r repeater) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleStep, definition *formatters.StepDefinition) {
for _, f := range r {
f.Pending(pickle, step, definition)
}
}
// Summary triggers Summary for all added formatters.
func (r repeater) Summary() {
for _, f := range r {
f.Summary()
}
}
// Add adds formatter with output writer.
func (m *MultiFormatter) Add(name string, out io.Writer) {
f := formatters.FindFmt(name)
if f == nil {
panic("formatter not found: " + name)
}
m.formatters = append(m.formatters, formatter{
fmt: f,
out: out,
})
}
// FormatterFunc implements the FormatterFunc for the multi formatter.
func (m *MultiFormatter) FormatterFunc(suite string, out io.Writer) formatters.Formatter {
for _, f := range m.formatters {
out := out
if f.out != nil {
out = f.out
}
m.repeater = append(m.repeater, f.fmt(suite, out))
}
return m.repeater
}

47
run.go
Просмотреть файл

@ -16,6 +16,7 @@ import (
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
ifmt "github.com/cucumber/godog/internal/formatters"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/parser"
"github.com/cucumber/godog/internal/storage"
@ -141,7 +142,13 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
output = opt.Output
}
if formatterParts := strings.SplitN(opt.Format, ":", 2); len(formatterParts) > 1 {
multiFmt := ifmt.MultiFormatter{}
for _, formatter := range strings.Split(opt.Format, ",") {
out := output
formatterParts := strings.SplitN(formatter, ":", 2)
if len(formatterParts) > 1 {
f, err := os.Create(formatterParts[1])
if err != nil {
err = fmt.Errorf(
@ -155,14 +162,29 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
defer f.Close()
output = f
opt.Format = formatterParts[0]
out = f
}
if opt.NoColors {
output = colors.Uncolored(output)
out = colors.Uncolored(out)
} else {
output = colors.Colored(output)
out = colors.Colored(out)
}
if nil == formatters.FindFmt(formatterParts[0]) {
var names []string
for name := range formatters.AvailableFormatters() {
names = append(names, name)
}
fmt.Fprintln(os.Stderr, fmt.Errorf(
`unregistered formatter name: "%s", use one of: %s`,
opt.Format,
strings.Join(names, ", "),
))
return exitOptionError
}
multiFmt.Add(formatterParts[0], out)
}
if opt.ShowStepDefinitions {
@ -184,20 +206,7 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
opt.Concurrency = 1
}
formatter := formatters.FindFmt(opt.Format)
if nil == formatter {
var names []string
for name := range formatters.AvailableFormatters() {
names = append(names, name)
}
fmt.Fprintln(os.Stderr, fmt.Errorf(
`unregistered formatter name: "%s", use one of: %s`,
opt.Format,
strings.Join(names, ", "),
))
return exitOptionError
}
runner.fmt = formatter(suiteName, output)
runner.fmt = multiFmt.FormatterFunc(suiteName, output)
var err error
if runner.features, err = parser.ParseFeatures(opt.Tags, opt.Paths); err != nil {