Use multiple formatters in the same test run
Этот коммит содержится в:
родитель
60e2e2f4df
коммит
9d4b221f7a
2 изменённых файлов: 174 добавлений и 32 удалений
133
internal/formatters/fmt_multi.go
Обычный файл
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
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 {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче