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?
You would see the first behavior, because the enclosing scope of the defer
s is the same anonymous function as the previous Println
. defer
red functions get called when exiting the scope.
"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
.
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