I am currently writing a test suite using busted/luassert and since I have put some assertions in a separate function I am getting inaccurate stack traces. For example, consider the following test suite (a_spec.lua):

local function my_custom_assertion(x)     --  1
   assert.is_true(x > 0)                  --  2 <- 
end                                       --  3
                                          --  4
describe("My test suite", function()      --  5
    it("they are positive", function()    --  6
        my_custom_assertion(-10)          --  7 <-
        my_custom_assertion(-20)          --  8 <-
    end)                                  --  9
end)                                      -- 10

When I run it, my test case fails but the stack trace points to line 2 so I can't tell which of the two assertions was the one that failed.

$busted spec/a_spec.lua 
◼
0 successes / 1 failure / 0 errors / 0 pending : 0.002242 seconds

Failure → spec/a_spec.lua @ 6
My test suite they are positive
spec/a_spec.lua:2: Expected objects to be the same.
Passed in:
(boolean) false
Expected:
(boolean) true

Is there a way I could have it point to line 7 or 8 instead? One way this would be possible is if luassert's assert.is_true function had a level parameter similar to the builtin error function.

Looking at luassert's source code it seems that it does care about the stack level but I haven't been able to figure out if this feature is internal or if it is exposed to the user somehow.

2

There are 2 best solutions below

0
On BEST ANSWER

Turns out that there is a way to solve my actual problem of finding out which of the assertions was the one that fired without needing to change how I write my tests. By invoking busted with the -v (--verbose) option it prints a full stack trace when an assertion fails instead of just providing a single line number.

$ busted -v spec/a_spec.lua

0 successes / 1 failure / 0 errors / 0 pending : 0.003241 seconds

Failure → spec/a_spec.lua @ 6
My test suite they are positive
spec/a_spec.lua:2: Expected objects to be the same.
Passed in:
(boolean) false
Expected:
(boolean) true

stack traceback:
    spec/a_spec.lua:2: in upvalue 'my_custom_assertion'
    spec/a_spec.lua:7: in function <spec/a_spec.lua:6>

That mention of line number 7 lets me know what assertion was the one that failed.

2
On

Instead of creating a custom assertion by creating a function that calls assert.xyzz(), create a function that returns true or false and register it with assert:register.

See the second example in the README.