Skip to content
Jusonex edited this page Mar 12, 2017 · 8 revisions

MTA:SA Unit Testing Framework

Requirements

  • VSCode integration (list of succeeded/failed tests)
  • Unit test library (assert functions, test case classes etc.)
  • Easy to load (e.g. by adding a single Lua file to the resource)
  • Doesn't require clients on the server
  • (clever cleanup to avoid restarting the whole resource every single time (which could take ages for larger gamemodes))
  • Windows (writing tests) and Linux (executing tests in CI env) support

Implementation Ideas

Implementing the requirements

VSCode integration

It is not yet possible to add new icons to the sidebar. However, we could open the the results in a temporary document.

Hopefully, we can get something like this in the end:

Unit test library

Implementing it should go pretty straight forward. It should not rely on external dependencies e.g. the classlib, but should ship it's own class library if required (without bloating the global namespace!).

API Example
GangTest = MTAUnit.Test()

function GangTest:setup()
    -- called on instantiation to initialise stuff
    self.gang = Gang:new()
end

function GangTest:testAddPlayer()
    local player = MTAUnit.makePlayer("Günther")
    self.gang:addPlayer(player)

    self:assertContains(self.gang:getPlayers(), player)
end

Easy to load

Something like minifying/bundling I guess so we end up with a single script file that contains everything.

<meta>
    <!-- Include gamemode script files as usual -->
    <script src="SomeNormalScriptFile" type="server"/>

    <!-- Option 1: Introduce new meta tag for dev deps (similar to node.js' 'devDependencies' section) -->
    <!-- This script is only loaded in development mode which can be enabled via a command -->
    <devscript src="MTAUnit.lua" type="shared"/>
    <!-- or -->
    <script src="MTAUnit.lua" type="dev-shared"/>

    <!-- Option 2: Include it as normal script and leave it to the player -->
    <!-- to take care it isn't included in the production build. Requires more advanced -->
    <!-- release pipelines though (which people who use this library might have anyway though) -->
    <script src="MTAUnit.lua" type="shared"/>
</meta>

The advantage of the extra option above is that we can use the same technique to load the test cases appropriately (i.e. do not load them in the production build). The downside is: It requires changes to the MTA server (which are probably not necessary...).

No Clients on the server

Requires a change in the MTA server code. Might be the most difficult part of the project if the sync logic is widely spread in the code. A bad alternative is to mock all functions that expect a player.

Architecture

We need something to control the server (e.g. execute commands) and communicate with the editor plugin to start executing the tests + get the results. Ideally, this is done by a small app that pipes stdin/stdout and provides a REST API (so MTA can use fetchRemote for communication).

TODO

  • Refactor MTA input logic