Wednesday 12 March 2014

Testbox: investigating which method/function/callback gets called when

G'day:
I had a bit of a wrestle with working out a glitch in my TestBox code y/day, and as a result ended up with a test CFC which shows where and when everything seems to run. I'll reproduce it here in case it saves anyone some time.


// TestExecutionSequence.cfc
component extends="testbox.system.testing.BaseSpec" {

    function beforeAll(){
        writeOutput("in beforeAll()<br>");
    }
    function afterAll(){
        writeOutput("in afterAll()<br>");
    }

    function run(){
        writeOutput("top of run()<br>");

        describe("outer describe", function(){
            writeOutput("top of outer describe()'s callback<br>");

            beforeEach(function(){
                writeOutput("in outer describe()'s beforeEach()<br>");
            });

            afterEach(function(){
                writeOutput("in outer describe()'s afterEach()<br>");
            });

            describe("inner describe", function(){
                writeOutput("top of inner describe()'s callback<br>");

                beforeEach(function(){
                    writeOutput("in inner describe()'s beforeEach()<br>");
                });

                afterEach(function(){
                    writeOutput("in inner describe()'s afterEach()<br>");
                });

                it("tests the negative", function(){
                    writeOutput("top of inner describe()'s first it()'s callback<br>");
                    expect(sgn(-1)).toBeLT(0);
                    writeOutput("bottom of inner describe()'s first it()'s callback<br>");
                });

                writeOutput("bottom of inner describe()'s callback<br>");
            });

            it("tests the truth", function(){
                writeOutput("top of first it()'s callback<br>");
                expect(true).toBeTrue();
                writeOutput("bottom of first it()'s callback<br>");
            });

            it("tests falsehood", function(){
                writeOutput("top of second it()'s callback<br>");
                expect(false).notToBeTrue();
                writeOutput("bottom of second it()'s callback<br>");
            });

            writeOutput("bottom of outer describe()'s callback<br>");
        });


        describe("second outer describe", function(){
            writeOutput("top of second outer describe()'s callback<br>");

            it("tests the absolute", function(){
                writeOutput("top of second outer describe()'s first it()'s callback<br>");
                expect(abs(-1)).toBe(1);
                writeOutput("bottom of second outer describe()'s first it()'s callback<br>");
            });

            writeOutput("bottom of second outer describe()'s callback<br>");
        });

        writeOutput("bottom of run()<br>");
    }

}

And here's the output (ignoring the test results, which are immaterial here):

top of run()
   top of outer describe()'s callback
     top of inner describe()'s callback
     bottom of inner describe()'s callback
   bottom of outer describe()'s callback
   top of second outer describe()'s callback
   bottom of second outer describe()'s callback
bottom of run()
in beforeAll()
    in outer describe()'s beforeEach()
        top of first it()'s callback
   
   
bottom of first it()'s callback

    in outer describe()'s afterEach()
    in outer describe()'s beforeEach()
        top of second it()'s callback
   
   
bottom of second it()'s callback
    in outer describe()'s afterEach()
        in inner describe()'s beforeEach()
        in outer describe()'s beforeEach()
            top of inner describe()'s first it()'s callback
   
        bottom of inner describe()'s first it()'s callback
        in inner describe()'s afterEach()
    in outer describe()'s afterEach()
    top of second outer describe()'s first it()'s callback
    bottom of second outer describe()'s first it()'s callback
in afterAll()


(note the indentation is not part of the original output, I just added it to try to add clarity to what's running when. I'm not sure I successed).

There's a few things to note here.

beforeAll()

I expected this to run... before everything. Before anything at all. Not just before the first test (ie: a call to the first it()'s callback). Where it runs is convenient, but I think there should be perhaps a beforeAll() and a beforeTests(), and beforeAll() should truly run before anything else.

Same with afterAll().

beforeAll() and beforeEach()

It seems slightly odd to me that beforeAll() is just a function, whereas beforeEach() is a call to a function which takes a function expression (which is then executed). I certainly didn't guess that, and had to refer to the docs.

Nested describe()

It quite cool how one can nest describe() calls, for subcategorising test output. This makes for a good visual cue when reading the results:


Anyway. That's it. Just a FYI, really.

--
Adam