Categories
Uncategorized

golang Development: library articles (five) go use test tools goconvey

Why use goconvey test program

goconvey integrated go test, go test seamless access. Run the test case management, but also provides a wealth of functions assertion, very friendly WEB interface, intuitive viewing test results.
    If you do not goconvey, then write a test result, the test function first run, then run to determine the results of the test function to determine if various, various output message, and regression testing too much trouble. But if these are used goconvey becomes extremely simple.
    Or use the code to see some relatively simple and straightforward.

How to use goconvey test program

The first step of course is to install goconvey

go get github.com/smartystreets/goconvey

Look at the code being tested

package main

import "fmt"

type Student struct {
    Num int
    Name string

    Chinaese int
    English int
    Math int
}

func NewStudent(num int, name string) (*Student,error) {
    if num < 1 || len(name) < 1 {
        return nil,fmt.Errorf("num name empty")
    }
    stu := new(Student)
    stu.Num = num
    stu.Name = name
    return stu,nil
}

func (this *Student) GetAve() (int,error) {
    score := this.Chinaese + this.English + this.Math
    if score == 0 {
        return 0,fmt.Errorf("score is 0")
    }
    return score/3,nil
}

The main test code look goconvey

package main

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
)

func TestNew(t *testing.T) {
    Convey("start test new", t, func() {
        stu,err := NewStudent(0,"")
        Convey("have error", func() {
            So(err, ShouldBeError)
        })
        Convey("stu is nil", func() {
            So(stu, ShouldBeNil)
        })
    })
}

func TestScore(t *testing.T) {
    stu,_ := NewStudent(1,"test")
    Convey("if error", t, func() {
        _,err := stu.GetAve()
        Convey("have error", func() {
            So(err, ShouldBeError)
        })
    })

    Convey("normal", t, func() {
        stu.Math = 60
        stu.Chinaese = 70
        stu.English = 80
        score,err := stu.GetAve()
        Convey("have error", func() {
            So(err, ShouldBeError)
        })
        Convey("score > 60", func() {
            So(score, ShouldBeGreaterThan, 60)
        })
    })
}

Into the test code directory, go test execution

=== RUN   TestNew

  start test new
    have error ✔
    stu is nil ✔


2 total assertions

--- PASS: TestNew (0.00s)
=== RUN   TestScore

  if error
    have error ✔


3 total assertions


  normal
    have error ✘
    score > 60 ✔


Failures:

  * /data/www/go/src/test/student_test.go
  Line 35:

In fact, the command line is displayed in color-coded. The result is expected to occur will be marked with a check mark, if desired appear and did not appear will be marked with a fork.
    There are more fun WEB interface. Directory entry test code and then execute goconvey will open a WEB interface, more friendly identifies the test results, test how many times, a few by a few failures, at a glance.
    
    In fact, the use of special simple
    The introduction of class libraries, start Convey function, and the rest is calling So various assertion of various comparison

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
)
Convey("desc", t, func() {
So(var, function)
})

Basic common development in comparison function basically have, look at the comparison list of functions, looking seemingly are covered.

