Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TAP output #162

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmd/commander/commander.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"github.com/commander-cli/commander/pkg/output"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -75,8 +76,8 @@ commander test commander.yaml --filter="^filter1$"
Flags: []cli.Flag{
cli.BoolFlag{
Name: "no-color",
EnvVar: "COMMANDER_NO_COLOR",
Usage: "Activate or deactivate colored output",
EnvVar: "COMMANDER_NO_COLOR",
},
cli.BoolFlag{
Name: "verbose",
Expand All @@ -95,6 +96,11 @@ commander test commander.yaml --filter="^filter1$"
Name: "filter",
Usage: `Filter tests by a given regex pattern. Tests are filtered by its title.`,
},
cli.StringFlag{
Name: "format",
Usage: `Use a different test output format. Available are: cli, tap`,
Value: output.CLI,
},
},
Action: func(c *cli.Context) error {
return app.TestCommand(c.Args().First(), app.NewTestContextFromCli(c))
Expand Down
2 changes: 2 additions & 0 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type TestCommandContext struct {
Workdir string
Concurrent int
Filters []string
Format string
}

//NewTestContextFromCli is a constructor which creates the context
Expand All @@ -30,5 +31,6 @@ func NewTestContextFromCli(c *cli.Context) TestCommandContext {
Workdir: c.String("workdir"),
Concurrent: c.Int("concurrent"),
Filters: c.StringSlice("filter"),
Format: c.String("format"),
}
}
12 changes: 8 additions & 4 deletions pkg/app/test_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/commander-cli/commander/pkg/suite"
)

var out output.OutputWriter
var out output.Output

// TestCommand executes the test argument
// testPath is the path to the test suite config, it can be a dir or file
Expand All @@ -33,14 +33,17 @@ func TestCommand(testPath string, ctx TestCommandContext) error {
log.SetOutput(os.Stdout)
}

out = output.NewCliOutput(!ctx.NoColor)
var err error
out, err = output.NewOutput(ctx.Format, !ctx.NoColor)
if err != nil {
return err
}

if testPath == "" {
testPath = CommanderFile
}

