I have some questions regarding best practices or at least "acceptable" practices for writing unit tests for LUA code written specifically for love. I'll preface this by saying I'm totally a goal-oriented person, so my primary interests are in producing code that does what I intend it to do. I'm generally not interested in writing elegant or clever code, merely functional. Nevertheless, good testing coverage is very useful to me as it helps me prove my code is, indeed, functional. OK. That said.
The question. Is the method of mock/testing below suitable for love, and if not, any suggestions?
My method.
1) All functions I write will return some return value, even if I don't actually need it in the game
2) As I am not responsible for love.* functions, I do not test them or attempt to test them
3) All functions I write are written in such a fashion to test their individual components
How I do it:
I have a "tests.lua" module which includes all modules for my game, as well as LuaUnit. tests.lua is only used through lua, the love engine has no knowledge of it. It resembles this:
Code: Select all
-- tests.lua
love = {}
require('main') -- main
require('logging') -- our own logging
require('persistence') -- module to serialize data structures and write them to disk
require('modules/luaunit/luaunit') -- testing module
Now, many of my modules will access global variables. I know this isn't super ideal. But, for even those that don't, some still will try to use functions provided by love. Since these functions aren't part of my scope, and likely won't even function, I mock any love functions while testing. i.e.:
Code: Select all
-- tests.lua
-- Mocked love functions - is there a better way to do this?
love = {
graphics = {
newImage = function() return end,
newFont = function() return end,
},
mouse = {
setVisible = function() return end,
}
}
Code: Select all
-- tests.lua
load_mock_data()
-- Test Logging module
Test_f_colony_logging_tests = {}
function Test_f_colony_logging_tests:testGoodData()
test_message = 'test message'
test_level = 'warn'
rv, err = f_colony_log(test_message, test_level)
assertEquals ( type(rv), 'number')
assertEquals ( rv, 0 )
assertEquals ( type(err), 'nil')
end
LuaUnit:run()
It does mean there are some cases I can't test - like if I tell love to load a font file, and the font file doesn't exist, I'm not able to test that. That's not ideal, and I haven't thought of a good way around it yet, but I'm open to suggestions. One way I am considering is a set of functional tests I can trigger in-game, so I have full access to the love suite. It also means I'd have to execute both unit tests then run functional tests in-game(I can certainly automate that, of course). I suppose if love can take command-line arguments and my game can access them, I could even execute the tests with the game running - but then that means no headless testing.