Convey("Equality assertions should be accessible", t, func() {
        thing1a := thing{a: "asdf"}
        thing1b := thing{a: "asdf"}
        thing2 := thing{a: "qwer"}

        So(1, ShouldEqual, 1)
        So(1, ShouldNotEqual, 2)
        So(1, ShouldAlmostEqual, 1.000000000000001)
        So(1, ShouldNotAlmostEqual, 2, 0.5)
        So(thing1a, ShouldResemble, thing1b)
        So(thing1a, ShouldNotResemble, thing2)
        So(&thing1a, ShouldPointTo, &thing1a)
        So(&thing1a, ShouldNotPointTo, &thing1b)
        So(nil, ShouldBeNil)
        So(1, ShouldNotBeNil)
        So(true, ShouldBeTrue)
        So(false, ShouldBeFalse)
        So(0, ShouldBeZeroValue)
        So(1, ShouldNotBeZeroValue)
    })

    Convey("Numeric comparison assertions should be accessible", t, func() {
        So(1, ShouldBeGreaterThan, 0)
        So(1, ShouldBeGreaterThanOrEqualTo, 1)
        So(1, ShouldBeLessThan, 2)
        So(1, ShouldBeLessThanOrEqualTo, 1)
        So(1, ShouldBeBetween, 0, 2)
        So(1, ShouldNotBeBetween, 2, 4)
        So(1, ShouldBeBetweenOrEqual, 1, 2)
        So(1, ShouldNotBeBetweenOrEqual, 2, 4)
    })

    Convey("Container assertions should be accessible", t, func() {
        So([]int{1, 2, 3}, ShouldContain, 2)
        So([]int{1, 2, 3}, ShouldNotContain, 4)
        So(map[int]int{1: 1, 2: 2, 3: 3}, ShouldContainKey, 2)
        So(map[int]int{1: 1, 2: 2, 3: 3}, ShouldNotContainKey, 4)
        So(1, ShouldBeIn, []int{1, 2, 3})
        So(4, ShouldNotBeIn, []int{1, 2, 3})
        So([]int{}, ShouldBeEmpty)
        So([]int{1}, ShouldNotBeEmpty)
        So([]int{1, 2}, ShouldHaveLength, 2)
    })

    Convey("String assertions should be accessible", t, func() {
        So("asdf", ShouldStartWith, "a")
        So("asdf", ShouldNotStartWith, "z")
        So("asdf", ShouldEndWith, "df")
        So("asdf", ShouldNotEndWith, "as")
        So("", ShouldBeBlank)
        So("asdf", ShouldNotBeBlank)
        So("asdf", ShouldContainSubstring, "sd")
        So("asdf", ShouldNotContainSubstring, "af")
    })

    Convey("Panic recovery assertions should be accessible", t, func() {
        So(panics, ShouldPanic)
        So(func() {}, ShouldNotPanic)
        So(panics, ShouldPanicWith, "Goofy Gophers!")
        So(panics, ShouldNotPanicWith, "Guileless Gophers!")
    })

    Convey("Type-checking assertions should be accessible", t, func() {

        // NOTE: Values or pointers may be checked.  If a value is passed,
        // it will be cast as a pointer to the value to avoid cases where
        // the struct being tested takes pointer receivers. Go allows values
        // or pointers to be passed as receivers on methods with a value
        // receiver, but only pointers on methods with pointer receivers.
        // See:
        // http://golang.org/doc/effective_go.html#pointers_vs_values
        // http://golang.org/doc/effective_go.html#blank_implements
        // http://blog.golang.org/laws-of-reflection

        So(1, ShouldHaveSameTypeAs, 0)
        So(1, ShouldNotHaveSameTypeAs, "1")

        So(bytes.NewBufferString(""), ShouldImplement, (*io.Reader)(nil))
        So("string", ShouldNotImplement, (*io.Reader)(nil))
    })

    Convey("Time assertions should be accessible", t, func() {
        january1, _ := time.Parse(timeLayout, "2013-01-01 00:00")
        january2, _ := time.Parse(timeLayout, "2013-01-02 00:00")
        january3, _ := time.Parse(timeLayout, "2013-01-03 00:00")
        january4, _ := time.Parse(timeLayout, "2013-01-04 00:00")
        january5, _ := time.Parse(timeLayout, "2013-01-05 00:00")
        oneDay, _ := time.ParseDuration("24h0m0s")

        So(january1, ShouldHappenBefore, january4)
        So(january1, ShouldHappenOnOrBefore, january1)
        So(january2, ShouldHappenAfter, january1)
        So(january2, ShouldHappenOnOrAfter, january2)
        So(january3, ShouldHappenBetween, january2, january5)
        So(january3, ShouldHappenOnOrBetween, january3, january5)
        So(january1, ShouldNotHappenOnOrBetween, january2, january5)
        So(january2, ShouldHappenWithin, oneDay, january3)
        So(january5, ShouldNotHappenWithin, oneDay, january1)
        So([]time.Time{january1, january2}, ShouldBeChronological)
    })

Particularly useful test a library, develop a written code uses goconvey good habit to do the test, but also the way under cover and use cases, will allow the development of more effective, reducing the rate of Bug.

Leave a Reply