On Github mkboudreau / meetup-june2014
Presented by Michael Boudreau
1. Java Dev - IBM - 15 Years this November 2. Married, 3 Boys (3,5,7) who keep me busy 3. GO - 2 1/2 Months - In Spare Time 4. So if you're sittin there wondering why I'm up here, rest assured ---- I'm wondering the same thingTest Frameworks (if we have time)
Out of Scope
Test Strategy & Practices
(i.e. tdd vs bdd or when to mock, stub, spy, dummy, or fake)
How to test specific Go types
(i.e. channels, interfaces, structs, slices)
$ go test
// lottery.go package lottery func ProduceSixLotteryNumbers() []int { return []int{4,8,15,16,23,42} }1.
// lottery_test.go package lottery import ( "testing" ) func TestXxx(t *testing.T) { //... }1.
// lottery.go package lottery func ProduceSixLotteryNumbers() []int { return []int{4,8,15,16,23,42} }
// lottery_test.go package lottery func TestProduceSixLotteryNumbers(t *testing.T) { lottery := ProduceSixLotteryNumbers() if lottery == nil { t.Errorf("lottery should not be nil") } else if len(lottery) != 6 { t.Errorf("expected lottery to be size 6, but was %v", len(lottery)) } }1.
$ go test $ go test -v1. github.com/mkboudreau/meetup-june2014/code/lottery 2. go test 3. go test -v
$ go test -bench .
// lottery_test.go package lottery import ( "testing" ) func BenchmarkXxx(b *testing.B) { for i := 0; i < b.N; i++ { // } }1.
func TestProduceSixLotteryNumbers(t *testing.T) { lottery := ProduceSixLotteryNumbers() if lottery == nil { t.Errorf("lottery should not be nil") } else if len(lottery) != 6 { t.Errorf("expected lottery to be size 6, but was %v", len(lottery)) } } func BenchmarkProduceSixLotteryNumbers(b *testing.B) { for i := 0; i < b.N; i++ { ProduceSixLotteryNumbers() } }1.
$ go test -cover
$ go test -coverprofile=cover.out
$ go tool cover -func=cover.out
$ go tool cover -html=cover.out
$ go test -race
type TaskData struct { In <-chan interface{} Out chan<- interface{} Error chan<- error } type TaskRunner interface { Run(data *TaskData) } func RunTask(data *TaskData, runner TaskRunner) { go func() { defer close(data.Out) runner.Run(data) }() }
in := make(chan interface{}) out := make(chan interface{}) err := make(chan error) taskData := &TaskData{ In: in, Out: out, Error: err, } RunTask(taskData, &FilterString{Filter: "HELLO"}) go func() { in <- "TESTING A" in <- "123" in <- "HELLO" in <- "456" in <- "TESTING B" close(in) }()
func ChainTasks(data *TaskData, runners ...TaskRunner) { for i, runner := range runners { if i < len(runners)-1 { ch := make(chan interface{}) RunTask(&TaskData{In: data.In, Out: ch, Error: data.Error}, runner) data.In = ch } else { RunTask(&TaskData{In: data.In, Out: data.Out, Error: data.Error}, runner) } } }
================== WARNING: DATA RACE Write by goroutine 5: // ... Previous read by goroutine 7: // ... Goroutine 5 (running) created at: // ... Goroutine 7 (running) created at: // ... ================== .........................................PASS Found 1 data race(s)
Write by goroutine 5: runtime.closechan() .../code/taskrunner.func 001() .../code/taskrunner/taskrunner.go:22 +0xba
Previous read by goroutine 7: runtime.chansend() .../code/taskrunner.adaptStringChannelToInterfaceChannel() .../code/taskrunner/taskrunner_string.go:47 +0xbd
.../code/taskrunner.func 001() /Users/.../code/taskrunner/taskrunner.go:22 +0xba
func RunTask(data *TaskData, runner TaskRunner) { go func() { defer close(data.Out) runner.Run(data) }() // line 22 }
.../code/taskrunner.adaptStringChannelToInterfaceChannel() /Users/.../code/taskrunner/taskrunner_string.go:47 +0xbd
func adaptStringChannelToInterfaceChannel(in <-chan string, out chan<- interface{}, err chan<- error) { defer close(out) for someString := range in { out <- someString // line 47 } }
package helloworld import ( "fmt" ) func Example() { result := DoSomething() fmt.Println(result) // Output: Hello }1.
Package Level Example
func Example() {}
Example for Function
func ExampleFuncName() {}
Example for Type
func ExampleTypeName() {}
Example for Method on Type
func ExampleTypeName_MethodName() {}
Example for Variant of Function (applies to all)
func ExampleFuncName_variation() {}
godoc -http=:8888
func TestExamplePackage(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Example Package Suite") }
var _ = Describe("some description.... ", func() { Context("Some context....", func() { It("Should work with table-driven tests", func() { for _, testcase := range testcases { actual := MyFunction(testcase.input) Expect(actual).ToNot(BeNil()) Expect(actual).To(Equal(testcase.expected)) } }) It("Should be nil with the text inconceivable", func() { badTestCase := "inconceivable" actual := MyFunction(badTestCase) Expect(actual).To(BeNil()) }) }) })1.
func TestSpec(t *testing.T) { Convey("Given some integer with a starting value", t, func() { x := 1 Convey("When the integer is incremented", func() { x++ Convey("The value should be greater by one", func() { So(x, ShouldEqual, 2) }) }) }) }1.