Changed test framework to not require outside deps
This commit is contained in:
parent
f4298b02be
commit
33d080f6c6
7
Makefile
7
Makefile
@ -14,7 +14,8 @@ all: $(EXE)
|
||||
|
||||
$(EXE): $(SRC)
|
||||
echo "#!/usr/bin/env lua" > $@
|
||||
LUA_PATH="./src/?.lua;./src/?/init.lua" FENNEL_PATH="./src/?.fnl;./src/?/init.fnl" \
|
||||
LUA_PATH="./src/?.lua" \
|
||||
FENNEL_PATH="./src/?.fnl" \
|
||||
$(FENNEL) --require-as-include --compile src/fennel-ls.fnl >> $@
|
||||
chmod 755 $@
|
||||
|
||||
@ -22,8 +23,8 @@ clean:
|
||||
rm -f $(EXE)
|
||||
|
||||
test:
|
||||
# requires busted to be installed
|
||||
FENNEL_PATH="./src/?.fnl;./src/?/init.fnl" $(FENNEL) --correlate test/init.fnl --verbose
|
||||
LUA_PATH="./src/?.lua;./?.lua" FENNEL_PATH="./src/?.fnl;./?.fnl" \
|
||||
$(FENNEL) test/init.fnl
|
||||
|
||||
install: $(EXE)
|
||||
mkdir -p $(DESTDIR)$(BIN_DIR) && cp $< $(DESTDIR)$(BIN_DIR)/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: view} (require :fennel))
|
||||
(local {: ROOT-URI
|
||||
@ -20,7 +20,7 @@
|
||||
suggestion.label suggestion.label)]
|
||||
(if expected
|
||||
(each [_ exp (ipairs expected)]
|
||||
(is.truthy (. seen exp) (.. exp " was not suggested, but should be"))))
|
||||
(is (. seen exp) (.. exp " was not suggested, but should be"))))
|
||||
(if ?unexpected
|
||||
(each [_ exp (ipairs ?unexpected)]
|
||||
(is.nil (. seen exp) (.. exp " was suggested, but shouldn't be"))))))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: view} (require :fennel))
|
||||
(local {: ROOT-URI
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: ROOT-URI
|
||||
: setup-server} (require :test.utils))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: view} (require :fennel))
|
||||
(local {: ROOT-URI
|
||||
|
||||
@ -2,24 +2,24 @@
|
||||
"This document does not include tests. Instead it includes macros that are used for tests."
|
||||
|
||||
(fn it [desc ...]
|
||||
"busted's `it` function"
|
||||
"lust's `it` function"
|
||||
(let [body [...]]
|
||||
(table.insert body `nil)
|
||||
`((. (require :busted) :it)
|
||||
`((. (require :test.lust) :it)
|
||||
,desc (fn [] ,desc ,(unpack body)))))
|
||||
|
||||
(fn describe [desc ...]
|
||||
"busted's `describe` function"
|
||||
"lust's `describe` function"
|
||||
(let [body [...]]
|
||||
(table.insert body `nil)
|
||||
`((. (require :busted) :describe)
|
||||
`((. (require :test.lust) :describe)
|
||||
,desc (fn [] ,desc ,(unpack body)))))
|
||||
|
||||
(fn before-each [...]
|
||||
"busted's `describe` function"
|
||||
"lust's `before_each` function"
|
||||
(let [body [...]]
|
||||
(table.insert body `nil)
|
||||
`((. (require :busted) :before_each)
|
||||
`((. (require :test.lust) :before_each)
|
||||
(fn [] ,(unpack body)))))
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
((require :busted.runner))
|
||||
|
||||
(require :test.completion-test)
|
||||
(require :test.diagnostic-test)
|
||||
(require :test.goto-definition-test)
|
||||
@ -8,3 +6,7 @@
|
||||
(require :test.misc-test)
|
||||
(require :test.string-processing-test)
|
||||
(require :test.settings-test)
|
||||
|
||||
(let [{: passes : errors} (require :test.lust)]
|
||||
(print (.. passes " passes. " errors " errors."))
|
||||
(os.exit errors))
|
||||
|
||||
10
test/is.fnl
Normal file
10
test/is.fnl
Normal file
@ -0,0 +1,10 @@
|
||||
;; this package is here to translate into lust's weird dsl
|
||||
(local {: view} (require :fennel))
|
||||
(local {: expect} (require :test.lust))
|
||||
;; lust uses weird terminology, but equal is by __eq, same is by recursively having the same contents
|
||||
(setmetatable {:equal #((. (expect $1) :to :be) $2)
|
||||
:same #((. (expect $1) :to :equal) $2)
|
||||
:nil #((. (expect $1) :to_not :exist))
|
||||
:not {:nil #((. (expect $1) :to :exist))}
|
||||
:truthy #((. (expect $1) :to :be :truthy))}
|
||||
{:__call #((. (expect $2) :to :be :truthy))})
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local stringio (require :test.pl.stringio))
|
||||
(local json-rpc (require :fennel-ls.json-rpc))
|
||||
|
||||
242
test/lust.lua
Normal file
242
test/lust.lua
Normal file
@ -0,0 +1,242 @@
|
||||
-- lust v0.1.0 - Lua test framework
|
||||
-- https://github.com/bjornbytes/lust
|
||||
-- MIT LICENSE
|
||||
|
||||
local lust = {}
|
||||
lust.level = 0
|
||||
lust.passes = 0
|
||||
lust.errors = 0
|
||||
lust.befores = {}
|
||||
lust.afters = {}
|
||||
|
||||
local red = string.char(27) .. '[31m'
|
||||
local green = string.char(27) .. '[32m'
|
||||
local normal = string.char(27) .. '[0m'
|
||||
local function indent(level) return string.rep('\t', level or lust.level) end
|
||||
|
||||
local function has(t, x)
|
||||
for k, v in pairs(t) do
|
||||
if v == x then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function lust.nocolor()
|
||||
red, green, normal = '', '', ''
|
||||
return lust
|
||||
end
|
||||
|
||||
function lust.describe(name, fn)
|
||||
print(indent() .. name)
|
||||
lust.level = lust.level + 1
|
||||
fn()
|
||||
lust.befores[lust.level] = {}
|
||||
lust.afters[lust.level] = {}
|
||||
lust.level = lust.level - 1
|
||||
end
|
||||
|
||||
function lust.it(name, fn)
|
||||
for level = 1, lust.level do
|
||||
if lust.befores[level] then
|
||||
for i = 1, #lust.befores[level] do
|
||||
lust.befores[level][i](name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local success, err = xpcall(fn, require('fennel').traceback)
|
||||
if success then lust.passes = lust.passes + 1
|
||||
else lust.errors = lust.errors + 1 end
|
||||
local color = success and green or red
|
||||
local label = success and 'PASS' or 'FAIL'
|
||||
print(indent() .. color .. label .. normal .. ' ' .. name)
|
||||
if err then
|
||||
print(indent(lust.level + 1) .. red .. tostring(err) .. normal)
|
||||
end
|
||||
|
||||
for level = 1, lust.level do
|
||||
if lust.afters[level] then
|
||||
for i = 1, #lust.afters[level] do
|
||||
lust.afters[level][i](name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if has(arg, "--quit-at-first-test") then os.exit(1) end
|
||||
end
|
||||
|
||||
function lust.before(fn)
|
||||
lust.befores[lust.level] = lust.befores[lust.level] or {}
|
||||
table.insert(lust.befores[lust.level], fn)
|
||||
end
|
||||
|
||||
function lust.after(fn)
|
||||
lust.afters[lust.level] = lust.afters[lust.level] or {}
|
||||
table.insert(lust.afters[lust.level], fn)
|
||||
end
|
||||
|
||||
-- Assertions
|
||||
local function isa(v, x)
|
||||
if type(x) == 'string' then
|
||||
return type(v) == x,
|
||||
'expected ' .. tostring(v) .. ' to be a ' .. x,
|
||||
'expected ' .. tostring(v) .. ' to not be a ' .. x
|
||||
elseif type(x) == 'table' then
|
||||
if type(v) ~= 'table' then
|
||||
return false,
|
||||
'expected ' .. tostring(v) .. ' to be a ' .. tostring(x),
|
||||
'expected ' .. tostring(v) .. ' to not be a ' .. tostring(x)
|
||||
end
|
||||
|
||||
local seen = {}
|
||||
local meta = v
|
||||
while meta and not seen[meta] do
|
||||
if meta == x then return true end
|
||||
seen[meta] = true
|
||||
meta = getmetatable(meta) and getmetatable(meta).__index
|
||||
end
|
||||
|
||||
return false,
|
||||
'expected ' .. tostring(v) .. ' to be a ' .. tostring(x),
|
||||
'expected ' .. tostring(v) .. ' to not be a ' .. tostring(x)
|
||||
end
|
||||
|
||||
error('invalid type ' .. tostring(x))
|
||||
end
|
||||
|
||||
local function strict_eq(t1, t2)
|
||||
if type(t1) ~= type(t2) then return false end
|
||||
if type(t1) ~= 'table' then return t1 == t2 end
|
||||
for k, _ in pairs(t1) do
|
||||
if not strict_eq(t1[k], t2[k]) then return false end
|
||||
end
|
||||
for k, _ in pairs(t2) do
|
||||
if not strict_eq(t2[k], t1[k]) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local paths = {
|
||||
[''] = { 'to', 'to_not' },
|
||||
to = { 'have', 'equal', 'be', 'exist', 'fail', 'match' },
|
||||
to_not = { 'have', 'equal', 'be', 'exist', 'fail', 'match', chain = function(a) a.negate = not a.negate end },
|
||||
a = { test = isa },
|
||||
an = { test = isa },
|
||||
be = { 'a', 'an', 'truthy',
|
||||
test = function(v, x)
|
||||
return v == x,
|
||||
'expected ' .. tostring(v) .. ' and ' .. tostring(x) .. ' to be equal',
|
||||
'expected ' .. tostring(v) .. ' and ' .. tostring(x) .. ' to not be equal'
|
||||
end
|
||||
},
|
||||
exist = {
|
||||
test = function(v)
|
||||
return v ~= nil,
|
||||
'expected ' .. tostring(v) .. ' to exist',
|
||||
'expected ' .. tostring(v) .. ' to not exist'
|
||||
end
|
||||
},
|
||||
truthy = {
|
||||
test = function(v)
|
||||
return v,
|
||||
'expected ' .. tostring(v) .. ' to be truthy',
|
||||
'expected ' .. tostring(v) .. ' to not be truthy'
|
||||
end
|
||||
},
|
||||
equal = {
|
||||
test = function(v, x)
|
||||
return strict_eq(v, x),
|
||||
'expected ' .. tostring(v) .. ' and ' .. tostring(x) .. ' to be exactly equal',
|
||||
'expected ' .. tostring(v) .. ' and ' .. tostring(x) .. ' to not be exactly equal'
|
||||
end
|
||||
},
|
||||
have = {
|
||||
test = function(v, x)
|
||||
if type(v) ~= 'table' then
|
||||
error('expected ' .. tostring(v) .. ' to be a table')
|
||||
end
|
||||
|
||||
return has(v, x),
|
||||
'expected ' .. tostring(v) .. ' to contain ' .. tostring(x),
|
||||
'expected ' .. tostring(v) .. ' to not contain ' .. tostring(x)
|
||||
end
|
||||
},
|
||||
fail = {
|
||||
test = function(v)
|
||||
return not pcall(v),
|
||||
'expected ' .. tostring(v) .. ' to fail',
|
||||
'expected ' .. tostring(v) .. ' to not fail'
|
||||
end
|
||||
},
|
||||
match = {
|
||||
test = function(v, p)
|
||||
if type(v) ~= 'string' then v = tostring(v) end
|
||||
local result = string.find(v, p)
|
||||
return result ~= nil,
|
||||
'expected ' .. v .. ' to match pattern [[' .. p .. ']]',
|
||||
'expected ' .. v .. ' to not match pattern [[' .. p .. ']]'
|
||||
end
|
||||
},
|
||||
}
|
||||
|
||||
function lust.expect(v)
|
||||
local assertion = {}
|
||||
assertion.val = v
|
||||
assertion.action = ''
|
||||
assertion.negate = false
|
||||
|
||||
setmetatable(assertion, {
|
||||
__index = function(t, k)
|
||||
if has(paths[rawget(t, 'action')], k) then
|
||||
rawset(t, 'action', k)
|
||||
local chain = paths[rawget(t, 'action')].chain
|
||||
if chain then chain(t) end
|
||||
return t
|
||||
end
|
||||
return rawget(t, k)
|
||||
end,
|
||||
__call = function(t, ...)
|
||||
if paths[t.action].test then
|
||||
local res, err, nerr = paths[t.action].test(t.val, ...)
|
||||
if assertion.negate then
|
||||
res = not res
|
||||
err = nerr or err
|
||||
end
|
||||
if not res then
|
||||
error(err or 'unknown failure', 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
return assertion
|
||||
end
|
||||
|
||||
function lust.spy(target, name, run)
|
||||
local spy = {}
|
||||
local subject
|
||||
|
||||
local function capture(...)
|
||||
table.insert(spy, {...})
|
||||
return subject(...)
|
||||
end
|
||||
|
||||
if type(target) == 'table' then
|
||||
subject = target[name]
|
||||
target[name] = capture
|
||||
else
|
||||
run = name
|
||||
subject = target or function() end
|
||||
end
|
||||
|
||||
setmetatable(spy, {__call = function(_, ...) return capture(...) end})
|
||||
|
||||
if run then run() end
|
||||
|
||||
return spy
|
||||
end
|
||||
|
||||
lust.test = lust.it
|
||||
lust.paths = paths
|
||||
|
||||
return lust
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: view &as fennel} (require :fennel))
|
||||
(local {: setup-server
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local {: view} (require :fennel))
|
||||
(local {: ROOT-URI
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
(import-macros {: is-matching : describe : it} :test)
|
||||
(local is (require :luassert))
|
||||
(local is (require :test.is))
|
||||
|
||||
(local fennel (require :fennel))
|
||||
(local utils (require :fennel-ls.utils))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user