var result runtime.Result
var err error
switch {
case ctx.Dir:
fmt.Println("Starting test against directory: " + testPath + "...")
Expand All @@ -64,7 +67,8 @@ func TestCommand(testPath string, ctx TestCommandContext) error {
return fmt.Errorf(err.Error())
}

if !out.PrintSummary(result) && !ctx.Verbose {
out.PrintSummary(result)
if result.Failed != 0 && !ctx.Verbose {
return fmt.Errorf("Test suite failed, use --verbose for more detailed output")
}

Expand Down
26 changes: 13 additions & 13 deletions pkg/output/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@ import (
"github.com/logrusorgru/aurora"
)

// OutputWriter represents the output
type OutputWriter struct {
var _ Output = (*CLIOutputWriter)(nil)

// CLIOutputWriter represents the output
type CLIOutputWriter struct {
out io.Writer
au aurora.Aurora
template cliTemplate
}

// NewCliOutput creates a new OutputWriter with a stdout writer
func NewCliOutput(color bool) OutputWriter {
// NewCliOutput creates a new C̄LIOutputWriter with a stdout writer
func NewCliOutput(color bool) Output {
au := aurora.NewAurora(color)
if run.GOOS == "windows" {
au = aurora.NewAurora(false)
}

t := newCliTemplate()

return OutputWriter{
return CLIOutputWriter{
out: os.Stdout,
au: au,
template: t,
Expand All @@ -48,7 +50,7 @@ type TestResult struct {
}

// GetEventHandler create a new runtime.EventHandler
func (w *OutputWriter) GetEventHandler() *runtime.EventHandler {
func (w CLIOutputWriter) GetEventHandler() *runtime.EventHandler {
handler := runtime.EventHandler{}
handler.TestFinished = func(testResult runtime.TestResult) {
tr := convertTestResult(testResult)
Expand All @@ -64,7 +66,7 @@ func (w *OutputWriter) GetEventHandler() *runtime.EventHandler {
}

// PrintSummary prints summary
func (w *OutputWriter) PrintSummary(result runtime.Result) bool {
func (w CLIOutputWriter) PrintSummary(result runtime.Result) {
if result.Failed > 0 {
w.printFailures(result.TestResults)
}
Expand All @@ -77,24 +79,22 @@ func (w *OutputWriter) PrintSummary(result runtime.Result) bool {
} else {
w.fprintf(w.au.Green(summary))
}

return result.Failed == 0
}

// printResult prints the simple output form of a TestReault
func (w *OutputWriter) printResult(r TestResult) {
func (w CLIOutputWriter) printResult(r TestResult) {
if !r.Success {
w.fprintf(w.au.Red(w.template.testResult(r)))
return
}
w.fprintf(w.template.testResult(r))
}

func (w *OutputWriter) printSkip(r TestResult) {
func (w CLIOutputWriter) printSkip(r TestResult) {
w.fprintf(fmt.Sprintf("- [%s] %s, was skipped", r.Node, r.Title))
}

func (w *OutputWriter) printFailures(results []runtime.TestResult) {
func (w CLIOutputWriter) printFailures(results []runtime.TestResult) {
w.fprintf("")
w.fprintf(w.au.Bold("Results"))
w.fprintf(w.au.Bold(""))
Expand All @@ -118,7 +118,7 @@ func (w *OutputWriter) printFailures(results []runtime.TestResult) {
}
}

func (w *OutputWriter) fprintf(a ...interface{}) {
func (w CLIOutputWriter) fprintf(a ...interface{}) {
if _, err := fmt.Fprintln(w.out, a...); err != nil {
log.Fatal(err)
}
Expand Down
20 changes: 11 additions & 9 deletions pkg/output/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func Test_NewCliOutput(t *testing.T) {
got := NewCliOutput(true)
assert.IsType(t, OutputWriter{}, got)
assert.IsType(t, CLIOutputWriter{}, got)
}

func Test_GetEventHandler(t *testing.T) {
Expand All @@ -22,8 +22,9 @@ func Test_GetEventHandler(t *testing.T) {

func Test_EventHandlerTestFinished(t *testing.T) {
var buf bytes.Buffer
writer := NewCliOutput(true)
writer.out = &buf
writer := CLIOutputWriter{
out: &buf,
}
eh := writer.GetEventHandler()

testResults := createFakeTestResults()
Expand All @@ -39,8 +40,9 @@ func Test_EventHandlerTestFinished(t *testing.T) {

func Test_EventHandlerTestSkipped(t *testing.T) {
var buf bytes.Buffer
writer := NewCliOutput(true)
writer.out = &buf
writer := CLIOutputWriter{
out: &buf,
}
eh := writer.GetEventHandler()

testResults := createFakeTestResults()
Expand All @@ -62,11 +64,11 @@ func Test_PrintSummary(t *testing.T) {
}

var buf bytes.Buffer
writer := NewCliOutput(true)
writer.out = &buf
writer := CLIOutputWriter{
out: &buf,
}

outResult := writer.PrintSummary(r)
assert.False(t, outResult)
writer.PrintSummary(r)

output := buf.String()
assert.Contains(t, output, "✗ [192.168.0.1] 'Failed test', on property 'Stdout'")
Expand Down
28 changes: 28 additions & 0 deletions pkg/output/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package output

import (
"errors"
"fmt"
"github.com/commander-cli/commander/pkg/runtime"
)

const (
TAP = "tap"
CLI = "cli"
)

type Output interface {
GetEventHandler() *runtime.EventHandler
PrintSummary(result runtime.Result)
}

// NewOutput creates a new output
func NewOutput(format string, color bool) (Output, error) {
switch format {
case TAP:
return NewTAPOutputWriter(), nil
case CLI:
return NewCliOutput(color), nil
}
return nil, errors.New(fmt.Sprintf("Invalid format type %s", format))
}
13 changes: 13 additions & 0 deletions pkg/output/output_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package output

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestNewOutput(t *testing.T) {
var o Output
o, err := NewOutput(CLI, false)
assert.NoError(t, err)
assert.Implements(t, (*Output)(nil), o)
}
52 changes: 52 additions & 0 deletions pkg/output/tap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package output

import (
"fmt"
"github.com/commander-cli/commander/pkg/runtime"
"io"
"log"
"os"
)

var _ Output = (*CLIOutputWriter)(nil)

// TAPOutputWriter writes TAP results
type TAPOutputWriter struct {
out io.Writer
}

// NewTAPOutputWriter represents the output, defaults to stdout
func NewTAPOutputWriter() Output {
return TAPOutputWriter{
out: os.Stdout,
}
}

func (w TAPOutputWriter) GetEventHandler() *runtime.EventHandler {
return runtime.NewEmptyEventHandler()
}

func (w TAPOutputWriter) PrintSummary(result runtime.Result) {
counter := 0
for _, r := range result.TestResults {
if r.Skipped {
// skipped tests are not specified in the TAP specification
continue
}

counter++
if r.FailedProperty != "" {
w.fprintf("%d ok - %s", counter+1, r.TestCase.Title)
} else {
w.fprintf("%d not ok - %s", counter+1, r.TestCase.Title)
}
}

w.fprintf("1..%d", counter)
}

func (w TAPOutputWriter) fprintf(msg string , a ...interface{}) {
if _, err := fmt.Fprintln(w.out, fmt.Sprintf(msg, a...)); err != nil {
log.Fatal(err)
}
}
10 changes: 9 additions & 1 deletion pkg/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type TestResult struct {
Skipped bool
}

// Result respresents the aggregation of all TestResults/summary of a runtime
// Result represents the aggregation of all TestResults/summary of a runtime
type Result struct {
TestResults []TestResult
Duration time.Duration
Expand Down Expand Up @@ -166,3 +166,11 @@ func (r *Runtime) Start(tests []TestCase) Result {

return result
}

// NewEmptyEventHandler returns an event handler with empty implementations
func NewEmptyEventHandler() *EventHandler {
return &EventHandler{
TestFinished: func(result TestResult) {},
TestSkipped: func(result TestResult) {},
}
}