mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
e2e/cli: implemented run logic
This commit is contained in:
232
e2e/cli/command/test_decoder.go
Normal file
232
e2e/cli/command/test_decoder.go
Normal file
@@ -0,0 +1,232 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type EventDecoder struct {
|
||||
r io.Reader
|
||||
|
||||
dec *json.Decoder
|
||||
report *TestReport
|
||||
}
|
||||
|
||||
type TestReport struct {
|
||||
Events []*TestEvent
|
||||
Suites map[string]*TestSuite
|
||||
TotalSuites int
|
||||
TotalFailedSuites int
|
||||
TotalCases int
|
||||
TotalFailedCases int
|
||||
TotalTests int
|
||||
TotalFailedTests int
|
||||
Elapsed float64
|
||||
Output []string
|
||||
}
|
||||
|
||||
type TestEvent struct {
|
||||
Time time.Time // encodes as an RFC3339-format string
|
||||
Action string
|
||||
Package string
|
||||
Test string
|
||||
Elapsed float64 // seconds
|
||||
Output string
|
||||
|
||||
eventType string
|
||||
suiteName string
|
||||
caseName string
|
||||
testName string
|
||||
}
|
||||
|
||||
type TestSuite struct {
|
||||
Name string
|
||||
Cases map[string]*TestCase
|
||||
Failed int
|
||||
Elapsed float64
|
||||
Output []string
|
||||
}
|
||||
|
||||
type TestCase struct {
|
||||
Name string
|
||||
Tests map[string]*Test
|
||||
Failed int
|
||||
Elapsed float64
|
||||
Output []string
|
||||
}
|
||||
|
||||
type Test struct {
|
||||
Name string
|
||||
Output []string
|
||||
Failed bool
|
||||
Elapsed float64
|
||||
}
|
||||
|
||||
func NewDecoder(r io.Reader) *EventDecoder {
|
||||
return &EventDecoder{
|
||||
r: r,
|
||||
dec: json.NewDecoder(r),
|
||||
report: &TestReport{
|
||||
Suites: map[string]*TestSuite{},
|
||||
Events: []*TestEvent{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *EventDecoder) Decode(logger io.Writer) (*TestReport, error) {
|
||||
for d.dec.More() {
|
||||
var e TestEvent
|
||||
err := d.dec.Decode(&e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.report.record(&e)
|
||||
if logger != nil {
|
||||
logger.Write([]byte(e.Output))
|
||||
}
|
||||
}
|
||||
return d.report, nil
|
||||
}
|
||||
|
||||
func (r *TestReport) record(event *TestEvent) {
|
||||
if !strings.HasPrefix(event.Test, "TestE2E") {
|
||||
return
|
||||
}
|
||||
parts := strings.Split(event.Test, "/")
|
||||
switch len(parts) {
|
||||
case 1:
|
||||
r.recordRoot(event)
|
||||
case 2:
|
||||
event.suiteName = parts[1]
|
||||
r.recordSuite(event)
|
||||
case 3:
|
||||
event.suiteName = parts[1]
|
||||
event.caseName = parts[2]
|
||||
r.recordCase(event, r.Suites[event.suiteName])
|
||||
case 4:
|
||||
event.suiteName = parts[1]
|
||||
event.caseName = parts[2]
|
||||
event.testName = strings.Join(parts[3:], "/")
|
||||
suite := r.Suites[event.suiteName]
|
||||
r.recordTest(event, suite, suite.Cases[event.caseName])
|
||||
}
|
||||
r.Events = append(r.Events, event)
|
||||
|
||||
}
|
||||
|
||||
func (r *TestReport) recordRoot(event *TestEvent) {
|
||||
switch event.Action {
|
||||
case "run":
|
||||
case "output":
|
||||
r.Output = append(r.Output, event.Output)
|
||||
case "pass", "fail":
|
||||
r.Elapsed = event.Elapsed
|
||||
}
|
||||
}
|
||||
func (r *TestReport) recordSuite(event *TestEvent) {
|
||||
switch event.Action {
|
||||
case "run":
|
||||
r.Suites[event.suiteName] = &TestSuite{
|
||||
Name: event.suiteName,
|
||||
Cases: map[string]*TestCase{},
|
||||
}
|
||||
r.TotalSuites += 1
|
||||
case "output":
|
||||
r.Suites[event.suiteName].Output = append(r.Suites[event.suiteName].Output, event.Output)
|
||||
case "pass":
|
||||
r.Suites[event.suiteName].Elapsed = event.Elapsed
|
||||
case "fail":
|
||||
r.Suites[event.suiteName].Elapsed = event.Elapsed
|
||||
r.TotalFailedSuites += 1
|
||||
}
|
||||
}
|
||||
func (r *TestReport) recordCase(event *TestEvent, suite *TestSuite) {
|
||||
switch event.Action {
|
||||
case "run":
|
||||
suite.Cases[event.caseName] = &TestCase{
|
||||
Name: event.caseName,
|
||||
Tests: map[string]*Test{},
|
||||
}
|
||||
r.TotalCases += 1
|
||||
case "output":
|
||||
suite.Cases[event.caseName].Output = append(suite.Cases[event.caseName].Output, event.Output)
|
||||
case "pass":
|
||||
suite.Cases[event.caseName].Elapsed = event.Elapsed
|
||||
case "fail":
|
||||
suite.Cases[event.caseName].Elapsed = event.Elapsed
|
||||
suite.Failed += 1
|
||||
r.TotalFailedCases += 1
|
||||
}
|
||||
}
|
||||
func (r *TestReport) recordTest(event *TestEvent, suite *TestSuite, c *TestCase) {
|
||||
switch event.Action {
|
||||
case "run":
|
||||
c.Tests[event.testName] = &Test{
|
||||
Name: event.testName,
|
||||
}
|
||||
r.TotalTests += 1
|
||||
case "output":
|
||||
c.Tests[event.testName].Output = append(c.Tests[event.testName].Output, event.Output)
|
||||
case "pass":
|
||||
c.Tests[event.testName].Elapsed = event.Elapsed
|
||||
case "fail":
|
||||
c.Tests[event.testName].Elapsed = event.Elapsed
|
||||
c.Tests[event.testName].Failed = true
|
||||
c.Failed += 1
|
||||
r.TotalFailedTests += 1
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TestReport) Summary() string {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
red := color.New(color.FgRed).SprintFunc()
|
||||
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(
|
||||
fmt.Sprintf("Summary: %v/%v suites failed | %v/%v cases failed | %v/%v tests failed\n",
|
||||
r.TotalFailedSuites, r.TotalSuites,
|
||||
r.TotalFailedCases, r.TotalCases,
|
||||
r.TotalFailedTests, r.TotalTests))
|
||||
|
||||
sb.WriteString("Details:\n")
|
||||
w := tabwriter.NewWriter(&sb, 0, 0, 1, ' ', tabwriter.AlignRight)
|
||||
for sname, suite := range r.Suites {
|
||||
status := red("FAIL")
|
||||
if suite.Failed == 0 {
|
||||
status = green("PASS")
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "[%s]\t%s\t\t\t (%vs)\n", status, sname, suite.Elapsed)
|
||||
for cname, c := range suite.Cases {
|
||||
status := red("FAIL")
|
||||
if c.Failed == 0 {
|
||||
status = green("PASS")
|
||||
}
|
||||
fmt.Fprintf(w, "[%s]\t↳\t%s\t\t (%vs)\n", status, cname, c.Elapsed)
|
||||
for tname, test := range c.Tests {
|
||||
status := red("FAIL")
|
||||
if !test.Failed {
|
||||
status = green("PASS")
|
||||
}
|
||||
fmt.Fprintf(w, "[%s]\t\t↳\t%s\t (%vs)\n", status, tname, test.Elapsed)
|
||||
if test.Failed {
|
||||
for _, line := range test.Output[2:] {
|
||||
fmt.Fprintf(w, "\t\t\t%s\n", strings.Replace(strings.TrimSpace(line), "\t", " ", -1))
|
||||
}
|
||||
fmt.Fprintln(w, "\t\t\t----------")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
return sb.String()
|
||||
}
|
||||
Reference in New Issue
Block a user