func (ts *Testsuites) SetFailure(message string) {
	ts.Failure = &Failure{
		Message: message,
	}
}
SetFailure adds a failure to the TestSuites collection for startup failures in the test harness
package report
import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"time"
)
type Type string
const (
	XML Type = "xml"
	JSON Type = "json"
)
type Property struct {
	Name  string `xml:"name,attr" json:"name"`
	Value string `xml:"value,attr" json:"value"`
}
type Properties struct {
	Property []Property `xml:"property" json:"property,omitempty"`
}
type Failure struct {
	Text string `xml:",chardata" json:"text,omitempty"`
	Message string `xml:"message,attr" json:"message"`
	Type    string `xml:"type,attr" json:"type,omitempty"`
}
type Testcase struct {
	Classname string `xml:"classname,attr" json:"classname"`
	Name string `xml:"name,attr" json:"name"`
	Timestamp time.Time `xml:"timestamp,attr" json:"timestamp"`
	Time string `xml:"time,attr" json:"time"`
	Assertions int `xml:"assertions,attr" json:"assertions,omitempty"`
	Failure *Failure `xml:"failure" json:"failure,omitempty"`
	end time.Time
}
type Testsuite struct {
	Tests int `xml:"tests,attr" json:"tests"`
	Failures int `xml:"failures,attr" json:"failures"`
	Timestamp time.Time `xml:"timestamp,attr" json:"timestamp"`
	Time string `xml:"time,attr" json:"time"`
	Name string `xml:"name,attr" json:"name"`
	Properties *Properties `xml:"properties" json:"properties,omitempty"`
	Testcase []*Testcase `xml:"testcase" json:"testcase,omitempty"`
}
type Testsuites struct {
	XMLName xml.Name `json:"-"`
	Name string `xml:"name,attr" json:"name"`
	Tests int `xml:"tests,attr" json:"tests"`
	Failures int `xml:"failures,attr" json:"failures"`
	Time string `xml:"time,attr" json:"time"`
	Properties *Properties `xml:"properties" json:"properties,omitempty"`
	Testsuite []*Testsuite `xml:"testsuite" json:"testsuite,omitempty"`
	Failure *Failure `xml:"failure" json:"failure,omitempty"`
	start   time.Time
}
func NewSuiteCollection(name string) *Testsuites {
	start := time.Now()
	return &Testsuites{XMLName: xml.Name{Local: "testsuites"}, Name: name, start: start}
}
func NewSuite(name string) *Testsuite {
	start := time.Now()
	return &Testsuite{Name: name, Timestamp: start}
}
func NewCase(name string) *Testcase {
	start := time.Now()
	return &Testcase{Name: name, Timestamp: start}
}
func NewFailure(msg string, errs []error) *Failure {
	f := &Failure{Message: msg}
	if len(errs) > 0 {
		f.Text = errs[len(errs)-1].Error()
	}
	return f
}
func (ts *Testsuite) AddTestcase(testcase *Testcase) {
	testcase.end = time.Now()
	elapsed := time.Since(testcase.Timestamp)
	testcase.Time = fmt.Sprintf("%.3f", elapsed.Seconds())
	testcase.Classname = filepath.Base(ts.Name)
	ts.Testcase = append(ts.Testcase, testcase)
	ts.Tests++
	if testcase.Failure != nil {
		ts.Failures++
	}
}
func (ts *Testsuite) AddProperty(property Property) {
	if ts.Properties == nil {
		ts.Properties = &Properties{Property: []Property{property}}
		return
	}
	if ts.Properties.Property == nil {
		ts.Properties.Property = []Property{property}
		return
	}
	ts.Properties.Property = append(ts.Properties.Property, property)
}
func (ts *Testsuites) AddTestSuite(testsuite *Testsuite) {
	ts.Testsuite = append(ts.Testsuite, testsuite)
}
func (ts *Testsuites) AddProperty(property Property) {
	if ts.Properties == nil {
		ts.Properties = &Properties{Property: []Property{property}}
		return
	}
	if ts.Properties.Property == nil {
		ts.Properties.Property = []Property{property}
		return
	}
	ts.Properties.Property = append(ts.Properties.Property, property)
}
func (ts *Testsuites) Close() {
	elapsed := time.Since(ts.start)
	ts.Time = fmt.Sprintf("%.3f", elapsed.Seconds())
	for _, testsuite := range ts.Testsuite {
		elapsed = latestEnd(testsuite.Timestamp, testsuite.Testcase).Sub(testsuite.Timestamp)
		testsuite.Time = fmt.Sprintf("%.3f", elapsed.Seconds())
		ts.Tests += testsuite.Tests
		ts.Failures += testsuite.Failures
	}
}
func latestEnd(start time.Time, testcases []*Testcase) time.Time {
	end := start
	for _, testcase := range testcases {
		if testcase.end.After(end) {
			end = testcase.end
		}
	}
	return end
}
func (ts *Testsuites) Report(dir, name string, ftype Type) error {
	ts.Close()
	switch ftype {
	case XML:
		return writeXMLReport(dir, name, ts)
	case JSON:
		fallthrough
	default:
		return writeJSONReport(dir, name, ts)
	}
}
func (ts *Testsuites) NewSuite(name string) *Testsuite {
	suite := NewSuite(name)
	ts.AddTestSuite(suite)
	return suite
}