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

SMAT-175: qase #9

Draft
wants to merge 4 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
54 changes: 54 additions & 0 deletions cmd/qase-cli/internal/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2020 Insolar Network Ltd.
// All rights reserved.
// This material is licensed under the Insolar License version 1.0,
// available at https://github.com/insolar/testrail-cli/LICENSE.md.

package internal

import (
"log"

"github.com/insolar/testrail-cli/types"
)

// FilterTestObjects split test objects into groups: valid/not found/wrong description
func FilterTestObjects(objectList []*types.TestMatcher, caseList types.TestCasesWithDescription, skipDesc bool) *TestObjectSummary {
var (
summary TestObjectSummary
objectMap = make(map[int]*types.TestMatcher)
caseMap = make(map[int]types.TestCaseWithDescription)
)

for _, c := range caseList {
caseMap[c.ID] = c
}

for _, object := range objectList {
if object.Status == "SKIP" && object.IssueURL == "" {
summary.SkippedNoIssue = append(summary.SkippedNoIssue, object)
}

if object.ID != 0 {
if _, ok := objectMap[object.ID]; ok {
log.Printf("duplicate testcase: %d\n", object.ID)
}
}

objectMap[object.ID] = object

c, ok := caseMap[object.ID]
if !ok {
summary.NotFound = append(summary.NotFound, object)
continue
}

object.OriginalDescription = c.Description
if !skipDesc && object.Description != c.Description {
summary.WrongDesc = append(summary.WrongDesc, object)
continue
}
summary.Valid = append(summary.Valid, object)
}

return &summary
}
79 changes: 79 additions & 0 deletions cmd/qase-cli/internal/matcher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2020 Insolar Network Ltd.
// All rights reserved.
// This material is licensed under the Insolar License version 1.0,
// available at https://github.com/insolar/testrail-cli/LICENSE.md.

package internal

import (
"log"
"regexp"
"strconv"

"github.com/insolar/testrail-cli/parser"
"github.com/insolar/testrail-cli/types"
)

var (
testStatusRe = regexp.MustCompile(`--- (.*):`)
testSkipIssueRe = regexp.MustCompile(`insolar\.atlassian\.net/browse/([A-Z]+-\d+)`)
testCaseIdRe = regexp.MustCompile(`C(\d{1,8})\s(.*)`)
)

type Converter struct{}

func (c Converter) ConvertEventsToMatcherObjectsPreload(events map[string][]parser.TestEvent) []*types.TestMatcher {
reader := parser.NewStreamingEventReaderFromMap(events)
return c.ConvertEventsToMatcherObjects(reader)
}

func (Converter) ConvertEventsToMatcherObjects(reader parser.EventReader) []*types.TestMatcher {
matchers := make(map[string]*types.TestMatcher)

for {
name, event, err := reader.Next()
if parser.IsEOF(err) {
break
} else if err != nil {
log.Fatal(err)
}

if event.Action == "output" {
if event.Test == "" {
continue
}

t, ok := matchers[name]
if !ok {
t = &types.TestMatcher{}
matchers[name] = t
}

t.GoTestName = event.Test

if res := testCaseIdRe.FindStringSubmatch(event.Output); len(res) == 3 {
d, err := strconv.Atoi(res[1])
if err != nil {
log.Fatal(err)
}
// TODO: Bad, should harden regex instead, debatable for now
if t.ID != 0 {
continue
}
t.ID = d
t.Description = res[2]
} else if res := testStatusRe.FindStringSubmatch(event.Output); len(res) == 2 {
t.Status = res[1]
} else if res := testSkipIssueRe.FindStringSubmatch(event.Output); len(res) == 2 {
t.IssueURL = res[1]
}
}
}

matcherList := make([]*types.TestMatcher, 0, len(matchers))
for _, val := range matchers {
matcherList = append(matcherList, val)
}

return matcherList
}
49 changes: 49 additions & 0 deletions cmd/qase-cli/internal/summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2020 Insolar Network Ltd.
// All rights reserved.
// This material is licensed under the Insolar License version 1.0,
// available at https://github.com/insolar/testrail-cli/LICENSE.md.

package internal

import (
"log"

"github.com/insolar/testrail-cli/types"
)

