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

Feat/add append command #32

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ Available Commands:
version Prints the version number of go-test-report

Flags:
-g, --groupSize int the number of tests per test group indicator (default 20)
-h, --help help for go-test-report
-o, --output string the HTML output file (default "test_report.html")
-s, --size string the size (in pixels) of the clickable indicator for test result groups (default "24")
-t, --title string the title text shown in the test report (default "go-test-report")
-v, --verbose while processing, show the complete output from go test
-a, --append append to the HTML output file
-g, --groupSize int the number of tests per test group indicator (default 100)
-h, --help help for go-test-report
-o, --output string the HTML output file (default "test_report.html")
-p, --package string if run with a test file, point out the target package
-s, --size string the size (in pixels) of the clickable indicator for test result groups (default "24")
-t, --title string the title text shown in the test report (default "go-test-report")
-v, --verbose while processing, show the complete output from go test

Use "go-test-report [command] --help" for more information about a command.
```
Expand Down Expand Up @@ -135,6 +137,17 @@ Additionally, _both_ the width and height of the _group size indicator_ can be s
$ go test -json | go-test-report -g 32x16
```

Use `-a` or `--append` to append message to the existed html file. you should use it with `-o` or you will append the content to default html file.
every time you append, will create a new group.
```bash
$ go test -json | go-test-report -a (-o xxx.html)
```

Use `-p` to point out that tested file in which package. Example bellow:
```bash
$ go test ./main_test.go | go-test-report -p github.com/vakenbolt/go-test-report
```

## Building from source

