Split test declarations and stubs out into their own files; improve encapsulation a bit

This commit is contained in:
Jason Perkins 2016-05-18 15:56:04 -04:00
parent e0e988eccb
commit b240131d09
6 changed files with 190 additions and 90 deletions

View File

@ -1,4 +1,6 @@
return {
"self-test.lua",
"test_declare.lua",
"test_hooks.lua",
"testfx.lua",
}

View File

@ -41,17 +41,28 @@
function m.executeSelfTest()
local focus = {}
if _OPTIONS["test"] then
focus = string.explode(_OPTIONS["test"] or "", ".", true)
m.loadTestsFromManifests()
local result, err = m.runTests(_OPTIONS["test-only"])
if err then
error(err, 0)
end
printf("%d tests passed, %d failed in %0.02f seconds",
result.passed, result.failed, result.elapsed)
if result.failed > 0 then
os.exit(5)
end
end
function m.loadTestsFromManifests()
local mask = path.join(_MAIN_SCRIPT_DIR, "**/tests/_tests.lua")
--
local manifests = os.matchfiles(mask)
-- TODO: "**" should also match "." but doesn't currently
local top = path.join(_MAIN_SCRIPT_DIR, "tests/_tests.lua")
if os.isfile(top) then
table.insert(manifests, 1, top)
@ -59,29 +70,22 @@
for i = 1, #manifests do
local manifest = manifests[i]
_TESTS_DIR = path.getdirectory(manifest)
local files = dofile(manifest)
for f = 1, #files do
dofile(path.join(_TESTS_DIR, files[f]))
for i = 1, #files do
local filename = path.join(_TESTS_DIR, files[i])
dofile(filename)
end
end
--
local startTime = os.clock()
passed, failed = test.runall(focus[1], focus[2])
io.write('running time : ', os.clock() - startTime,'\n')
msg = string.format("%d tests passed, %d failed", passed, failed)
if (failed > 0) then
print(msg)
os.exit(5)
else
print(msg)
end
end
dofile("test_declare.lua")
dofile("test_hooks.lua")
return m

View File

@ -0,0 +1,70 @@
---
-- test_declare.lua
--
-- Declare unit test suites, and fetch tests from them.
--
-- Author Jason Perkins
-- Copyright (c) 2008-2016 Jason Perkins and the Premake project.
---
local p = premake
local m = p.modules.self_test
local _ = {}
_.suites = {}
T = _.suites
---
-- Declare a new test suite.
--
-- @param suiteName
-- A unique name for the suite. This name will be displayed as part of
-- test failure messages, and also to select the suite when using the
-- `--test-only` command line parameter. Best to avoid spaces and special
-- characters which might not be command line friendly. An error will be
-- raised if the name is not unique.
-- @return
-- The new test suite object.
---
function m.declare(suiteName)
if _.suites[suiteName] then
error('Duplicate test suite "'.. suiteName .. '"', 2)
end
local suite = {}
suite._SCRIPT_DIR = _SCRIPT_DIR
suite._TESTS_DIR = _TESTS_DIR
_.suites[suiteName] = suite
return suite
end
---
-- Parse a test identifier and split it into separate suite and test names.
--
-- @param identifier
-- A test identifier, which may be nil or an empty string, a test suite
-- name, or a suite and test with the format "suiteName.testName".
-- @return
-- Two values: the suite name and the test name, or nil if not included
-- in the identifier.
---
function m.parseTestIdentifier(identifier)
local suiteName, testName
if identifier then
local parts = string.explode(identifier, ".", true)
suiteName = iif(parts[1] ~= "", parts[1], nil)
testName = iif(parts[2] ~= "", parts[2], nil)
end
return suiteName, testName
end

View File

@ -0,0 +1,77 @@
---
-- test_hooks.lua
--
-- Wire into the Lua runtime environment to support testing.
--
-- Author Jason Perkins
-- Copyright (c) 2008-2016 Jason Perkins and the Premake project.
---
local p = premake
local m = p.modules.self_test
local _ = {}
function m.installTestingHooks()
local hooks = {}
hooks.io_open = io.open
hooks.io_output = io.output
hooks.os_writefile_ifnotequal = os.writefile_ifnotequal
hooks.p_utf8 = p.utf8
hooks.print = print
io.open = _.stub_io_open
io.output = _.stub_io_output
os.writefile_ifnotequal = _.stub_os_writefile_ifnotequal
print = _.stub_print
p.utf8 = _.stub_utf8
return hooks
end
function m.removeTestingHooks(hooks)
io.open = hooks.io_open
io.output = hooks.io_output
os.writefile_ifnotequal = hooks.os_writefile_ifnotequal
p.utf8 = hooks.p_utf8
print = hooks.print
end
function _.stub_io_open(fname, mode)
test.value_openedfilename = fname
test.value_openedfilemode = mode
return {
close = function()
test.value_closedfile = true
end
}
end
function _.stub_io_output(f)
end
function _.stub_os_writefile_ifnotequal(content, fname)
m.value_openedfilename = fname
m.value_closedfile = true
return 0
end
function _.stub_print(s)
end
function _.stub_utf8()
end

View File

@ -296,43 +296,6 @@
end
--
-- Test stubs
--
local function stub_io_open(fname, mode)
test.value_openedfilename = fname
test.value_openedfilemode = mode
return {
close = function()
test.value_closedfile = true
end
}
end
local function stub_io_output(f)
end
local function stub_print(s)
end
local function stub_utf8()
end
local function stub_os_writefile_ifnotequal(content, fname)
test.value_openedfilename = fname;
test.value_closedfile = true
return 0;
end
--
-- Define a collection for the test suites
--
T = {}
--
-- Test execution function
@ -411,19 +374,6 @@
function test.declare(id)
if T[id] then
error("Duplicate test suite " .. id)
end
T[id] = {
_TESTS_DIR = _TESTS_DIR,
_SCRIPT_DIR = _SCRIPT_DIR,
}
return T[id]
end
function test.suppress(id)
if type(id) == "table" then
for i = 1, #id do
@ -436,23 +386,16 @@
function test.runall(suitename, testname)
function test.runTests(suitename, testname)
test.print = print
local real_print = print
local real_open = io.open
local real_output = io.output
local hooks = test.installTestingHooks()
print = stub_print
io.open = stub_io_open
io.output = stub_io_output
os.writefile_ifnotequal = stub_os_writefile_ifnotequal
premake.utf8 = stub_utf8
local startTime = os.clock()
local numpassed = 0
local numfailed = 0
function runtest(suitename, suitetests, testname, testfunc)
if suitetests.setup ~= testfunc and
suitetests.teardown ~= testfunc and
@ -495,7 +438,6 @@
end
end
if suitename then
runsuite(suitename, T[suitename], testname)
else
@ -504,10 +446,15 @@
end
end
print = real_print
io.open = real_open
io.output = real_output
local result = {
passed = numpassed,
failed = numfailed,
start = startTime,
elapsed = os.clock() - startTime
}
return numpassed, numfailed
test.removeTestingHooks(hooks)
return result
end

View File

@ -51,7 +51,7 @@
newoption {
trigger = "test",
trigger = "test-only",
description = "When testing, run only the specified suite or test"
}