Skip to content

Instantly share code, notes, and snippets.

@LastTalon
Last active December 5, 2023 18:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LastTalon/0efa6c0a2e7d63d6a651e0f8e5d500a7 to your computer and use it in GitHub Desktop.
Save LastTalon/0efa6c0a2e7d63d6a651e0f8e5d500a7 to your computer and use it in GitHub Desktop.

A CI Workflow for testing in roblox. It includes style checking, testing in Roblox and Lemur, and coverage reporting of Lemur tests.

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment