roblox-testing
Skill25 starsChanged 56 days agoMITView on GitHub
Test, debug, or profile Roblox experiences. Use for Studio debugging, TestEZ, logging, connection cleanup, memory or network diagnostics, MicroProfiler, Scene Analysis, and Script Profiler.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- EL4CTEO/roblox-skillstheir own version, first seen Sep 28, 2026
- zukoma42-dev/claude-skillstheir own version, first seen Mar 25, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- EL4CTEO/roblox-skills★ 92same name
- zukoma42-dev/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository16 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- roblox-animationSkill
- roblox-audioSkill
- roblox-coreSkill
- roblox-datastoresSkill
- roblox-gamepassesSkill
- roblox-mcpSkill
- roblox-networkingSkill
- roblox-npcsSkill
- roblox-open-cloudSkill
- roblox-physicsSkill
- roblox-rojoSkill
- robloxSkill
- roblox-teleportSkill
- roblox-user-interfacesSkill
- roblox-vfxSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
31 rules. About 0 are common, 20 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈20
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 17
Start with a reproducible failure and identify whether it occurs on the client, server, or both.
- Distinctive: line 21
Reproduce it: If you can't reproduce it, you can't fix it.
- Distinctive: line 22
Isolate it: Remove systems until the bug disappears.
- Distinctive: line 23
Measure it: Use tools instead of guessing.
- Distinctive: line 24
Fix one thing at a time: Verify the fix and add a regression test if possible.
- Very specific: line 29
Use print, warn, and error deliberately:
- Distinctive: line 40
Avoid logging secrets, player data, or PII.
- Very specific: line 55
Use assert for internal invariants that should never fail:
- Very specific: line 102
Use the Luau language server (luau-lsp) or the Luau type checker in Studio to catch errors before runtime.
- Distinctive: line 105
Add type annotations to module exports and pure functions.
- Very specific: line 106
Run luau-lsp analyze in CI or before committing.
- Distinctive: line 108
Do not over-type untyped engine APIs.
- Distinctive: line 112
Use Studio's built-in debugger for step-through debugging:
- Distinctive: line 114
Run in Play mode and use the debugger controls to step over, into, or out.
- Very specific: line 120
Use xpcall with debug.traceback to capture full stack traces from failures:
- Distinctive: line 137
Use a Maid/Janitor-style collector:
- Very specific: line 149
Use :Once() for one-shot event handlers.
- Very specific: line 150
Use Instance.Destroying to trigger cleanup when an instance is removed:
- Very specific: line 158
Always pair :Connect() with a matching :Disconnect() or destruction.
- Distinctive: line 180
Never log secrets, keys, user identifiers, or personal information.
- Very specific: line 217
Use BasePart:GetNetworkOwner() to inspect ownership.
- Distinctive: line 240
Always call DataStores from the server and validate serialization before saving.
- Distinctive: line 244
Use the Developer Console Memory tab or Scene Analysis to compare snapshots:
- Very specific: line 260
Add custom labels with debug.profilebegin/debug.profileend.
- Distinctive: line 299
Check Network tab in Developer Console for HTTP/DataStore failures.
- Very specific: line 300
Use Shift+F3 in-game for network debug stats.
- Distinctive: line 326
Check logs and errors in the Developer Console.
- Distinctive: line 328
Use MicroProfiler/Script Profiler for performance issues.
- Distinctive: line 329
Use Scene Analysis for memory leaks and scene composition.
- Distinctive: line 330
Add targeted logging or tests to confirm the fix.
- Distinctive: line 331
Verify on low-end devices and with network simulation when relevant.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
roblox-testing
Official sources:
- https://create.roblox.com/docs/en-us/studio/developer-console
- https://create.roblox.com/docs/en-us/performance-optimization/identify
- https://create.roblox.com/docs/en-us/performance-optimization/microprofiler
- https://create.roblox.com/docs/en-us/performance-optimization/scene-analysis
- https://create.roblox.com/docs/en-us/studio/optimization/memory-usage
- https://create.roblox.com/docs/en-us/studio/optimization/scriptprofiler
Start with a reproducible failure and identify whether it occurs on the client, server, or both. Choose a debugging or profiling tool based on that evidence.
The debugging mindset
- Reproduce it. If you can't reproduce it, you can't fix it.
- Isolate it. Remove systems until the bug disappears; the last thing removed is the cause.
- Measure it. Use tools instead of guessing.
- Fix one thing at a time. Verify the fix and add a regression test if possible.
- Log defensively. Good logs make future debugging faster.
Logging discipline
Use print, warn, and error deliberately:
printfor normal diagnostics.warnfor recoverable problems you should notice.errorfor programming errors that should stop execution.
Include context in log messages:
warn(string.format("[DataStore] Save failed for %d: %s", userId, tostring(err)))Avoid logging secrets, player data, or PII.
pcall and assertions
Wrap fallible calls, especially cloud services, HTTP, DataStores, Marketplace:
local ok, result = pcall(function()
return someService:DoSomething()
end)
if not ok then
warn("DoSomething failed:", result)
endUse assert for internal invariants that should never fail:
assert(config.MaxSpeed > 0, "MaxSpeed must be positive")Developer Console
Open with F9 in-game or in Studio play mode.
Tabs:
- Log: client/server output, errors, warnings.
- Memory: categorized memory usage.
- Network: HTTP and service requests.
- Server Stats: heartbeat, ping, data ping.
- Script Profiler: record script CPU usage.
- MicroProfiler: capture server dumps.
Toggle Client/Server views to see which side emitted output.
Unit testing with TestEZ
The standard Roblox testing framework is TestEZ. It supports nested describe/it blocks, lifecycle hooks, async tests, and a rich matcher API.
TestEZ example:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TestEZ = require(ReplicatedStorage.DevPackages.TestEZ)
local MathUtils = require(ReplicatedStorage.MathUtils)
describe("MathUtils", function()
it("clamps values", function()
expect(MathUtils.clamp(5, 0, 10)).to.equal(5)
expect(MathUtils.clamp(-1, 0, 10)).to.equal(0)
expect(MathUtils.clamp(11, 0, 10)).to.equal(10)
end)
end)
TestEZ.TestBootstrap:run({ game.ReplicatedStorage.Tests })For legacy in-Studio tests, TestService:Error(msg) can mark failures visibly in Studio output, but most projects should prefer TestEZ. The scripts folder contains a minimal TestRunner.lua shim only for environments where TestEZ is unavailable.
Luau type checking
Use the Luau language server (luau-lsp) or the Luau type checker in Studio to catch errors before runtime.
Best practices:
- Add type annotations to module exports and pure functions.
- Run
luau-lsp analyzein CI or before committing. - Enable
--!strictfor new modules. - Do not over-type untyped engine APIs; prefer casts at boundaries.
Studio Debugger
Use Studio's built-in debugger for step-through debugging:
- Set breakpoints by clicking the gutter next to a line number.
- Run in Play mode and use the debugger controls to step over, into, or out.
- Inspect the call stack, local variables, and upvalues in the debugger panel.
- The debugger works in both client and server contexts when Studio runs both.
xpcall and debug.traceback
Use xpcall with debug.traceback to capture full stack traces from failures:
local ok, err = xpcall(function()
riskyOperation()
end, debug.traceback)
if not ok then
warn(err)
endThis is especially useful at top-level entry points, scheduled callbacks, and connection handlers where pcall alone discards the stack.
Connection cleanup
Leaked RBXScriptConnection objects are a common source of memory leaks and stale state. Prefer explicit cleanup patterns:
- Use a Maid/Janitor-style collector:
local Maid = require(path.to.Maid)
local maid = Maid.new()
maid:GiveTask(workspace.ChildAdded:Connect(onChild))
maid:GiveTask(RunService.Heartbeat:Connect(onStep))
maid:Destroy() -- disconnects everything- Use
:Once()for one-shot event handlers. - Use
Instance.Destroyingto trigger cleanup when an instance is removed:
obj.Destroying:Connect(function()
cleanup()
end)- Always pair
:Connect()with a matching:Disconnect()or destruction.
Prefer task over spawn/delay
The task library is more predictable than legacy spawn, delay, and wait:
-- good
task.wait(1)
task.delay(1, callback)
task.spawn(coroutineOrFn)
-- avoid
spawn(callback)
delay(1, callback)
wait(1)task.defer is useful for yielding to the next resumption cycle without opening a new thread.
Log rate limiting and secrets hygiene
- Never log secrets, keys, user identifiers, or personal information.
- Sanitize values before logging:
local function sanitize(value)
if typeof(value) == "Instance" and value:IsA("Player") then
return "Player(" .. tostring(value.UserId) .. ")"
end
return value
end- Rate-limit noisy logs to avoid flooding the console and network:
local lastLog = 0
local function throttledLog(message)
local now = os.clock()
if now - lastLog > 5 then
lastLog = now
warn(message)
end
endNetwork ownership
Incorrect network ownership causes jittery physics and replication lag. Visualize ownership and assign it explicitly:
-- Server
part:SetNetworkOwner(player)
-- Client-side visualization (debug only)
local ownershipLabel -- create BillboardGui or use DebugDrawUse BasePart:GetNetworkOwner() to inspect ownership. Vehicles and held items should usually be owned by the controlling player.
DataStore retry pattern
For retry-safe reads, use bounded retries with exponential backoff and jitter. Do not use this generic loop to replay writes: a failed response can hide a committed write, and independently retried requests can execute out of order. See roblox-datastores for write reconciliation and per-key ordering.
local function readWithRetry(fn, maxAttempts)
maxAttempts = maxAttempts or 5
for attempt = 1, maxAttempts do
local ok, result = pcall(fn)
if ok then
return true, result
elseif attempt == maxAttempts then
return false, result
else
warn("DataStore attempt " .. attempt .. " failed; retrying...")
task.wait(2 ^ attempt * 0.1 + math.random() * 0.5)
end
end
endAlways call DataStores from the server and validate serialization before saving.
Memory snapshot comparison
Use the Developer Console Memory tab or Scene Analysis to compare snapshots:
- Capture a baseline snapshot in a stable state.
- Play through the action that may leak (spawn/despawn enemies, open/close UI).
- Return to the stable state and capture a second snapshot.
- Compare PlaceMemory, Luau heap, and instance counts.
- Investigate categories that did not return to baseline; look for unparented instances in Scene Analysis.
MicroProfiler
Open with Ctrl+F6 (⌘+F6) in Studio or the desktop client.
Use it to:
- Find frame-time spikes.
- Identify whether a bottleneck is script compute, physics, or rendering.
- Capture server dumps from the Developer Console.
- Add custom labels with
debug.profilebegin/debug.profileend.
Key colors:
- Orange: worker thread (scripts, physics, animations) bottleneck.
- Blue: render thread bottleneck.
- Red: GPU wait / render complexity.
Scene Analysis
Available in Studio under Window → Performance Summary → Scene Analysis.
Views:
- Script memory: per-script Luau heap.
- Unparented instances: potential memory leaks held by scripts.
- Instance composition: counts by category.
- Audio/Animation memory: asset memory usage.
- Triangle composition: draw call breakdown.
Scene Analysis is a Studio UI tool; there is no public SceneAnalysisService API.
Script Profiler
Records CPU time per script. Use it when MicroProfiler points to scripts but you need to know which script.
Common bug categories
| Symptom | Likely causes |
| Script silently fails | Missing pcall, error swallowed, wrong script context |
| Data not saving | DataStore called from client, non-serializable value, no pcall |
| Remote not working | Wrong side, handler not connected, argument mismatch |
| Lag spikes | Pathfinding every frame, too many particles, unbatched loops |
| Physics jitter | Wrong network ownership, assembly splits, conflicting constraints |
| NPCs stuck | Blocked path not recomputed, bad agent params, streaming issues |
| UI doesn't update | Property not replicated, wrong parent, layout order |
| Memory grows forever | Leaked connections, unparented instances, cached assets |
Network debugging
- Check Network tab in Developer Console for HTTP/DataStore failures.
- Use
Shift+F3in-game for network debug stats. - Distinguish network ping (round-trip time) from data ping (replication queue).
- Use Studio's beta Network Simulator for separate inbound/outbound latency, jitter, and packet loss. Enable New Device Simulator in Beta Features, restart Studio, then open Test → Device Simulator → Network. Select Apply to activate staged changes. Ideal Fiber still adds 8 ms each way; use all-zero custom values for a zero-added-delay baseline. See network simulation.
Load time debugging
Measure load time:
local start = os.clock()
game.Loaded:Connect(function()
print("Loaded in", os.clock() - start)
end)Run this from a LocalScript in ReplicatedFirst. It starts timing when ReplicatedFirst replicates and stops when game.Loaded fires, so it excludes the time to connect to the server and load the avatar. Load time as players experience it, from clicking Play to the world rendering, is longer. Enable Print Join Size Breakdown in Studio Settings → Network to see the largest replicated instances.
Scripts
scripts/TestRunner.lua: a minimal TestEZ fallback with nested suites, lifecycle hooks, matchers, async support, and TestService integration.scripts/Logger.lua: a structured logger with level filtering and guarded formatting.scripts/DebugDraw.lua: utility for drawing rays, points, and boxes in 3D for visual debugging.
How to proceed
- Reproduce the issue reliably.
- Check logs and errors in the Developer Console.
- Determine client vs server scope.
- Use MicroProfiler/Script Profiler for performance issues.
- Use Scene Analysis for memory leaks and scene composition.
- Add targeted logging or tests to confirm the fix.
- Verify on low-end devices and with network simulation when relevant.
- Compare memory snapshots before and after suspected leaks.
<!-- catalog:references:start -->Reference index
- common-bugs-and-fixes.md: Trace a symptom to likely causes and a focused fix.
- debugging-tools.md: Inspect logs, breakpoints, stack traces, or runtime state.
- network-simulation.md: Reproduce latency, jitter, or packet-loss problems in Studio.
- performance-profiling.md: Find CPU, GPU, memory, or load-time bottlenecks.
- testing-patterns.md: Write unit tests, mock dependencies, or test client-server flows.
<!-- catalog:references:end -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

