Skip to content

Instantly share code, notes, and snippets.

@retrozoid
Created September 10, 2019 08:30
Show Gist options
  • Save retrozoid/caee499dd2cb7488b6741a5f020c7cf6 to your computer and use it in GitHub Desktop.
Save retrozoid/caee499dd2cb7488b6741a5f020c7cf6 to your computer and use it in GitHub Desktop.
golang test json converter to teamcity test format
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"time"
)
var (
input = os.Stdin
output = os.Stdout
testStarted = "##teamcity[testStarted name='%s' flowId='%d' captureStandardOutput='false']\n"
testFinished = "##teamcity[testFinished name='%s' flowId='%d' duration='%d']\n"
testFailed = "##teamcity[testFailed name='%s' flowId='%d' message='failure message' details='message and stack trace']\n"
testIgnored = "##teamcity[testIgnored name='%s' flowId='%d' message='skipped']\n"
testStdOut = "##teamcity[testStdOut name='%s' flowId='%d' out='%s']\n"
testStdErr = "##teamcity[testStdErr name='%s' flowId='%d' out='%s']\n"
)
// TestEvent The JSON stream is a newline-separated sequence of TestEvent objects corresponding to the Go struct:
type TestEvent struct {
Time time.Time // encodes as an RFC3339-format string
Action string
Package string
Test string
Elapsed float64 // seconds
Output string
}
// The Action field is one of a fixed set of action descriptions
const (
RUN = "run" // the test has started running
PAUSE = "pause" // the test has been paused
CONT = "cont" // the test has continued running
PASS = "pass" // the test passed
BENCH = "bench" // the benchmark printed log output but did not fail
FAIL = "fail" // the test or benchmark failed
OUTPUT = "output" // the test printed output
SKIP = "skip" // the test was skipped or the package contained no tests
)
func main() {
reader := bufio.NewReader(input)
process(reader, output)
}
func escape(s string) string {
s = strings.TrimSuffix(s, "\n")
s = strings.Replace(s, "|", "||", -1)
s = strings.Replace(s, "\n", "|n", -1)
s = strings.Replace(s, "\r", "|n", -1)
s = strings.Replace(s, "'", "|'", -1)
s = strings.Replace(s, "]", "|]", -1)
s = strings.Replace(s, "[", "|[", -1)
return s
}
func process(r *bufio.Reader, w io.Writer) {
var id int64
flows := make(map[string]int64)
flow := func(test string) int64 {
if _, ok := flows[test]; !ok {
flows[test] = id
id++
}
return flows[test]
}
var event = new(TestEvent)
for {
line, err := r.ReadBytes('\n')
if err != nil {
break
}
err = json.Unmarshal(line, event)
if err != nil {
continue
}
if event.Test == "" {
continue
}
flowID := flow(event.Test)
switch event.Action {
case RUN:
fmt.Fprintf(w, testStarted, event.Test, flowID)
case PAUSE, CONT, BENCH:
case PASS, FAIL, SKIP:
if event.Action == SKIP {
fmt.Fprintf(w, testIgnored, event.Test, flowID)
}
if event.Action == FAIL {
fmt.Fprintf(w, testFailed, event.Test, flowID)
}
fmt.Fprintf(w, testFinished, event.Test, flowID, int64(event.Elapsed*1000))
case OUTPUT:
fmt.Fprintf(w, testStdOut, event.Test, flowID, escape(event.Output))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment