Skip to content

Add flaky test mark #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Check docs generation with LDoc.
- Add `--repeat-group` (`-R`) option to run tests in a circle within the group.
- Add `flaky` test mark.

## 0.5.7

Expand Down
18 changes: 18 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ List of luatest functions
+--------------------------------------------------------------------+-----------------------------------------------+
| ``xfail_if (condition, message)`` | Mark test as xfail if condition is met. |
+--------------------------------------------------------------------+-----------------------------------------------+
| ``flaky (message)`` | Mark test as flaky. |
+--------------------------------------------------------------------+-----------------------------------------------+
| ``skip (message)`` | Skip a running test. |
+--------------------------------------------------------------------+-----------------------------------------------+
| ``skip_if (condition, message)`` | Skip a running test if condition is met. |
Expand Down Expand Up @@ -283,6 +285,22 @@ keep xfail tests in sync with an issue tracker.
XFail only applies to the errors raised by the luatest assertions. Regular Lua
errors still cause the test failure.

.. _xfail:

---------------------------------
Flaky
---------------------------------

The ``flaky`` mark can be used to temporarily remove flaky error from your tests.

.. code-block:: Lua

local g = t.group()
g.test_fail = function()
t.flaky("Can be failed and I don't know why ")
t.assert_equals(1, math.random(0,1))
end

.. _capturing-output:

---------------------------------
Expand Down
16 changes: 16 additions & 0 deletions luatest/assertions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ local prettystr_pairs = pp.tostring_pair
local M = {}

local xfail = false
local flaky = false

-- private exported functions (for testing)
M.private = {}
Expand All @@ -26,6 +27,13 @@ function M.private.is_xfail()
return xfail_status
end


function M.private.is_flaky()
local flaky_status = flaky
flaky = false
return flaky_status
end

--[[--

EPS is meant to help with Lua's floating point math in simple corner
Expand Down Expand Up @@ -169,6 +177,14 @@ function M.xfail_if(condition, message)
end
end

--- Mark a test as xfail if condition is met
--
-- @param condition
-- @string message
function M.flaky(message)
flaky = message or true
end

--- Check that two values are equal.
-- Tables are compared by value.
--
Expand Down
7 changes: 5 additions & 2 deletions luatest/output/generic.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ end
-- luacheck: pop

function Output.mt:status_line(colors)
colors = colors or {success = '', failure = '', reset = '', xfail = ''}
colors = colors or {success = '', failure = '', reset = '', xfail = '', flaky = ''}
-- return status line string according to results
local tests = self.result.tests
local s = {
Expand All @@ -69,7 +69,10 @@ function Output.mt:status_line(colors)
if #tests.error > 0 then
table.insert(s, string.format("%s%d %s%s", colors.failure, #tests.error, 'errored', colors.reset))
end
if #tests.fail == 0 and #tests.error == 0 and #tests.xsuccess == 0 then
if #tests.flaky > 0 then
table.insert(s, string.format("%s%d %s%s", colors.flaky, #tests.flaky, 'flaky', colors.reset))
end
if #tests.fail == 0 and #tests.error == 0 and #tests.xsuccess == 0 and #tests.flaky == 0 then
table.insert(s, '0 failed')
end
if #tests.skip > 0 then
Expand Down
1 change: 1 addition & 0 deletions luatest/output/text.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function Output.mt:end_suite()
failure = self.class.ERROR_COLOR_CODE,
reset = self.class.RESET_TERM,
xfail = self.class.WARN_COLOR_CODE,
flaky = self.class.WARN_COLOR_CODE,
}))
if self.result.notSuccessCount == 0 then
print('OK')
Expand Down
11 changes: 9 additions & 2 deletions luatest/runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ function Runner.mt:start_suite(selected_count, not_selected_count)
skip = {},
xfail = {},
xsuccess = {},
flaky = {},
},
}
self.output.result = self.result
Expand All @@ -324,7 +325,7 @@ function Runner.mt:update_status(node, err)
elseif not node:is('success') then
return
elseif err.status == 'fail' or err.status == 'error' or err.status == 'skip'
or err.status == 'xfail' or err.status == 'xsuccess' then
or err.status == 'xfail' or err.status == 'xsuccess' or err.status == 'flaky' then
node:update_status(err.status, err.message, err.trace)
else
error('No such status: ' .. pp.tostring(err.status))
Expand All @@ -340,7 +341,7 @@ function Runner.mt:end_test(node)
if node:is('error') or node:is('fail') or node:is('xsuccess') then
self.result.aborted = self.fail_fast
elseif not node:is('success') and not node:is('skip')
and not node:is('xfail') then
and not node:is('xfail') and not node:is('flaky') then
error('No such node status: ' .. pp.tostring(node.status))
end
end
Expand Down Expand Up @@ -377,6 +378,7 @@ function Runner.mt:protected_call(instance, method, pretty_name)

-- check if test was marked as xfail and reset xfail flag
local xfail = assertions.private.is_xfail()
local flaky = assertions.private.is_flaky()

if type(err.message) ~= 'string' then
err.message = pp.tostring(err.message)
Expand All @@ -399,6 +401,11 @@ function Runner.mt:protected_call(instance, method, pretty_name)
return err
end

if flaky and err.status ~= 'error' and err.status ~= 'skip' then
err.status = 'flaky'
return err
end

-- reformat / improve the stack trace
if pretty_name then -- we do have the real method name
err.trace = err.trace:gsub("in (%a+) 'method'", "in %1 '" .. pretty_name .. "'")
Expand Down
40 changes: 40 additions & 0 deletions test/flaky_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
local t = require('luatest')
local g = t.group()

local helper = require('test.helper')

g.test_failed = function()
local result = helper.run_suite(function(lu2)
local pg = lu2.group('flaky')
pg.test_fail = function()
lu2.flaky()
lu2.assert_equals(2 + 2, 5)
end
end)

t.assert_equals(result, 0)
end

g.test_succeeded = function()
local result = helper.run_suite(function(lu2)
local pg = lu2.group('flaky')
pg.test_success = function()
lu2.flaky()
lu2.assert_equals(2 + 3, 5)
end
end)

t.assert_equals(result, 0)
end

g.test_error = function()
local result = helper.run_suite(function(lu2)
local pg = lu2.group('flaky')
pg.test_error = function()
lu2.flaky()
error('Boom!')
end
end)

t.assert_equals(result, 1)
end