Skip to content

Commit

Permalink
chore(tests): improve test runner system
Browse files Browse the repository at this point in the history
* Implements an extension to frktest's `lune_console_reporter` for
  displaying status of individual running test cases and suites -- with
  colors :O!
* Include mechanism for running select tests using the test runner
  script.
  • Loading branch information
CompeyDev committed Dec 2, 2024
1 parent ba5d496 commit ac5b8f9
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 20 deletions.
57 changes: 45 additions & 12 deletions .lune/test.luau
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,54 @@ local fs = require("@lune/fs")
local process = require("@lune/process")

local frktest = require("@pkg/frktest")
local reporter = require("../tests/_reporter")

-- HACK: Cast require to allow for dynamic paths in strict mode
-- A more proper solution would be to use luau.load instead, but
-- frktest requires its global state to be modified by test suites
local require = require :: (path: string) -> () -> ()

if process.args[1] ~= nil then
require("../tests/" .. process.args[1])()
else
for _, test in fs.readDir("tests") do
require("../tests/" .. test)()
end
end
local require = require :: (
path: string
) -> (
test: typeof(setmetatable(
{} :: {
case: (name: string, fn: () -> nil) -> (),
suite: (name: string, fn: () -> ()) -> (),
},
{ __index = frktest.test }
))
) -> ()

local allowed_tests = process.args
for _, test in fs.readDir("tests") do
-- If we are given any arguments, we only run those tests, otherwise,
-- we run all the tests

-- So, to include only a certain set of test files, you can provide either
-- the full path to the test file (with or without the extension) or the test
-- file name
local withoutExt = string.sub(test, 1, -6)
local is_allowed = #process.args == 0
or table.find(allowed_tests, `tests/{test}`)
or table.find(allowed_tests, withoutExt)
or table.find(allowed_tests, `tests/{withoutExt}`)

local constructors = {
case = frktest.test.case,
suite = frktest.test.suite,
}

frktest._reporters.lune_console_reporter.init()
if not frktest.run() then
process.exit(1)
if not is_allowed then
constructors.case = frktest.test.skip.case
constructors.suite = frktest.test.skip.suite
end

-- Ignore files starting with underscores, eg: _reporter.luau
if string.sub(test, 1, 1) == "_" then
continue
end

require("../tests/" .. test)(setmetatable(constructors, { __index = frktest.test }))
end

reporter.init()
process.exit(tonumber(frktest.run()))
55 changes: 55 additions & 0 deletions tests/_reporter.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
local stdio = require("@lune/stdio")

local frktest = require("@pkg/frktest")
local Reporter = frktest._reporters.lune_console_reporter

local STYLE = table.freeze({
suite = function(name: string)
return `{stdio.style("bold")}{stdio.color("purple")}SUITE{stdio.style("reset")} {name}`
end,

report = function(name: string, state: "run" | "success" | "error" | "skip")
local state_color: stdio.Color = if state == "run"
then "white"
elseif state == "success" then "green"
elseif state == "error" then "red"
elseif state == "skip" then "yellow"
else error("Invalid test state")
return ` {stdio.style("bold")}{stdio.color(state_color)}{if state == "skip" then "SKIP" else "TEST"}{stdio.style(
"reset"
)} {name}`
end,
})

--- Clears a the previous line, and moves to its beginning
local function clear_last_line(): ()
return stdio.write("\x1b[A\x1b[K\x1b[0G\x1b[?25h")
end

local ReporterExt = {}
function ReporterExt.init()
frktest.test.on_suite_enter(function(suite)
print(STYLE.suite(suite.name))
end)

frktest.test.on_suite_leave(function()
stdio.write("\n")
end)

frktest.test.on_test_enter(function(test)
print(STYLE.report(test.name, "run"))
end)

frktest.test.on_test_leave(function(test)
clear_last_line()
print(STYLE.report(test.name, if test.failed then "error" else "success"))
end)

frktest.test.on_test_skipped(function(test)
print(STYLE.report(test.name, "skip"))
end)

Reporter.init()
end

return setmetatable(ReporterExt, { __index = Reporter })
3 changes: 1 addition & 2 deletions tests/cmp.luau
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
local frktest = require("@pkg/frktest")
local test = frktest.test
local check = frktest.assert.check

local Option = require("../luau_packages/option")
type Option<T> = Option.Option<T>

local Semver = require("../lib")

return function()
return function(test: typeof(frktest.test))
test.suite("Semver comparison tests", function()
test.case("Basic version comparisons", function()
local v1 = Semver.parse("1.2.3"):unwrap()
Expand Down
3 changes: 1 addition & 2 deletions tests/parse_invalid.luau
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
local frktest = require("@pkg/frktest")
local test = frktest.test
local check = frktest.assert.check

local Semver = require("../lib")

return function()
return function(test: typeof(frktest.test))
test.suite("Invalid semver parsing tests", function()
test.case("Rejects missing components", function()
local res = Semver.parse("1.2")
Expand Down
3 changes: 1 addition & 2 deletions tests/parse_valid.luau
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
local frktest = require("@pkg/frktest")
local test = frktest.test
local check = frktest.assert.check

local Option = require("../luau_packages/option")
type Option<T> = Option.Option<T>

local Semver = require("../lib")

return function()
return function(test: typeof(frktest.test))
test.suite("Basic tests", function()
test.case("Semver creates valid version objects", function()
local res = Semver.parse("1.2.3-beta.1")
Expand Down
3 changes: 1 addition & 2 deletions tests/tostring.luau
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
local frktest = require("@pkg/frktest")
local test = frktest.test
local check = frktest.assert.check

local Option = require("../luau_packages/option")
type Option<T> = Option.Option<T>

local Semver = require("../lib")

return function()
return function(test: typeof(frktest.test))
test.suite("Stringification tests", function()
test.case("A version constructed with new() when stringified should match expected string", function()
local versionMap: { [string]: Semver.Version } = {
Expand Down

0 comments on commit ac5b8f9

Please sign in to comment.