Writing unit tests when the func calls panic()
It's a new year and you've decide to step up your unit testing game. Life is good as a Go programer, since Go comes with an awesome test package in the standard library - https://golang.org/pkg/testing
This is great. There's no reason to re-invent the wheel. No really, please don't write yet another test package. You're not that special and your software isn't super special as well. Please, I'm begging you to use the standard lib solution. DevOps and every other person that maintains your software in the future will curse your name forever if you decide to roll your own.
So that's settled, you're writing some unit tests using the Go testing package, and you stubble into this function:
func mustExist(varValue string, varName string) {
if len(varValue) == 0 {
panic(varName + " not set")
}
}
func mustExist(varValue string, varName string) {
if len(varValue) == 0 {
panic(varName + " not set")
}
}
You have so many questions at this point. First, why would someone write this func? What were they thinking? Don't they know you should never panic? Haven't they seen Mat Ryer's presentation: Things in Go I never use Even though you have all these questions, you realize that you probably should refactor this thing, since it's used a LOT in this thing you're writing unit tests for.
So, how are you going write unit tests for this thing? The first time you send it bad data, it's going to panic and your tests are going to come to a screeching halt.
func TestPanic(t *testing.T) {
mustExist("", "what the heck")
}
So, how are you going write unit tests for this thing? The first time you send it bad data, it's going to panic and your tests are going to come to a screeching halt.
func TestPanic(t *testing.T) {
mustExist("", "what the heck")
}
--- FAIL: TestPanic (0.00s)
panic: what the heck not set [recovered]
panic: what the heck not set
Yep, just as we feared. But don't fret, there's a simple solution to this problem: defer and recover. This is straight from the go wiki: panic causes the program stack to begin unwinding and recover can stop it.
Now we can stop panicking and just write the unit test:
func Test_mustExist(t * testing.T) {
tests: = [] struct {
name string
varValue string
varName string
wantPanic bool
} {
{
name: "mom",
varValue: "hi",
varName: "mom",
wantPanic: false
}, {
name: "panic",
varValue: "",
varName: "panic",
wantPanic: true
},
}
for _,
tt: = range tests {
t.Run(tt.name, func(t * testing.T) {
func() {
defer func() {
if err: = recover();
err != nil {
if !tt.wantPanic {
t.Errorf("Unexpected panic")
}
}
}()
mustExist(tt.varValue, tt.varName)
}()
})
}
}
Yep, go is pretty sweet. Even when you're completely panicked, it provides an elegant clear solution.
Happy New Year.
Happy New Year.
No comments:
Post a Comment