TestSuite = { -- @method - TestSuite:new() -- @desc - creates a new TestSuite object that handles all the tests -- @return {table} - returns the new TestSuite object new = function(self) local test = { -- testsuite internals modules = {}, module = nil, test = nil, testcanvas = nil, current = 1, output = '', totals = {0, 0, 0}, time = 0, xml = '', html = '', mdrows = '', mdfailures = '', delayed = nil, fakequit = false, windowmode = true, current_os = love._os, lua_version = tonumber(_VERSION:match("%d%.%d")), has_lua_jit = type(jit) == 'table', -- love modules to test audio = {}, data = {}, event = {}, filesystem = {}, font = {}, graphics = {}, image = {}, joystick = {}, love = {}, keyboard = {}, math = {}, mouse = {}, physics = {}, sensor = {}, sound = {}, system = {}, thread = {}, timer = {}, touch = {}, video = {}, window = {} } setmetatable(test, self) self.__index = self return test end, -- @method - TestSuite:runSuite() -- @desc - called in love.update, runs through every method or every module -- @param {number} delta - delta from love.update to track time elapsed -- @return {nil} runSuite = function(self, delta) -- stagger between tests if self.module ~= nil then if self.module.start then -- work through each test method 1 by 1 if self.module.index <= #self.module.running then -- run method once if self.module.called[self.module.index] == nil then self.module.called[self.module.index] = true local method = self.module.running[self.module.index] self.test = TestMethod:new(method, self.module) TextRun = 'love.' .. self.module.module .. '.' .. method self.test.co = coroutine.create(function() local ok, chunk, err = pcall( love.test[love.test.module.module][method], love.test.test ) if ok == false then love.test.test['passed'] = false love.test.test['fatal'] = tostring(chunk) .. tostring(err) end end) -- once called we have a corouting, so just call resume every frame -- until we have finished else -- move onto next yield if any -- pauses can be set with TestMethod:waitFrames(frames) coroutine.resume(self.test.co) -- when wait finished (or no yields) if coroutine.status(self.test.co) == 'dead' then -- now we're all done evaluate the test local ok, chunk, err = pcall(self.test.evaluateTest, self.test) if ok == false then self.test.passed = false self.test.fatal = tostring(chunk) .. tostring(err) end -- save having to :release() anything we made in the last test collectgarbage("collect") -- move onto the next test self.module.index = self.module.index + 1 end end -- once all tests have run else -- print module results and add to output self.module:printResult() -- if we have more modules to go run the next one self.current = self.current + 1 if #self.modules >= self.current then self.module = self.modules[self.current] self.module:runTests() -- otherwise print the final results and export output else self:printResult() love.event.quit(0) end end end end end, -- @method - TestSuite:printResult() -- @desc - prints the result of the whole test suite as well as writes -- the MD, XML + HTML of the testsuite output -- @return {nil} printResult = function(self) local finaltime = UtilTimeFormat(self.time) -- in case we dont have love.graphics loaded, for future module specific disabling local name = 'NONE' local version = 'NONE' local vendor = 'NONE' local device = 'NONE' if love.graphics then name, version, vendor, device = love.graphics.getRendererInfo() end local md = '\n\n### Info\n' .. '**' .. tostring(self.totals[1] + self.totals[2] + self.totals[3]) .. '** tests were completed in **' .. finaltime .. 's** with **' .. tostring(self.totals[1]) .. '** passed, **' .. tostring(self.totals[2]) .. '** failed, and **' .. tostring(self.totals[3]) .. '** skipped\n\n' .. 'Renderer: ' .. name .. ' | ' .. version .. ' | ' .. vendor .. ' | ' .. device .. '\n\n' .. '### Report\n' .. '| Module | Pass | Fail | Skip | Time |\n' .. '| --------------------- | ------ | ------ | ------- | ------ |\n' .. self.mdrows .. '\n### Failures\n' .. self.mdfailures local xml = '\n' local status = '
' if self.totals[2] == 0 then status = '
' end local html = [[ ]] local wrap_cls = '' if self.totals[2] > 0 then wrap_cls = 'fail' end html = html .. '

' .. status .. ' love.test report

' .. '

Renderer: ' .. name .. ' | ' .. version .. ' | ' .. vendor .. ' | ' .. device .. '

' .. '

' love.filesystem.write('tempoutput/' .. self.output .. '.xml', xml .. self.xml .. '') love.filesystem.write('tempoutput/' .. self.output .. '.html', html .. self.html .. '
') love.filesystem.write('tempoutput/' .. self.output .. '.md', md) self.module:log('grey', '\nFINISHED - ' .. finaltime .. 's\n') local failedcol = '\27[31m' if self.totals[2] == 0 then failedcol = '\27[37m' end self.module:log('green', tostring(self.totals[1]) .. ' PASSED' .. ' || ' .. failedcol .. tostring(self.totals[2]) .. ' FAILED || \27[37m' .. tostring(self.totals[3]) .. ' SKIPPED') end }