type URLFormatter interface {
FormatURL(int) string
}

type TestObjectSummary struct {
Valid []*types.TestMatcher
NotFound []*types.TestMatcher
WrongDesc []*types.TestMatcher
SkippedNoIssue []*types.TestMatcher
}

func (s TestObjectSummary) LogInvalidTests(f URLFormatter) {
if len(s.NotFound) > 0 {
log.Println("Tests without testrail case ID:")
for _, o := range s.NotFound {
log.Printf(" %s", o.GoTestName)
}
}

if len(s.WrongDesc) > 0 {
log.Println("Test title discrepancy with testrail test-case title:")
for _, o := range s.WrongDesc {
log.Printf(" %s", o.GoTestName)
log.Printf(" Test Description: %s", o.Description)
log.Printf(" Original Description: %s", o.OriginalDescription)
// log.Printf(" TestCase URL: %s", f.FormatURL(o.ID))
}
}

if len(s.SkippedNoIssue) > 0 {
log.Println("Skipped tests without issue:")
for _, o := range s.SkippedNoIssue {
log.Printf(" %s", o.GoTestName)
}
}
}
97 changes: 97 additions & 0 deletions cmd/qase-cli/qase-cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2020 Insolar Network Ltd.
// All rights reserved.
// This material is licensed under the Insolar License version 1.0,
// available at https://github.com/insolar/testrail-cli/LICENSE.md.

package main

import (
"flag"
"io"
"log"
"os"

"github.com/spf13/pflag"
"github.com/spf13/viper"

"github.com/insolar/testrail-cli/cmd/qase-cli/internal"
"github.com/insolar/testrail-cli/parser"
"github.com/insolar/testrail-cli/parser/json"
"github.com/insolar/testrail-cli/parser/text"
"github.com/insolar/testrail-cli/qase"
)

func main() {
viper.AutomaticEnv()
viper.SetEnvPrefix("QS")
flag.String("API_TOKEN", "", "Qase apiToken")
flag.String("FILE", "", "go test json file")
flag.String("RUN_NAME", "", "ci qase RunName")
flag.String("PROJECT_ID", "", "qase project id")
flag.Int("SUITE_ID", 0, "qase suite id")
flag.Bool("SKIP-DESC", false, "skip description check")
flag.String("FORMAT", "json", "test output format")
flag.String("MATCHER", "default", "test output matcher")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)

var (
apiToken = viper.GetString("API_TOKEN")
runName = viper.GetString("RUN_NAME")
projectID = viper.GetString("PROJECT_ID")
suiteID = viper.GetInt32("SUITE_ID")
file = viper.GetString("FILE")
skipDesc = viper.GetBool("SKIP-DESC")
)

if apiToken == "" {
log.Fatal("provide qase apiToken")
}
if runName == "" {
log.Fatal("provide runName")
}
if projectID == "" {
log.Fatal("provide qase project id")
}
if suiteID == 0 {
log.Fatal("provide suite id, ex.: --SUITE_ID=54, or env QS_SUITE_ID=54")
}

var (
parserName = viper.GetString("format")
parserInstance parser.Parser
)
switch parserName {
case "json":
parserInstance = json.Parser{}
case "text":
parserInstance = text.Parser{}
default:
log.Fatalf("Unsupported format %s", parserName)
}

matcherInstance := internal.Converter{}

var stream io.Reader = os.Stdin
if file != "" {
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()

stream = f
}
eventReader := parserInstance.GetParseIterator(stream)
tObjects := matcherInstance.ConvertEventsToMatcherObjects(eventReader)

t := qase.NewUploader(apiToken)
t.Init(projectID, suiteID, runName)

filteredObjects := internal.FilterTestObjects(tObjects, t.GetCasesWithDescription(), skipDesc)
filteredObjects.LogInvalidTests(t)

t.AddTests(filteredObjects.Valid)
t.Upload()
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ module github.com/insolar/testrail-cli
go 1.12

require (
github.com/antihax/optional v1.0.0
github.com/educlos/testrail v0.0.0-20190627213040-ca1b25409ae2
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.6.2
github.com/stretchr/testify v1.4.0
go.qase.io/client v0.0.4
)
Loading