Skip to content

Commit

Permalink
Created internal packages for formatters, storage and models
Browse files Browse the repository at this point in the history
  • Loading branch information
lonnblad committed Jun 28, 2020
1 parent c7d7393 commit 932e07b
Show file tree
Hide file tree
Showing 31 changed files with 991 additions and 769 deletions.
4 changes: 4 additions & 0 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ import (
"time"

"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/utils"
)

// repeats a space n times
var s = utils.S

var descFeaturesArgument = "Optional feature(s) to run. Can be:\n" +
s(4) + "- dir " + colors.Yellow("(features/)") + "\n" +
s(4) + "- feature " + colors.Yellow("(*.feature)") + "\n" +
Expand Down
3 changes: 2 additions & 1 deletion flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/formatters"
)

func TestFlagsShouldRandomizeAndGenerateSeed(t *testing.T) {
Expand Down Expand Up @@ -61,7 +62,7 @@ func TestFlagsUsageShouldIncludeFormatDescriptons(t *testing.T) {
output := colors.Uncolored(&buf)

// register some custom formatter
Format("custom", "custom format description", junitFunc)
Format("custom", "custom format description", formatters.JUnitFormatterFunc)

var opt Options
flags := FlagSet(&opt)
Expand Down
65 changes: 16 additions & 49 deletions fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,33 @@ import (
"strings"
"unicode/utf8"

"github.com/cucumber/messages-go/v10"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
internal_fmt "github.com/cucumber/godog/internal/formatters"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/storage"
)

type registeredFormatter struct {
name string
description string
fmt FormatterFunc
}

var formatters []*registeredFormatter

// FindFmt searches available formatters registered
// and returns FormaterFunc matched by given
// format name or nil otherwise
func FindFmt(name string) FormatterFunc {
for _, el := range formatters {
if el.name == name {
return el.fmt
}
}

return nil
return formatters.FindFmt(name)
}

// Format registers a feature suite output
// formatter by given name, description and
// FormatterFunc constructor function, to initialize
// formatter with the output recorder.
func Format(name, description string, f FormatterFunc) {
formatters = append(formatters, &registeredFormatter{
name: name,
fmt: f,
description: description,
})
formatters.Format(name, description, f)
}

// AvailableFormatters gives a map of all
// formatters registered with their name as key
// and description as value
func AvailableFormatters() map[string]string {
fmts := make(map[string]string, len(formatters))

for _, f := range formatters {
fmts[f.name] = f.description
}

return fmts
return formatters.AvailableFormatters()
}

// Formatter is an interface for feature runner
Expand All @@ -62,18 +42,7 @@ func AvailableFormatters() map[string]string {
// suite results in different ways. These new
// formatters needs to be registered with a
// godog.Format function call
type Formatter interface {
TestRunStarted()
Feature(*messages.GherkinDocument, string, []byte)
Pickle(*messages.Pickle)
Defined(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition)
Failed(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition, error)
Passed(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition)
Skipped(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition)
Undefined(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition)
Pending(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition)
Summary()
}
type Formatter = formatters.Formatter

// ConcurrentFormatter is an interface for a Concurrent
// version of the Formatter interface.
Expand All @@ -87,18 +56,14 @@ type ConcurrentFormatter interface {
}

type storageFormatter interface {
setStorage(*storage)
SetStorage(*storage.Storage)
}

// FormatterFunc builds a formatter with given
// suite name and io.Writer to record output
type FormatterFunc func(string, io.Writer) Formatter

func isLastStep(pickle *messages.Pickle, step *messages.Pickle_PickleStep) bool {
return pickle.Steps[len(pickle.Steps)-1].Id == step.Id
}
type FormatterFunc = formatters.FormatterFunc

func printStepDefinitions(steps []*StepDefinition, w io.Writer) {
func printStepDefinitions(steps []*models.StepDefinition, w io.Writer) {
var longest int
for _, def := range steps {
n := utf8.RuneCountInString(def.Expr.String())
Expand All @@ -109,9 +74,11 @@ func printStepDefinitions(steps []*StepDefinition, w io.Writer) {

for _, def := range steps {
n := utf8.RuneCountInString(def.Expr.String())
location := def.definitionID()
location := internal_fmt.DefinitionID(def)
spaces := strings.Repeat(" ", longest-n)
fmt.Fprintln(w, yellow(def.Expr.String())+spaces, blackb("# "+location))
fmt.Fprintln(w,
colors.Yellow(def.Expr.String())+spaces,
colors.Bold(colors.Black)("# "+location))
}

if len(steps) == 0 {
Expand Down
79 changes: 79 additions & 0 deletions formatters/fmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package formatters

import (
"io"

"github.com/cucumber/messages-go/v10"

"github.com/cucumber/godog/internal/models"
)

type registeredFormatter struct {
name string
description string
fmt FormatterFunc
}

var registeredFormatters []*registeredFormatter

// FindFmt searches available formatters registered
// and returns FormaterFunc matched by given
// format name or nil otherwise
func FindFmt(name string) FormatterFunc {
for _, el := range registeredFormatters {
if el.name == name {
return el.fmt
}
}

return nil
}

// Format registers a feature suite output
// formatter by given name, description and
// FormatterFunc constructor function, to initialize
// formatter with the output recorder.
func Format(name, description string, f FormatterFunc) {
registeredFormatters = append(registeredFormatters, &registeredFormatter{
name: name,
fmt: f,
description: description,
})
}

// AvailableFormatters gives a map of all
// formatters registered with their name as key
// and description as value
func AvailableFormatters() map[string]string {
fmts := make(map[string]string, len(registeredFormatters))

for _, f := range registeredFormatters {
fmts[f.name] = f.description
}

return fmts
}

// Formatter is an interface for feature runner
// output summary presentation.
//
// New formatters may be created to represent
// suite results in different ways. These new
// formatters needs to be registered with a
// godog.Format function call
type Formatter interface {
TestRunStarted()
Feature(*messages.GherkinDocument, string, []byte)
Pickle(*messages.Pickle)
Defined(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition)
Failed(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition, error)
Passed(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition)
Skipped(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition)
Undefined(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition)
Pending(*messages.Pickle, *messages.Pickle_PickleStep, *models.StepDefinition)
Summary()
}

// FormatterFunc builds a formatter with given
// suite name and io.Writer to record output
type FormatterFunc func(string, io.Writer) Formatter
104 changes: 104 additions & 0 deletions internal/formatters/fmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package formatters

import (
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"

"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/utils"
"github.com/cucumber/messages-go/v10"
)

var (
red = colors.Red
redb = colors.Bold(colors.Red)
green = colors.Green
blackb = colors.Bold(colors.Black)
yellow = colors.Yellow
cyan = colors.Cyan
cyanb = colors.Bold(colors.Cyan)
whiteb = colors.Bold(colors.White)
)

// repeats a space n times
var s = utils.S

var (
passed = models.Passed
failed = models.Failed
skipped = models.Skipped
undefined = models.Undefined
pending = models.Pending
)

type sortFeaturesByName []*models.Feature

func (s sortFeaturesByName) Len() int { return len(s) }
func (s sortFeaturesByName) Less(i, j int) bool { return s[i].Feature.Name < s[j].Feature.Name }
func (s sortFeaturesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

type sortPicklesByID []*messages.Pickle

func (s sortPicklesByID) Len() int { return len(s) }
func (s sortPicklesByID) Less(i, j int) bool {
iID := mustConvertStringToInt(s[i].Id)
jID := mustConvertStringToInt(s[j].Id)
return iID < jID
}
func (s sortPicklesByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

type sortPickleStepResultsByPickleStepID []models.PickleStepResult

func (s sortPickleStepResultsByPickleStepID) Len() int { return len(s) }
func (s sortPickleStepResultsByPickleStepID) Less(i, j int) bool {
iID := mustConvertStringToInt(s[i].PickleStepID)
jID := mustConvertStringToInt(s[j].PickleStepID)
return iID < jID
}
func (s sortPickleStepResultsByPickleStepID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func mustConvertStringToInt(s string) int {
i, err := strconv.Atoi(s)
if err != nil {
panic(err)
}

return i
}

// DefinitionID ...
func DefinitionID(sd *models.StepDefinition) string {
ptr := sd.HandlerValue.Pointer()
f := runtime.FuncForPC(ptr)
file, line := f.FileLine(ptr)
dir := filepath.Dir(file)

fn := strings.Replace(f.Name(), dir, "", -1)
var parts []string
for _, gr := range matchFuncDefRef.FindAllStringSubmatch(fn, -1) {
parts = append(parts, strings.Trim(gr[1], "_."))
}
if len(parts) > 0 {
// case when suite is a structure with methods
fn = strings.Join(parts, ".")
} else {
// case when steps are just plain funcs
fn = strings.Trim(fn, "_.")
}

if pkg := os.Getenv("GODOG_TESTED_PACKAGE"); len(pkg) > 0 {
fn = strings.Replace(fn, pkg, "", 1)
fn = strings.TrimLeft(fn, ".")
fn = strings.Replace(fn, "..", ".", -1)
}

return fmt.Sprintf("%s:%d -> %s", filepath.Base(file), line, fn)
}

var matchFuncDefRef = regexp.MustCompile(`\(([^\)]+)\)`)
Loading

0 comments on commit 932e07b

Please # to comment.