goconvey icon indicating copy to clipboard operation
goconvey copied to clipboard

How to organize complicated test

Open caibirdme opened this issue 3 years ago • 1 comments

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?

caibirdme avatar Jul 21 '21 11:07 caibirdme

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?

caioaao avatar Oct 22 '21 19:10 caioaao