An easy to use test framework for Roblox.
- Write tests using ModuleScripts with no dependancies.
- One-file runner deployment.
- Readable and configurable output.
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.
- 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.
-
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
camelCasefor the test names, they will be turned intocamel casefor 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.
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 ====
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
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
- 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.
The main advantage to Rotest over other frameworks is that tests are written simply as Lua modules with no dependancies (injected or otherwise), which means there’s nothing new to learn to start writing tests.
Rotest is similar in spirit to libraries like PyTest and xUnit which utilise more language features rather than framework to write tests.
- 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
We are using it while developing Splash Music.