ginkgo
ginkgo copied to clipboard
How can I implement "BeforeEachContext"?
I'm looking for a way to run some code for each Context
but not for the It
s 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
})
})
})
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?
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).
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.
v2.0 will support BeforeAll
- you can get to the proposal doc in #711 to learn more about what that support will look like.