Page 1 of 1

Writing unit tests within love code

Posted: Sun Aug 18, 2013 9:50 am
by soulmata
Hello,

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
... et cetera.
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,
  }
}
Then I just write tests as normal, like:

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()
So far, I've found I can write unit tests for virtually any function write, and nearly every component of it. I'm careful to make sure to validate my inputs, die on data I can't handle, et cetera. The only "messy" part about it, I think, is that I have to mock the love functions to mocked responses. I see that as OK because I don't maintain / don't care about testing the love functions, I only care about how my own code interacts with them - so if a love function should return an image, I mock it in my test suite to return test image data.

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.

Re: Writing unit tests within love code

Posted: Sun Aug 18, 2013 10:23 pm
by markgo
You may be interested in this how this man does it: https://bitbucket.org/blprice61/dark-st ... ve-ike/src

Hope it gives you some ideas. Good luck.

Re: Writing unit tests within love code

Posted: Tue Aug 20, 2013 5:59 pm
by soulmata
It looks like he took the same approach I did, and mocks all of the needed love functions. At least I know I'm on the right track.

Does anyone else here have experiencing writing unit tests for their love code?

Re: Writing unit tests within love code

Posted: Tue Aug 20, 2013 7:26 pm
by ejmr
Recently I have been using Busted for unit testing. Here is project where I use it, a component that is part of the game I am working on. So far I’ve been happy with the combination of Busted and LÖVE. It provides ways to create stubs for LÖVE functions but I have not thoroughly explored how well that works in practice, and I suspect that may be the make-or-break aspect of using Busted together with LÖVE. I have heard good things about Telescope but personally I’ve not used it for anything LÖVE-related.

Re: Writing unit tests within love code

Posted: Thu Aug 22, 2013 2:13 pm
by kikito
Similar approach from me on the anim8 tests: love mocks and example of use.

I think that tests are great for libraries. Writing tests for a whole game will be very challenging, unless you manage to split your code very carefully, so that in fact your game becomes a "bunch of libraries acting together". Good luck!

Re: Writing unit tests within love code

Posted: Sat Sep 14, 2019 4:50 pm
by mccarthy
Highjacking this thread as it seems most relevant to my question.

I'm currently attempting to write some tests for some procedurally generated terrain in a game I'm working on. I make use of the love.math.noise(x, y) function in the terrain generation. Naturally, when I create a new terrain object in the setup for my tests, busted has no idea about the love.math table.

Is there a way to expose the various love functions? I know in this specific instance I could get around it by writing my own simplex noise lib and using that, but I figured this must be a problem people have come across before and hopefully there is a solution already out there.

Thanks in advance for any help and advice!

Re: Writing unit tests within love code

Posted: Sat Sep 14, 2019 6:04 pm
by pgimeno
mccarthy wrote: Sat Sep 14, 2019 4:50 pm Is there a way to expose the various love functions? I know in this specific instance I could get around it by writing my own simplex noise lib and using that, but I figured this must be a problem people have come across before and hopefully there is a solution already out there.
You can require love:

Code: Select all

package.preload.love = package.loadlib('/path/to/liblove-11.2.so', 'luaopen_love')
require 'love'
require 'love.math'
Or you can ditch busted and roll your own unit testing.

Re: Writing unit tests within love code

Posted: Sat Sep 14, 2019 7:30 pm
by mccarthy
Thanks for the response!

I spotted your reply here after posting, but still having some issues. I've renamed liblove.so to love.so, and put it in the root directory of my LÖVE project (just for convenience at this point), but still seeing the following error:

Code: Select all

spec/map/terrain_spec.lua:2: error loading module 'love' from file './love.so':
dlopen(./love.so, 6): no suitable image found.  Did find:
./love.so: unknown file type, first eight bytes: 0x7F 0x45 0x4C 0x46 0x01 0x01 0x01 0x00
I should mention I'm using OSX and not a Linux distro, which may be an issue here. At this point I may well just roll my own unit testing framework, though Busted looks pretty useful so it'd be nice to get that up and running.

Again, your help is very much appreciated!

Re: Writing unit tests within love code

Posted: Sat Sep 14, 2019 8:23 pm
by pgimeno
I wonder if you're using the right file and the right architecture. Wasn't it .dylib for Mac? Not sure about that, I may be outdated. 0x7F 0x45 0x4C 0x46 0x01 0x01 0x01 0x00 means ELF 32-bit little-endian; there doesn't seem to be anything wrong there if Mac can load 32-bit ELF shared libraries.

EDIT: After unzipping the MacOS distribution, it appears to me that the file you want is love.app/Contents/Frameworks/love.framework/Versions/A/love - I'm not sure, but the 'file' Linux utility identifies it as: "Mach-O 64-bit x86_64 dynamically linked shared library, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|WEAK_DEFINES|BINDS_TO_WEAK|NO_REEXPORTED_DYLIBS>"

Re: Writing unit tests within love code

Posted: Mon Sep 16, 2019 6:52 am
by TheHUG
for tests where I need access to love functions I use: https://love2d.org/forums/viewtopic.php?t=75192

Another option would be to mock the functions you need