Fixes #3627.
---
branch: Totktonada/gh-3627-tap-show-local-variables
travis-ci: https://travis-ci.org/tarantool/tarantool/builds/417616160
issue: https://github.com/tarantool/tarantool/issues/3627
src/lua/tap.lua | 45 ++++++++++++++++++++++++++++++++++-----
test/app-tap/tap.result | 26 ++++++++++++++++++++--
test/app-tap/tap.test.lua | 21 +++++++++++++++---
3 files changed, 82 insertions(+), 10 deletions(-)
diff --git a/src/lua/tap.lua b/src/lua/tap.lua
index edc9f2211..9dd531422 100644
--- a/src/lua/tap.lua
+++ b/src/lua/tap.lua
@@ -1,6 +1,6 @@
--- tap.lua internal file
---
---- The Test Anything Protocol vesion 13 producer
+--- The Test Anything Protocol version 13 producer
---
-- yaml formatter must be able to encode any Lua variable
@@ -36,12 +36,43 @@ local function traceback(level)
return trace
end
+local function locals(test, level)
+ level = level or 3
+ local variables = {}
+ local idx = 1
+ while true do
+ local name, value = debug.getlocal(level, idx)
+ if name ~= nil then
+ -- compare a table with a tuple raises an error, so we check types
+ -- first
+ local eq = type(value) == type(test) and value == test
+ -- temporary values start with '('
+ if not name:startswith('(') and not eq then
+ variables[name] = value
+ end
+ else
+ break
+ end
+ idx = 1 + idx
+ end
+ return variables
+end
+
local function diag(test, fmt, ...)
io.write(string.rep(' ', 4 * test.level), "# ", string.format(fmt, ...),
"\n")
end
-local function ok(test, cond, message, extra)
+local function ok(test, cond, message, extra, opts)
+ opts = opts or {}
+ local show_locals
+ if opts.locals ~= nil then
+ show_locals = opts.locals
+ elseif test.locals ~= nil then
+ show_locals = test.locals
+ else
+ show_locals = true
+ end
test.total = test.total + 1
io.write(string.rep(' ', 4 * test.level))
if cond then
@@ -58,6 +89,9 @@ local function ok(test, cond, message, extra)
extra.filename = extra.trace[#extra.trace].filename
extra.line = extra.trace[#extra.trace].line
end
+ if show_locals then
+ extra.locals = locals(test)
+ end
if next(extra) == nil then
return false -- don't have extra information
end
@@ -221,6 +255,7 @@ local function test(parent, name, fun, ...)
failed = 0;
planned = 0;
trace = parent == nil and true or parent.trace;
+ locals = parent == nil and true or parent.locals;
}, test_mt)
if fun ~= nil then
test:diag('%s', test.name)
@@ -245,7 +280,7 @@ local function check(test)
if test.planned ~= test.total then
if test.parent ~= nil then
ok(test.parent, false, "bad plan", { planned = test.planned;
- run = test.total})
+ run = test.total}, {locals = false})
else
diag(test, string.format("bad plan: planned %d run %d",
test.planned, test.total))
@@ -255,13 +290,13 @@ local function check(test)
ok(test.parent, false, "failed subtests", {
failed = test.failed;
planned = test.planned;
- })
+ }, {locals = false})
else
diag(test, "failed subtest: %d", test.failed)
end
else
if test.parent ~= nil then
- ok(test.parent, true, test.name)
+ ok(test.parent, true, test.name, {locals = false})
end
end
return test.planned == test.total and test.failed == 0
diff --git a/test/app-tap/tap.result b/test/app-tap/tap.result
index 3e7882331..36caa3023 100644
--- a/test/app-tap/tap.result
+++ b/test/app-tap/tap.result
@@ -1,5 +1,5 @@
TAP version 13
-1..32
+1..33
ok - true
ok - extra information is not printed on success
not ok - extra printed using yaml only on failure
@@ -148,4 +148,26 @@ not ok - failed subtests
ok - unlike(abcde, acd)
# like: end
ok - like
-# failed subtest: 15
+ # locals
+ 1..1
+ # locals nested
+ 1..2
+ ok - locals are not printed in case of success
+ not ok - locals are printed in case of fail
+ ---
+ locals:
+ a: 42
+ ...
+ # locals nested: end
+ not ok - failed subtests
+ ---
+ planned: 2
+ failed: 1
+ ...
+ # locals: end
+not ok - failed subtests
+ ---
+ planned: 1
+ failed: 1
+ ...
+# failed subtest: 16
diff --git a/test/app-tap/tap.test.lua b/test/app-tap/tap.test.lua
index 0e1de7f1c..29dc0b100 100755
--- a/test/app-tap/tap.test.lua
+++ b/test/app-tap/tap.test.lua
@@ -12,15 +12,16 @@ local tap = require "tap"
-- Create a root test
--
test = tap.test("root test")
--- Disable stack traces for this test because Tarantool test system also
--- checks test output.
+-- Disable stack traces and locals for this test because Tarantool test system
+-- also checks test output.
test.trace = false
+test.locals = false
--
-- ok, fail and skip predicates
--
-test:plan(32) -- plan to run 3 test
+test:plan(33) -- plan to run 3 test
test:ok(true, 'true') -- basic function
local extra = { state = 'some userful information to debug on failure',
details = 'a table argument formatted using yaml.encode()' }
@@ -136,6 +137,20 @@ test:test('like', function(t)
t:unlike('abcde', 'acd', 'unlike(abcde, acd)')
end)
+-- The test case implicitly checks that locals will not be printed while
+-- checking the plan.
+test:test('locals', function(t)
+ t.locals = true
+ t:plan(1)
+ t:test('locals nested', function(t)
+ local a = 42
+ local tuple = box.tuple.new({})
+ t:plan(2)
+ t:ok(true, 'locals are not printed in case of success')
+ t:fail('locals are printed in case of fail')
+ end)
+end)
+
--
-- Finish root test. Since we used non-callback variant, we have to
-- call check explicitly.
--
2.17.1