123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package reporting
- import (
- "encoding/json"
- "fmt"
- "runtime"
- "strings"
- "github.com/smartystreets/goconvey/convey/gotest"
- )
- ////////////////// ScopeReport ////////////////////
- type ScopeReport struct {
- Title string
- File string
- Line int
- }
- func NewScopeReport(title string) *ScopeReport {
- file, line, _ := gotest.ResolveExternalCaller()
- self := new(ScopeReport)
- self.Title = title
- self.File = file
- self.Line = line
- return self
- }
- ////////////////// ScopeResult ////////////////////
- type ScopeResult struct {
- Title string
- File string
- Line int
- Depth int
- Assertions []*AssertionResult
- Output string
- }
- func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
- self := new(ScopeResult)
- self.Title = title
- self.Depth = depth
- self.File = file
- self.Line = line
- self.Assertions = []*AssertionResult{}
- return self
- }
- /////////////////// StoryReport /////////////////////
- type StoryReport struct {
- Test T
- Name string
- File string
- Line int
- }
- func NewStoryReport(test T) *StoryReport {
- file, line, name := gotest.ResolveExternalCaller()
- name = removePackagePath(name)
- self := new(StoryReport)
- self.Test = test
- self.Name = name
- self.File = file
- self.Line = line
- return self
- }
- // name comes in looking like "github.com/smartystreets/goconvey/examples.TestName".
- // We only want the stuff after the last '.', which is the name of the test function.
- func removePackagePath(name string) string {
- parts := strings.Split(name, ".")
- return parts[len(parts)-1]
- }
- /////////////////// FailureView ////////////////////////
- // This struct is also declared in github.com/smartystreets/assertions.
- // The json struct tags should be equal in both declarations.
- type FailureView struct {
- Message string `json:"Message"`
- Expected string `json:"Expected"`
- Actual string `json:"Actual"`
- }
- ////////////////////AssertionResult //////////////////////
- type AssertionResult struct {
- File string
- Line int
- Expected string
- Actual string
- Failure string
- Error interface{}
- StackTrace string
- Skipped bool
- }
- func NewFailureReport(failure string) *AssertionResult {
- report := new(AssertionResult)
- report.File, report.Line = caller()
- report.StackTrace = stackTrace()
- parseFailure(failure, report)
- return report
- }
- func parseFailure(failure string, report *AssertionResult) {
- view := new(FailureView)
- err := json.Unmarshal([]byte(failure), view)
- if err == nil {
- report.Failure = view.Message
- report.Expected = view.Expected
- report.Actual = view.Actual
- } else {
- report.Failure = failure
- }
- }
- func NewErrorReport(err interface{}) *AssertionResult {
- report := new(AssertionResult)
- report.File, report.Line = caller()
- report.StackTrace = fullStackTrace()
- report.Error = fmt.Sprintf("%v", err)
- return report
- }
- func NewSuccessReport() *AssertionResult {
- return new(AssertionResult)
- }
- func NewSkipReport() *AssertionResult {
- report := new(AssertionResult)
- report.File, report.Line = caller()
- report.StackTrace = fullStackTrace()
- report.Skipped = true
- return report
- }
- func caller() (file string, line int) {
- file, line, _ = gotest.ResolveExternalCaller()
- return
- }
- func stackTrace() string {
- buffer := make([]byte, 1024*64)
- n := runtime.Stack(buffer, false)
- return removeInternalEntries(string(buffer[:n]))
- }
- func fullStackTrace() string {
- buffer := make([]byte, 1024*64)
- n := runtime.Stack(buffer, true)
- return removeInternalEntries(string(buffer[:n]))
- }
- func removeInternalEntries(stack string) string {
- lines := strings.Split(stack, newline)
- filtered := []string{}
- for _, line := range lines {
- if !isExternal(line) {
- filtered = append(filtered, line)
- }
- }
- return strings.Join(filtered, newline)
- }
- func isExternal(line string) bool {
- for _, p := range internalPackages {
- if strings.Contains(line, p) {
- return true
- }
- }
- return false
- }
- // NOTE: any new packages that host goconvey packages will need to be added here!
- // An alternative is to scan the goconvey directory and then exclude stuff like
- // the examples package but that's nasty too.
- var internalPackages = []string{
- "goconvey/assertions",
- "goconvey/convey",
- "goconvey/execution",
- "goconvey/gotest",
- "goconvey/reporting",
- }
|