ginkgo icon indicating copy to clipboard operation
ginkgo copied to clipboard

How can I implement "BeforeEachContext"?

Open digulla opened this issue 4 years ago • 4 comments

I'm looking for a way to run some code for each Context but not for the Its inside. Example:

package main

import (
    . "github.com/onsi/ginkgo"
    . "github.com/onsi/gomega"
)

var _ = Describe("Per Context Setup", func() {
    var outerCount int;

    // Maybe "BeforeEachContext"?
    BeforeEach(func() {
        outerCount = 1;
    })

    Context("Context 1", func() {
        var innerCount int;

        BeforeEach(func() {
            innerCount = 1;
        })

        It("counters are initialized", func() {
            Expect(outerCount).To(Equal(1))
            Expect(innerCount).To(Equal(1))

            outerCount ++;
            innerCount ++;

            Expect(outerCount).To(Equal(2))
            Expect(innerCount).To(Equal(2))
        })
        It("outerCount is still 2", func() {
            Expect(innerCount).To(Equal(1)) // Correct
            Expect(outerCount).To(Equal(2)) // <<-- Id't like this succeed
        })
    })
})

digulla avatar Nov 25 '19 15:11 digulla

Would it be fair to say you are describing the behaviour of BeforeAll that would exist in other BDD libraries? This has been discussed a few times before: https://github.com/onsi/ginkgo/issues?utf8=%E2%9C%93&q=is%3Aissue+BeforeAll

Can you describe in less abstract terms what you are trying to achieve?

williammartin avatar Dec 11 '19 17:12 williammartin

Many unit testing frameworks execute tests in random order. This causes problems when you have to set up an expensive object and then test various aspects of it. Most common example: Create test database (not just a connection but creating a new, empty database, create&populate tables, et).

A lot of tests skip this setup step and expect that someone else somehow created a "good" database which makes them brittle. My approach to have code which can create a test database from scratch is more stable (for example, you can share business keys between the setup and test code to look up entities) but it's too slow to run in every test step.

Another case is creating a private blockchain for subset of tests and then deploy a few contracts to them.

Those operations take too much time to do them for every single test. On the other hand, I need to do them more than once with small changes, for example to test error handling when an important database table is missing / has wrong permissions: Does the code fail gracefully?

That's why I often encounter situations where I have to be able to group tests by "test environment" and then run a few tests per group in order.

In my case, after creating the private blockchain and put some data onto it, I need to do operations which depend on each other. So the first operation could be to make sure something fails when a smart contract isn't deployed. Then I deploy the smart contract, making sure this works. Then I start calling methods on the smart contract.

Ideally, there should be a way to say "stop the group when a test fails" but the workaround (look at failures in order) works for me.

I would like to be able to call the same methods with different environments, say permissions, to see when they work and when they fail (and how they fail).

Note that this somewhat breaks the concept of unit tests but when it comes to smart contracts on the blockchain, you eventually need a few tests that execute the actual contract on a private instance of the blockchain to test error handling and other weird stuff. Unit tests alone simply are not enough because the mock often isn't complete (a lot of blockchain code is happy-path software).

digulla avatar Dec 12 '19 12:12 digulla

Adding BeforeAll has a rich long contentious history in Ginkgo - and I'm considering alternatives to enable it. Often times, @digulla, I've accomplished exactly what you're describing by using BeforeSuite to set up all the expensive stuff once at the beginning of the suite and using cheaper alternatives (e.g. clearing out tables or reverting back to a known good state) before each test. To speed things up, I think enable test parallelization by having BeforeSuite set up sharded environments that key off of the GinkgoParallelNode() index.

onsi avatar Jun 16 '20 15:06 onsi

v2.0 will support BeforeAll - you can get to the proposal doc in #711 to learn more about what that support will look like.

onsi avatar Apr 05 '21 12:04 onsi