smartystreets/goconvey — pull request #199 by m4rw3r (2014-05-14 10:15:10+00:00)
Title: Unique closure variables per Convey invocation

Currently all tests require the test-writer to declare a variable outside the outermost ``Convey``-block to be able to reinitialize the data for every nested test:

```go
func TestNestingVar(t *testing.T) {
j := 0

var i int

Convey("A", t, func() {
j = j + 1
i = j

Convey("B", func() {
So(i, ShouldEqual, 1)
})

Convey("C", func() {
So(i, ShouldEqual, 2)
})
})
}
```

This pollutes the scope and also makes it slightly less intuitive for reasoning about what data is present in the nested ``Convey``-blocks. And in the worst case the writer might forget to reset the data in this "test-global" variable before the following tests, creating a possibility for test failures to cascade due to shared state.

This pull request enables the tests to be written like this:

```go
func TestNesting(t *testing.T) {
j := 0

Convey("A", t, func() {
j = j + 1
i := j

Convey("B", func() {
So(i, ShouldEqual, 1)
})

Convey("C", func() {
So(i, ShouldEqual, 2)
})
})
}
```

With the ``i`` variable above being properly enclosed in the nested closures, so that ``B`` gets the ``i`` from the first invocation of ``A`` and ``C`` gets the second instance of the ``i``.

The way this has been solved is that every time a nested ``Convey``-block executes it replaces the nested actions, so that every new execution of ``A`` will update both ``B`` and ``C`` above. Thanks to the execution order it will use the correct closure.