1. Miki Tebeka
  2. go2xunit

Commits

Miki Tebeka  committed 3208289

The Go way

  • Participants
  • Parent commits a478355
  • Branches dev

Comments (0)

Files changed (7)

File go2xunit.go

View file
 	"log"
 	"os"
 	"text/template"
+
+	"bitbucket.org/tebeka/go2xunit/types"
+	"bitbucket.org/tebeka/go2xunit/gocheck"
+	"bitbucket.org/tebeka/go2xunit/gotest"
 )
 
 const (
 	version = "0.2.1"
 )
 
-type Test struct {
-	Name, Time, Message string
-	Failed              bool
-}
-
-type Suite struct {
-	Name   string
-	Time   string
-	Status string
-	Tests  []*Test
-}
-
-func (suite *Suite) NumFailed() int {
-	count := 0
-	for _, test := range suite.Tests {
-		if test.Failed {
-			count++
-		}
-	}
-
-	return count
-}
-
-func (suite *Suite) Count() int {
-	return len(suite.Tests)
-}
 
 type TestResults struct {
-	Suites []*Suite
+	Suites []*types.Suite
 	Bamboo bool
 }
 
 
-func hasFailures(suites []*Suite) bool {
+func hasFailures(suites []*types.Suite) bool {
 	for _, suite := range suites {
 		if suite.NumFailed() > 0 {
 			return true
 `
 
 // writeXML exits xunit XML of tests to out
-func writeXML(suites []*Suite, out io.Writer, bamboo bool) {
+func writeXML(suites []*types.Suite, out io.Writer, bamboo bool) {
 	testsResult := TestResults{Suites: suites, Bamboo: bamboo}
 	t := template.New("test template")
 	t, err := t.Parse(xmlTemplate)
 	fail := flag.Bool("fail", false, "fail (non zero exit) if any test failed")
 	showVersion := flag.Bool("version", false, "print version and exit")
 	bamboo := flag.Bool("bamboo", false, "xml compatible with Atlassian's Bamboo")
-	gocheck := flag.Bool("gocheck", false, "parse gocheck output")
+	is_gocheck := flag.Bool("gocheck", false, "parse gocheck output")
 	flag.Parse()
 
 	if *showVersion {
 		log.Fatalf("error: %s", err)
 	}
 
-	var parse func(rd io.Reader) ([]*Suite, error)
+	var parse func(rd io.Reader) ([]*types.Suite, error)
 
-	if *gocheck {
-		parse = gc_Parse
+	if *is_gocheck {
+		parse = gocheck.Parse
 	} else {
-		parse = gt_Parse
+		parse = gotest.Parse
 	}
 
 	suites, err := parse(input)

File go2xunit_test.go

View file
 import (
 	"os"
 	"testing"
+
+	"bitbucket.org/tebeka/go2xunit/types"
+	"bitbucket.org/tebeka/go2xunit/gocheck"
+	"bitbucket.org/tebeka/go2xunit/gotest"
 )
 
 func Test_NumFailed(t *testing.T) {
-	suite := &Suite{
-		Tests: []*Test{},
+	suite := &types.Suite{
+		Tests: []*types.Test{},
 	}
 	if suite.NumFailed() != 0 {
 		t.Fatal("found more than 1 failure in empty list")
 	}
 
-	suite.Tests = []*Test{
-		&Test{Failed: false},
-		&Test{Failed: true},
-		&Test{Failed: false},
+	suite.Tests = []*types.Test{
+		&types.Test{Failed: false},
+		&types.Test{Failed: true},
+		&types.Test{Failed: false},
 	}
 
 	if suite.NumFailed() != 1 {
 	}
 }
 
-func loadTests(filename string, t *testing.T) ([]*Suite, error) {
+func loadTests(filename string, t *testing.T) ([]*types.Suite, error) {
 	file, err := os.Open(filename)
 	if err != nil {
 		t.Fatalf("can't open %s - %s", filename, err)
 	}
 
-	return gt_Parse(file)
+	return gotest.Parse(file)
 }
 
 func Test_parseOutput(t *testing.T) {
 		t.Fatalf("can't open %s - %s", filename, err)
 	}
 
-	suites, err := gc_Parse(file)
+	suites, err := gocheck.Parse(file)
 
 	if err != nil {
 		t.Fatalf("can't parse %s - %s", filename, err)
 		t.Fatalf("can't open %s - %s", filename, err)
 	}
 
-	suites, err := gc_Parse(file)
+	suites, err := gocheck.Parse(file)
 
 	if err != nil {
 		t.Fatalf("can't parse %s - %s", filename, err)

File gocheck.go

-// Parse "gocheck -vv" output
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"io"
-	"regexp"
-	"strings"
-)
-
-// Since mucking with local package is a PITA, just prefix everything with gc_
-
-const (
-	// START: mmath_test.go:16: MySuite.TestAdd
-	gc_startRE = "START: [^:]+:[^:]+: ([A-Za-z_][[:word:]]*).([A-Za-z_][[:word:]]*)"
-	// PASS: mmath_test.go:16: MySuite.TestAdd	0.000s
-	// FAIL: mmath_test.go:35: MySuite.TestDiv
-	gc_endRE = "(PASS|FAIL): [^:]+:[^:]+: ([A-Za-z_][[:word:]]*).([A-Za-z_][[:word:]]*)([[:space:]]+([0-9]+.[0-9]+))?"
-)
-
-func gc_map2arr(m map[string]*Suite) []*Suite {
-	arr := make([]*Suite, 0, len(m))
-	for _, suite := range(m) {
-		/* FIXME:
-		suite.Status =
-		suite.Time =
-		*/
-		arr = append(arr, suite)
-	}
-
-	return arr
-}
-
-// gc_Parse parses output of "go test -gocheck.vv", returns a list of tests
-// See data/gocheck.out for an example
-func gc_Parse(rd io.Reader) ([]*Suite, error) {
-	find_start := regexp.MustCompile(gc_startRE).FindStringSubmatch
-	find_end := regexp.MustCompile(gc_endRE).FindStringSubmatch
-
-	scanner := bufio.NewScanner(rd)
-	var test *Test
-	var suites = make(map[string]*Suite)
-	var suiteName string
-	var out []string
-
-	for lnum := 1; scanner.Scan(); lnum++ {
-		line := scanner.Text()
-		tokens := find_start(line)
-		if len(tokens) > 0 {
-			if test != nil {
-				return nil, fmt.Errorf("%d: start in middle\n", lnum)
-			}
-			suiteName = tokens[1]
-			test = &Test{Name: tokens[2]}
-			out = []string{}
-			continue
-		}
-
-		tokens = find_end(line)
-		if len(tokens) > 0 {
-			if test == nil {
-				return nil, fmt.Errorf("%d: orphan end", lnum)
-			}
-			if (tokens[2] != suiteName) || (tokens[3] != test.Name) {
-				return nil, fmt.Errorf("%d: suite/name mismatch", lnum)
-			}
-			test.Message = strings.Join(out, "\n")
-			test.Time = tokens[4]
-			test.Failed = (tokens[1] == "FAIL")
-
-			suite, ok := suites[suiteName]
-			if !ok {
-				suite = &Suite{Name:suiteName}
-			}
-			suite.Tests = append(suite.Tests, test)
-			suites[suiteName] = suite
-
-			test = nil
-			suiteName = ""
-			out = []string{}
-
-			continue
-		}
-
-		if test != nil {
-			out = append(out, line)
-		}
-	}
-
-	if err := scanner.Err(); err != nil {
-		return nil, err
-	}
-
-	return gc_map2arr(suites), nil
-}

File gocheck/gocheck.go

View file
+// Parse "gocheck -vv" output
+package gocheck
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"regexp"
+	"strings"
+
+	"bitbucket.org/tebeka/go2xunit/types"
+)
+
+const (
+	// START: mmath_test.go:16: MySuite.TestAdd
+	startRE = "START: [^:]+:[^:]+: ([A-Za-z_][[:word:]]*).([A-Za-z_][[:word:]]*)"
+	// PASS: mmath_test.go:16: MySuite.TestAdd	0.000s
+	// FAIL: mmath_test.go:35: MySuite.TestDiv
+	endRE = "(PASS|FAIL): [^:]+:[^:]+: ([A-Za-z_][[:word:]]*).([A-Za-z_][[:word:]]*)([[:space:]]+([0-9]+.[0-9]+))?"
+)
+
+func map2arr(m map[string]*types.Suite) []*types.Suite {
+	arr := make([]*types.Suite, 0, len(m))
+	for _, suite := range m {
+		/* FIXME:
+		suite.Status =
+		suite.Time =
+		*/
+		arr = append(arr, suite)
+	}
+
+	return arr
+}
+
+// Parse parses output of "go test -gocheck.vv", returns a list of tests
+// See data/gocheck.out for an example
+func Parse(rd io.Reader) ([]*types.Suite, error) {
+	find_start := regexp.MustCompile(startRE).FindStringSubmatch
+	find_end := regexp.MustCompile(endRE).FindStringSubmatch
+
+	scanner := bufio.NewScanner(rd)
+	var test *types.Test
+	var suites = make(map[string]*types.Suite)
+	var suiteName string
+	var out []string
+
+	for lnum := 1; scanner.Scan(); lnum++ {
+		line := scanner.Text()
+		tokens := find_start(line)
+		if len(tokens) > 0 {
+			if test != nil {
+				return nil, fmt.Errorf("%d: start in middle\n", lnum)
+			}
+			suiteName = tokens[1]
+			test = &types.Test{Name: tokens[2]}
+			out = []string{}
+			continue
+		}
+
+		tokens = find_end(line)
+		if len(tokens) > 0 {
+			if test == nil {
+				return nil, fmt.Errorf("%d: orphan end", lnum)
+			}
+			if (tokens[2] != suiteName) || (tokens[3] != test.Name) {
+				return nil, fmt.Errorf("%d: suite/name mismatch", lnum)
+			}
+			test.Message = strings.Join(out, "\n")
+			test.Time = tokens[4]
+			test.Failed = (tokens[1] == "FAIL")
+
+			suite, ok := suites[suiteName]
+			if !ok {
+				suite = &types.Suite{Name: suiteName}
+			}
+			suite.Tests = append(suite.Tests, test)
+			suites[suiteName] = suite
+
+			test = nil
+			suiteName = ""
+			out = []string{}
+
+			continue
+		}
+
+		if test != nil {
+			out = append(out, line)
+		}
+	}
+
+	if err := scanner.Err(); err != nil {
+		return nil, err
+	}
+
+	return map2arr(suites), nil
+}

File gotest.go

-// Parse "gotest -v" output
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"io"
-	"regexp"
-	"strings"
-)
-
-const (
-	// === RUN TestAdd
-	gt_startRE = "^=== RUN ([a-zA-Z_][[:word:]]*)"
-
-	// --- PASS: TestSub (0.00 seconds)
-	// --- FAIL: TestSubFail (0.00 seconds)
-	gt_endRE = "^--- (PASS|FAIL): ([a-zA-Z_][[:word:]]*) \\((\\d+.\\d+)"
-
-	// FAIL	_/home/miki/Projects/goroot/src/xunit	0.004s
-	// ok  	_/home/miki/Projects/goroot/src/anotherTest	0.000s
-	gt_suiteRE = "^(ok|FAIL)[ \t]+([^ \t]+)[ \t]+(\\d+.\\d+)"
-)
-
-func gt_Parse(rd io.Reader) ([]*Suite, error) {
-	find_start := regexp.MustCompile(gt_startRE).FindStringSubmatch
-	find_end := regexp.MustCompile(gt_endRE).FindStringSubmatch
-	find_suite := regexp.MustCompile(gt_suiteRE).FindStringSubmatch
-	is_exit := regexp.MustCompile("^exit status -?\\d+").MatchString
-
-	suites := []*Suite{}
-	var curTest *Test
-	var curSuite *Suite
-	var out []string
-
-	scanner := bufio.NewScanner(rd)
-	for lnum := 1; scanner.Scan(); lnum++ {
-		line := scanner.Text()
-
-		tokens := find_start(line)
-		if tokens != nil {
-			if curTest != nil {
-				return nil, fmt.Errorf("%d: test in middle of other", lnum)
-			}
-			curTest = &Test{
-				Name: tokens[1],
-			}
-			if len(out) > 0 {
-				message := strings.Join(out, "\n")
-				if (curSuite == nil) {
-					return nil, fmt.Errorf("orphan output: %s", message)
-				}
-				curSuite.Tests[len(curSuite.Tests)-1].Message = message
-			}
-			out = []string{}
-			continue
-		}
-
-		tokens = find_end(line)
-		if tokens != nil {
-			if curTest == nil {
-				return nil, fmt.Errorf("%d: orphan end test", lnum)
-			}
-			if tokens[2] != curTest.Name {
-				return nil, fmt.Errorf("%d: name mismatch", lnum)
-			}
-
-			curTest.Failed = (tokens[1] == "FAIL")
-			curTest.Time = tokens[3]
-			curTest.Message = strings.Join(out, "\n")
-			if curSuite == nil {
-				curSuite = &Suite{}
-			}
-			curSuite.Tests = append(curSuite.Tests, curTest)
-			curTest = nil
-			continue
-		}
-
-		tokens = find_suite(line)
-		if tokens != nil {
-			if curSuite == nil {
-				return nil, fmt.Errorf("%d: orphan end suite", lnum)
-			}
-			curSuite.Name = tokens[2]
-			curSuite.Time = tokens[3]
-			suites = append(suites, curSuite)
-			curSuite = nil
-
-			continue
-		}
-
-		if is_exit(line) || (line == "FAIL") {
-			continue
-		}
-
-		if curSuite == nil {
-			return nil, fmt.Errorf("%d: orphan line", lnum)
-		}
-
-		out = append(out, line)
-	}
-
-	if err := scanner.Err(); err != nil {
-		return nil, err
-	}
-
-	return suites, nil
-}

File gotest/gotest.go

View file
+// Parse "gotest -v" output
+package gotest
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"regexp"
+	"strings"
+
+	"bitbucket.org/tebeka/go2xunit/types"
+)
+
+const (
+	// === RUN TestAdd
+	startRE = "^=== RUN ([a-zA-Z_][[:word:]]*)"
+
+	// --- PASS: TestSub (0.00 seconds)
+	// --- FAIL: TestSubFail (0.00 seconds)
+	endRE = "^--- (PASS|FAIL): ([a-zA-Z_][[:word:]]*) \\((\\d+.\\d+)"
+
+	// FAIL	_/home/miki/Projects/goroot/src/xunit	0.004s
+	// ok  	_/home/miki/Projects/goroot/src/anotherTest	0.000s
+	suiteRE = "^(ok|FAIL)[ \t]+([^ \t]+)[ \t]+(\\d+.\\d+)"
+)
+
+func Parse(rd io.Reader) ([]*types.Suite, error) {
+	find_start := regexp.MustCompile(startRE).FindStringSubmatch
+	find_end := regexp.MustCompile(endRE).FindStringSubmatch
+	find_suite := regexp.MustCompile(suiteRE).FindStringSubmatch
+	is_exit := regexp.MustCompile("^exit status -?\\d+").MatchString
+
+	suites := []*types.Suite{}
+	var curTest *types.Test
+	var curSuite *types.Suite
+	var out []string
+
+	scanner := bufio.NewScanner(rd)
+	for lnum := 1; scanner.Scan(); lnum++ {
+		line := scanner.Text()
+
+		tokens := find_start(line)
+		if tokens != nil {
+			if curTest != nil {
+				return nil, fmt.Errorf("%d: test in middle of other", lnum)
+			}
+			curTest = &types.Test{
+				Name: tokens[1],
+			}
+			if len(out) > 0 {
+				message := strings.Join(out, "\n")
+				if (curSuite == nil) {
+					return nil, fmt.Errorf("orphan output: %s", message)
+				}
+				curSuite.Tests[len(curSuite.Tests)-1].Message = message
+			}
+			out = []string{}
+			continue
+		}
+
+		tokens = find_end(line)
+		if tokens != nil {
+			if curTest == nil {
+				return nil, fmt.Errorf("%d: orphan end test", lnum)
+			}
+			if tokens[2] != curTest.Name {
+				return nil, fmt.Errorf("%d: name mismatch", lnum)
+			}
+
+			curTest.Failed = (tokens[1] == "FAIL")
+			curTest.Time = tokens[3]
+			curTest.Message = strings.Join(out, "\n")
+			if curSuite == nil {
+				curSuite = &types.Suite{}
+			}
+			curSuite.Tests = append(curSuite.Tests, curTest)
+			curTest = nil
+			continue
+		}
+
+		tokens = find_suite(line)
+		if tokens != nil {
+			if curSuite == nil {
+				return nil, fmt.Errorf("%d: orphan end suite", lnum)
+			}
+			curSuite.Name = tokens[2]
+			curSuite.Time = tokens[3]
+			suites = append(suites, curSuite)
+			curSuite = nil
+
+			continue
+		}
+
+		if is_exit(line) || (line == "FAIL") {
+			continue
+		}
+
+		if curSuite == nil {
+			return nil, fmt.Errorf("%d: orphan line", lnum)
+		}
+
+		out = append(out, line)
+	}
+
+	if err := scanner.Err(); err != nil {
+		return nil, err
+	}
+
+	return suites, nil
+}

File types/types.go

View file
+package types
+
+type Test struct {
+	Name, Time, Message string
+	Failed              bool
+}
+
+type Suite struct {
+	Name   string
+	Time   string
+	Status string
+	Tests  []*Test
+}
+
+func (suite *Suite) NumFailed() int {
+	count := 0
+	for _, test := range suite.Tests {
+		if test.Failed {
+			count++
+		}
+	}
+
+	return count
+}
+
+func (suite *Suite) Count() int {
+	return len(suite.Tests)
+}