[GNU make](https://www.gnu.org/software/make/) is used as the main build automation tool for go-test-report. MacOS users may need to upgrade their local `make` to the latest version using [homebrew](https://brew.sh/).
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ module github.com/vakenbolt/go-test-report
go 1.13

require (
github.com/PuerkitoBio/goquery v1.7.0
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.6.1
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
github.com/andybalholm/cascadia v1.1.0
)
164 changes: 164 additions & 0 deletions go.sum

Large diffs are not rendered by default.

104 changes: 46 additions & 58 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"bufio"
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -42,34 +41,14 @@ type (
TestFunctionDetail testFunctionFilePos
}

templateData struct {
TestResultGroupIndicatorWidth string
TestResultGroupIndicatorHeight string
TestResults []*testGroupData
NumOfTestPassed int
NumOfTestFailed int
NumOfTestSkipped int
NumOfTests int
TestDuration time.Duration
ReportTitle string
JsCode template.JS
numOfTestsPerGroup int
OutputFilename string
TestExecutionDate string
}

testGroupData struct {
FailureIndicator string
SkippedIndicator string
TestResults []*testStatus
}

cmdFlags struct {
titleFlag string
sizeFlag string
groupSize int
outputFlag string
verbose bool
titleFlag string
sizeFlag string
groupSize int
outputFlag string
verbose bool
append bool
targetPackage string
}

goListJSONModule struct {
Expand Down Expand Up @@ -126,7 +105,22 @@ func initRootCommand() (*cobra.Command, *templateData, *cmdFlags) {
}
stdin := os.Stdin
stdinScanner := bufio.NewScanner(stdin)
testReportHTMLTemplateFile, _ := os.Create(tmplData.OutputFilename)
var (
testReportHTMLTemplateFile *os.File
tpl *template.Template
)
tpl, err := tmplData.initReportHTML()
if err != nil {
return err
}
if flags.append && FileExist(tmplData.OutputFilename) {
testReportHTMLTemplateFile, _ = os.OpenFile(tmplData.OutputFilename, os.O_RDWR, 0)
err := tmplData.readDataFromHTML(testReportHTMLTemplateFile)
if err != nil {
return err
}
}
testReportHTMLTemplateFile, _ = os.Create(tmplData.OutputFilename)
reportFileWriter := bufio.NewWriter(testReportHTMLTemplateFile)
defer func() {
_ = stdin.Close()
Expand All @@ -144,11 +138,11 @@ func initRootCommand() (*cobra.Command, *templateData, *cmdFlags) {
}
elapsedTestTime := time.Since(startTestTime)
// used to the location of test functions in test go files by package and test function name.
testFileDetailByPackage, err := getPackageDetails(allPackageNames)
testFileDetailByPackage, err := getPackageDetails(allPackageNames, flags.targetPackage)
if err != nil {
return err
}
err = generateReport(tmplData, allTests, testFileDetailByPackage, elapsedTestTime, reportFileWriter)
err = generateReport(tpl, tmplData, allTests, testFileDetailByPackage, elapsedTestTime, reportFileWriter)
elapsedTime := time.Since(startTime)
elapsedTimeMsg := []byte(fmt.Sprintf("[go-test-report] finished in %s\n", elapsedTime))
if _, err := cmd.OutOrStdout().Write(elapsedTimeMsg); err != nil {
Expand Down Expand Up @@ -182,7 +176,7 @@ func initRootCommand() (*cobra.Command, *templateData, *cmdFlags) {
rootCmd.PersistentFlags().IntVarP(&flags.groupSize,
"groupSize",
"g",
20,
100,
"the number of tests per test group indicator")
rootCmd.PersistentFlags().StringVarP(&flags.outputFlag,
"output",
Expand All @@ -194,6 +188,16 @@ func initRootCommand() (*cobra.Command, *templateData, *cmdFlags) {
"v",
false,
"while processing, show the complete output from go test ")
rootCmd.PersistentFlags().BoolVarP(&flags.append,
"append",
"a",
false,
"append to the HTML output file")
rootCmd.PersistentFlags().StringVarP(&flags.targetPackage,
"package",
"p",
"",
"if run with a test file, point out the target package")

return rootCmd, tmplData, flags
}
Expand All @@ -213,7 +217,7 @@ func readTestDataFromStdIn(stdinScanner *bufio.Scanner, flags *cmdFlags, cmd *co
}
goTestOutputRow := &goTestOutputRow{}
if err := json.Unmarshal(lineInput, goTestOutputRow); err != nil {
return nil, nil, err
continue
}
if goTestOutputRow.TestName != "" {
var status *testStatus
Expand Down Expand Up @@ -247,13 +251,17 @@ func readTestDataFromStdIn(stdinScanner *bufio.Scanner, flags *cmdFlags, cmd *co
return allPackageNames, allTests, nil
}

func getPackageDetails(allPackageNames map[string]*types.Nil) (testFileDetailsByPackage, error) {
func getPackageDetails(allPackageNames map[string]*types.Nil, defaultPackage string) (testFileDetailsByPackage, error) {
var out bytes.Buffer
var cmd *exec.Cmd
testFileDetailByPackage := testFileDetailsByPackage{}
stringReader := strings.NewReader("")
for packageName := range allPackageNames {
cmd = exec.Command("go", "list", "-json", packageName)
if packageName == "command-line-arguments" {
cmd = exec.Command("go", "list", "-json", defaultPackage)
} else {
cmd = exec.Command("go", "list", "-json", packageName)
}
out.Reset()
stringReader.Reset("")
cmd.Stdin = stringReader
Expand Down Expand Up @@ -314,29 +322,9 @@ func (t byName) Less(i, j int) bool {
return t[i].name < t[j].name
}

func generateReport(tmplData *templateData, allTests map[string]*testStatus, testFileDetailByPackage testFileDetailsByPackage, elapsedTestTime time.Duration, reportFileWriter *bufio.Writer) error {
// read the html template from the generated embedded asset go file
tpl := template.New("test_report.html.template")
testReportHTMLTemplateStr, err := hex.DecodeString(testReportHTMLTemplate)
if err != nil {
return err
}
tpl, err = tpl.Parse(string(testReportHTMLTemplateStr))
if err != nil {
return err
}
// read Javascript code from the generated embedded asset go file
testReportJsCodeStr, err := hex.DecodeString(testReportJsCode)
if err != nil {
return err
}

tmplData.NumOfTestPassed = 0
tmplData.NumOfTestFailed = 0
tmplData.NumOfTestSkipped = 0
tmplData.JsCode = template.JS(testReportJsCodeStr)
func generateReport(tpl *template.Template, tmplData *templateData, allTests map[string]*testStatus, testFileDetailByPackage testFileDetailsByPackage, elapsedTestTime time.Duration, reportFileWriter *bufio.Writer) error {
tgCounter := 0
tgID := 0
tgID := len(tmplData.TestResults)

// sort the allTests map by test name (this will produce a consistent order when iterating through the map)
var tests []testRef
Expand Down Expand Up @@ -374,7 +362,7 @@ func generateReport(tmplData *templateData, allTests map[string]*testStatus, tes
}
}
tmplData.NumOfTests = tmplData.NumOfTestPassed + tmplData.NumOfTestFailed + tmplData.NumOfTestSkipped
tmplData.TestDuration = elapsedTestTime.Round(time.Millisecond)
tmplData.TestDuration += elapsedTestTime.Round(time.Millisecond)
td := time.Now()
tmplData.TestExecutionDate = fmt.Sprintf("%s %d, %d %02d:%02d:%02d",
td.Month(), td.Day(), td.Year(), td.Hour(), td.Minute(), td.Second())
Expand Down
3 changes: 2 additions & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ func TestGenerateReport(t *testing.T) {
}
elapsedTestTime := 3 * time.Second
writer := bufio.NewWriter(&bytes.Buffer{})
err := generateReport(tmplData, allTests, testFileDetailsByPackage, elapsedTestTime, writer)
tpl, _ := tmplData.initReportHTML()
err := generateReport(tpl, tmplData, allTests, testFileDetailsByPackage, elapsedTestTime, writer)
assertions.Nil(err)
assertions.Equal(2, tmplData.NumOfTestPassed)
assertions.Equal(1, tmplData.NumOfTestFailed)
Expand Down
105 changes: 105 additions & 0 deletions report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"encoding/hex"
"encoding/json"
"github.com/PuerkitoBio/goquery"
"html/template"
"os"
"strconv"
"strings"
"time"
)

type templateData struct {
TestResultGroupIndicatorWidth string
TestResultGroupIndicatorHeight string
TestResults []*testGroupData
NumOfTestPassed int
NumOfTestFailed int
NumOfTestSkipped int
NumOfTests int
TestDuration time.Duration
ReportTitle string
JsCode template.JS
numOfTestsPerGroup int
OutputFilename string
TestExecutionDate string
}

type testGroupData struct {
FailureIndicator string
SkippedIndicator string
TestResults []*testStatus
}

func (tp *templateData) initReportHTML() (*template.Template, error) {
// read the html template from the generated embedded asset go file
tpl := template.New("test_report.html.template")
testReportHTMLTemplateStr, err := hex.DecodeString(testReportHTMLTemplate)
if err != nil {
return nil, err
}
tpl, err = tpl.Parse(string(testReportHTMLTemplateStr))
if err != nil {
return nil, err
}
// read Javascript code from the generated embedded asset go file
testReportJsCodeStr, err := hex.DecodeString(testReportJsCode)
if err != nil {
return nil, err
}
tp.JsCode = template.JS(testReportJsCodeStr)
return tpl, nil
}

func (tp *templateData) readDataFromHTML(fi *os.File) (err error) {
doc, _ := goquery.NewDocumentFromReader(fi)
// readHeader
doc.Find(".pageHeader .testStats .total strong").Each(func(i int, selection *goquery.Selection) {
if i == 0 {
a, err := strconv.Atoi(selection.Text())
if err != nil {
return
}
tp.NumOfTests = a
} else if i == 1 {
dua, err := time.ParseDuration(selection.Text())
if err != nil {
return
}
tp.TestDuration = dua
}
})

passText := doc.Find(".pageHeader .testStats .passed strong").Text()
passNum, err := strconv.Atoi(passText)
if err != nil {
return
}
tp.NumOfTestPassed = passNum

skippedText := doc.Find(".pageHeader .testStats .skipped strong").Text()
skippedNum, err := strconv.Atoi(skippedText)
if err != nil {
return
}
tp.NumOfTestSkipped = skippedNum

failedText := doc.Find(".pageHeader .testStats .failed strong").Text()
failedNum, err := strconv.Atoi(failedText)
if err != nil {
return
}
tp.NumOfTestFailed = failedNum

strs := strings.SplitAfter(doc.Find("script").Text(), "const data = ")
strs = strings.SplitAfter(strs[1], "}}]}]")
var tempResult []*testGroupData
err = json.Unmarshal([]byte(strs[0]), &tempResult)
if err != nil {
return
}
tp.TestResults = tempResult
return
}
16 changes: 16 additions & 0 deletions report_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"os"
"testing"
)

func TestRead(t *testing.T) {
t.Skip()
var tmp templateData
fi, _ := os.Open("test_report.html")
err := tmp.readDataFromHTML(fi)
if err != nil {
t.Error(err)
}
}
8 changes: 8 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

import "os"

func FileExist(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}