A CI Workflow for testing in roblox. It includes style checking, testing in Roblox and Lemur, and coverage reporting of Lemur tests.
-
-
Save LastTalon/0efa6c0a2e7d63d6a651e0f8e5d500a7 to your computer and use it in GitHub Desktop.
name: CI | |
on: | |
pull_request: | |
push: | |
branches: | |
- master | |
jobs: | |
format: | |
name: Formatting | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout Project | |
uses: actions/checkout@v2 | |
- name: Install Foreman | |
uses: Roblox/setup-foreman@v1 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Check Formatting | |
run: stylua --check . | |
lemur: | |
name: Lemur Testing | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout Project | |
uses: actions/checkout@v2 | |
with: | |
submodules: true | |
- name: Download Lemur | |
uses: actions/checkout@v2 | |
with: | |
repository: LPGhatguy/lemur | |
ref: "master" | |
path: lemur | |
submodules: true | |
- name: Install Lua | |
uses: leafo/gh-actions-lua@v8 | |
with: | |
luaVersion: "5.1" | |
- name: Install LuaRocks | |
uses: leafo/gh-actions-luarocks@v4 | |
- name: Install Lua Dependencies | |
run: | | |
luarocks install luacov | |
luarocks install luacov-reporter-lcov | |
luarocks install luafilesystem | |
luarocks install dkjson | |
luarocks install luasocket | |
luarocks install bit32 | |
- name: Run Tests | |
run: | | |
lua -lluacov tests/Lemur.server.lua | |
luacov -r lcov | |
- name: Report Coverage | |
uses: coverallsapp/github-action@v1.1.2 | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
path-to-lcov: luacov.report.out | |
roblox: | |
name: Roblox Testing | |
runs-on: windows-latest | |
steps: | |
- name: Checkout Project | |
uses: actions/checkout@v2 | |
with: | |
submodules: true | |
- name: Install Foreman | |
uses: Roblox/setup-foreman@v1 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Install Roblox | |
uses: osyrisrblx/roblox-win-installer-action@master | |
with: | |
cookie: ${{ secrets.ROBLOSECURITY || '_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_A293A7DBE35F8BCF906689DECD6726E783BBE6B331AB7313109C611DE40FB6EC2477F6403C1CCB5DBD1E07164546B8D7457EAC598E0DA5D4BEC983F0A951F326D7FD7DC12CF279CEA78FBD21FCBB9354EF573C03A9ECC6DE188F12B3CA3C07B5F043F8A0E470AA9C18BAF9C5B5300763AACD2A1965FA71704B22496F0ED798EE022813A9053940F1697A67A8814E7F46180985A5292AA87E44B3AAD205C8850B00511E9DC9A3359E240D3FDA0F72310C9474AFCB3E3CAA80E5FD7B44A7B3A13EF3D5825F2CF6C0051572E27D283BBB0CBA7B1E39C820B07EBE6E1297D54D6854A07BDFC9ABB7F0725BECA782A719447F246033846374EB701C925B35B4F696BB6568A2A5B58A1BBECB01028A17133908759C9A4FE5254F6A2782AF28CEB0C567E6E51AA29B0990914AB99068A3D942217A48DF2E' }} | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Build | |
run: rojo build -o build.rbxlx | |
- name: Run Tests | |
run: run-in-roblox --place build.rbxlx --script tests/Run.server.lua |
--- The Lemur test runner script. | |
-- This script can run with Lemur to perform automated tests. | |
-- | |
-- @script LemurTestRunner | |
-- @release 0.1.2, 2020-11-24 | |
-- @license MIT | |
-- Add init.lua to path allowing Lemur (and other dependencies to load) | |
package.path = package.path .. ";?/init.lua" | |
local Lemur = require("lemur") | |
local Habitat = Lemur.Habitat.new() | |
--- The source locations to load in lemur | |
local Source = { -- This can potentially be loaded from a project.json | |
{ "lib", "ReplicatedStorage.Monolith" }, | |
{ "tests", "ReplicatedStorage.Tests" }, | |
{ "modules/testez/src", "ReplicatedStorage.Tests.TestEZ" }, | |
} | |
--- Tokenizes a habitat path. | |
-- @param path the path to tokenize | |
-- @return a table of the tokens | |
local function tokenizePath(path) | |
local tokens = {} | |
for token in string.gmatch(path, "[^%.]+") do | |
table.insert(tokens, token) | |
end | |
return tokens | |
end | |
-- Build the project in Lemur | |
for _, pair in ipairs(Source) do | |
local source = Habitat:loadFromFs(pair[1]) | |
local tokens = tokenizePath(pair[2]) | |
local container = Habitat.game:GetService(tokens[1]) | |
local containerExists = false | |
-- Find the object we're placing this source in | |
if #tokens == 1 then | |
containerExists = true | |
else | |
for i = 2, #tokens - 1 do | |
container = container:FindFirstChild(tokens[i]) | |
end | |
local object = container:FindFirstChild(tokens[#tokens]) | |
if object then | |
container = object | |
containerExists = true | |
end | |
end | |
-- If the final container exists place everything inside. | |
if containerExists then | |
for _, object in ipairs(source:GetChildren()) do | |
object.Parent = container | |
end | |
source:Destroy() | |
else -- If it doesn't, replace it | |
source.Name = tokens[#tokens] | |
source.Parent = container | |
end | |
end | |
-- Load variables dependent on the build | |
local ReplicatedStorage = Habitat.game:GetService("ReplicatedStorage") | |
local Tests = Habitat:require(ReplicatedStorage:WaitForChild("Tests"):WaitForChild("Tests")) | |
local Roots = { ReplicatedStorage.Tests } | |
-- Run tests and set up exit status | |
local completed, result = Tests(Roots) | |
local status = 0 | |
-- Determine and report results | |
if completed then | |
if not result then | |
print("Tests have failed.") | |
status = 1 | |
end | |
else | |
print(result) | |
status = 2 | |
end | |
os.exit(status) |
MIT License
Copyright (c) 2021 Lucas Gangstad
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- The Roblox test runner script. | |
-- This script can run within Roblox to perform automated tests. | |
-- | |
-- @script TestRunner | |
-- @release 0.1.1, 2020-11-03 | |
-- @license MIT | |
local ReplicatedStorage = game:GetService("ReplicatedStorage") | |
local Tests = require(ReplicatedStorage:WaitForChild("Tests"):WaitForChild("Tests")) | |
--- The locations containing tests. | |
local Roots = { ReplicatedStorage.Tests } | |
local completed, result = Tests(Roots) | |
if completed then | |
if not result then | |
error("Tests have failed.", 0) | |
end | |
else | |
error(result, 0) | |
end |
--- Provides a function to run tests. | |
-- The generic testing function can be run in whatever testing environtment is | |
-- being used, providing a layer of abstraction between the test suite and the | |
-- environment. | |
-- | |
-- @module Tests | |
-- @release 0.1.1, 2020-11-03 | |
-- @license MIT | |
-- @see TestEZ | |
local ReplicatedStorage = game:GetService("ReplicatedStorage") | |
local TestEZ = require(ReplicatedStorage:WaitForChild("Tests"):WaitForChild("TestEZ")) | |
--- The testing function. | |
-- Accepts a list of roots, runs tests on them, then reports on test status. | |
-- | |
-- @param roots a table of roots to find tests | |
-- @return whether the tests completed | |
-- @return true if the tests were successful, false if the tests were | |
-- unsuccessful, an error message if the tests were not completed | |
local function Tests(roots) | |
print() | |
local completed, result = xpcall( | |
function() | |
local results = TestEZ.TestBootstrap:run(roots) | |
return results.failureCount == 0 | |
end, | |
debug.traceback | |
) | |
print() | |
return completed, result | |
end | |
return Tests |