Rotest
An easy to use test framework for Roblox.
You can find it on GitHub
Features
- Write tests using ModuleScripts with no dependancies.
- One-file runner deployment.
- Readable and configurable output.
Installation
It’s just one file, so you can copy the contents of src/Rotest.lua into a ModuleScript in game.ReplicatedStorage.
Or, you can also install using the package under release/rotest.rbxmx:
- Inside Roblox Studio right-click on Workspace and click on Insert from file.
- Browse to release/rotest.rbxmx and Open.
- Then move Rotest/Rotest to game.ReplicatedStorage.
Running tests
- Start Server.
- Open Command Bar.
- Run the following command:
require(game.ReplicatedStorage.Rotest):run()
Tests can be run via the command-line using run-in-roblox.
Each test will be executed in parallel using coroutines.
Writing tests
-
Tests are just ModuleScripts named to end with
.test
. -
Any methods in the test will be ran in the suite. Prefix private methods with
_
to prevent running. -
If you use
camelCase
for the test names, they will be turned intocamel case
for readability in the output. -
If you have a constructor method called
new()
it will be ran before each test. -
If you have a teardown method called
teardown()
it will be ran after each test.
Example
Let’s say you have a ModuleScript
that exposes a single function to round a number:
ReplicatedStorage > MathUtil
local Math = {}
function Math.round(numberToRound)
return math.floor(numberToRound + 0.5)
end
return Math
We can create a test for it by creating another ModuleScript
called Math.test in a Test folder.
ReplicatedStorage > Tests > Math.test
local MathUtil = require(game.ReplicatedStorage:WaitForChild('MathUtil'))
local MathUtilTest = {}
function MathUtilTest:roundsNumbersUp()
local numberToRound = 1.5
local roundedNumber = MathUtil.round(numberToRound)
assert(roundedNumber == 2, "Number not rounded up")
end
-- Other tests here...
return MathUtilTest
We can then start a Server and call the test runner using the Command Bar:
require(game.ReplicatedStorage.Rotest):run()
It should output something that looks like this:
========== Rotest results =============
Collected 2 tests
Math test:
[x] rounds numbers up (0.00 second(s))
[x] rounds numbers down (0.00 second(s))
==== 2 passed, 0 failed in 0.01 seconds ====
Arguments
The run(basepath, config)
method takes 2 argument:
-
basepath
- is the base path that the test runner will use to search for tests. -
config
- a table can have the following keys:-
verbose
- a boolean that specifies whether the runner should include every test in the output. Defaults totrue
-
Run on server start
You can automatically run the tests when the server starts, by creating a ServerScript
like this:
Game > ServerScriptService > RunTests
if game:GetService("RunService"):IsStudio() then
game:WaitForChild('ReplicatedStorage')
game.ReplicatedStorage:WaitForChild('Rotest')
require(game.ReplicatedStorage.Rotest):run()
end
More Examples
- Utils - Example of testing some simple util functions with no side effects.
- Datastore - Example of a simple datastore wrapper that loads player data. Shows how to use setup and teardown.
- Event - Example of a simple event handler. Includes a fairly sophisticated mock.
Why another unit test framework?
- Unlike TestEz and TestSuite, tests are not written in BDD-style.
- Unlike Nexus-Unit-Testing, tests are designed to be written as Lua modules with no imports
Who’s using it?
We are using it while developing Splash Music.