goconvey
goconvey copied to clipboard
How to organize complicated test
Say there's a function called RecommentBlogsForUser
, it will :
- check if the user is logged in
- get user info from redis
- query user age from db
- query user tag from tag system by age
- get blogs from recommend system by user tag...
It's not real, but what I mean is that the business logic is a little complicated sometimes.
So when I write test code for this function, I should do like this:
Convey("given a user request", t, func() {
req := initReq() // ...
Convey("when user is logged in", func() {
monkeyPatch(CheckLogin).Expect().Return(expectResult)
Convey("when get user info success from redis", func() {
monkeyPatch(RedisClient).Expect().Return(xxx)
Convey("query user age from db success", func() {
monkeyPatch(DB).Expect().Return(xxx)
Convey("when query user tag from tag system by age success", func() {
monkeyPatch(RPC).Expect().Return(xxx)
Convey("when get blogs from recommend system by user tag success", func() {
actual := F(req)
So(atual, ShouldEqual, expect)
})
})
})
})
})
})
This reminds me of callback hell!!
So are there any better ways to write test code for those complicated business logic function?
Completely new to this library, but I'd just combine Convey
clauses if you don't have to test other cases inside it, like so:
Convey("given a user request", t, func() {
req := initReq() // ...
Convey("when user is logged in", func() {
monkeyPatch(CheckLogin).Expect().Return(expectResult)
Convey("when user tag by age is x", func() {
monkeyPatch(RedisClient).Expect().Return(xxx)
monkeyPatch(DB).Expect().Return(xxx)
monkeyPatch(RPC).Expect().Return(xxx)
Convey("get blogs from recommend system by user tag succeeds", func() {
actual := F(req)
So(atual, ShouldEqual, expect)
})
})
})
})
and just branch them out if I wanted to test something else, in which case you either have this deeply nested structure or you'll have to duplicate code, at which point I guess it's just a style preference?