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.