when defer func is executed at ginkgo

4/3/2020

I'm rewriting unit test of our k8s controller with ginkgo.

As previous TDD, for each test, we will have something like.

    // Create the Channel  object and expect the Reconcile
    g.Expect(c.Create(context.TODO(), myObj)).NotTo(gomega.HaveOccurred())
    defer c.Delete(context.TODO(),myObj)

What we want is, create an object for a test and delete it from the underline cluster after this test.

Now, on ginkgo, we are running tests within spec of containers. To me the container is the origin process, if that's the case does it mean the defer defined within the It spec will execute before exiting container instead of exiting the It spec.

For example,

var _ = Describe("my desr", func(){
   It("a", func(){
     fmt.Println(100)
     defer func(){fmt.Println("a", 100)}()
   })

   It("b", func(){
     fmt.Println(200)
     defer func(){fmt.Println("b", 200)}()
  })
})

Would the result be:

a

100
a100
200
b200

Or

b

100
200
b200
a100

In my case, I definitely what the first behavior. Or I'm in the wrong direction in terms of getting the defer behavior? I mean, should I look into the BeforeEach and AfterEach approach?

-- Ian Zhang
ginkgo
go
kubernetes

3 Answers

4/4/2020

You would see the first behavior, because the enclosing scope of the defers is the same anonymous function as the previous Println. deferred functions get called when exiting the scope.

-- Oppen
Source: StackOverflow

4/4/2020

"Origin process" has nothing to do with it. Defer statements run when the surrounding function returns. In your case, the surrounding function is your anonymous func() passed to (and called by) It.

-- hobbs
Source: StackOverflow

4/3/2020

Do you plan to run tests in parallel? If so, then results will be unpredictable. In that case it's recommended to have a separate instance of external resources for each process.

I would recommend to look at how controller tests are implemented in controller-runtime. I believe, they create new Control Plane with envtest each time BeforeSuit function is called. And as ginkgo docs states:

when running in parallel, each parallel process will run BeforeSuite and AfterSuite functions

-- Grigoriy Mikhalkin
Source: StackOverflow