Testing
shiva-test is a lightweight test runner for Shiva modules. Tests run with stock lua5.4 — no live FiveM server required.
Install
bash
npm install -g @shiva-fw/cli
shiva make:test my-moduleOr manually:
bash
luarocks install shiva-testSetup
Each test file calls Test.setup() before writing any tests.
lua
-- spec/FishingService_spec.lua
Test.setup({
mode = 'server', -- 'server' | 'client'
framework = 'shiva', -- 'shiva' | 'qbcore' | 'esx' | 'ox' | 'none'
})Writing Tests
lua
Test.describe('FishingService', function()
Test.beforeEach(function()
Test.db.reset()
end)
Test.it('awards fish on successful catch', function()
Test.db.execute([[
INSERT INTO players (id, name) VALUES (1, 'TestPlayer')
]])
local service = FishingService.new()
service:catch(1, 'tuna')
local row = Test.db.single('SELECT * FROM fishing_log WHERE player_id = 1')
Test.expect(row).not_:toBeNil()
Test.expect(row.fish_type):toBe('tuna')
end)
Test.it('fires the fishing:caught event', function()
local service = FishingService.new()
service:catch(1, 'salmon')
Test.assertEventFired('fishing:caught', function(payload)
return payload.playerId == 1 and payload.fish == 'salmon'
end)
end)
end)Test.expect Assertions
lua
Test.expect(value):toBe(expected) -- strict equality (==)
Test.expect(value):toEqual(expected) -- deep equality
Test.expect(value):toBeNil()
Test.expect(value):not_:toBeNil()
Test.expect(value):toBeTrue()
Test.expect(value):toBeFalse()
Test.expect(value):toContain(item) -- table contains item
Test.expect(value):toMatch(pattern) -- string matches Lua pattern
Test.expect(fn):toThrow(msg?) -- function throws an errorDatabase Helpers
Test.db wraps a local SQLite database that resets between tests.
lua
Test.db.execute(sql, params?) -- run a statement
Test.db.query(sql, params?) -- return multiple rows
Test.db.single(sql, params?) -- return one row or nil
Test.db.reset() -- clear all tablesEvent Assertions
lua
-- Assert an event was fired (optionally matching a payload predicate)
Test.assertEventFired('fishing:caught')
Test.assertEventFired('fishing:caught', function(payload)
return payload.playerId == 42
end)
-- Assert an event was NOT fired
Test.assertEventNotFired('fishing:caught')Mocking Exports
lua
Test.mockExport('shiva-inventory', 'addItem', function(playerId, item, amount)
return true
end)Running Tests
bash
shiva test # all modules
shiva test my-module # single module
lua5.4 spec/FishingService_spec.lua # direct run
shiva test --watch # re-run on file change
shiva test --coverage # generate coverage reportCI Integration
Tests run automatically in CI via the shiva test command. See .github/workflows/ for the workflow configuration.