Writing Your First Test Cases
Our testing framework follows familiar patterns from popular testing libraries like Jest or Mocha. Tests are organized using describe
blocks for grouping and it
blocks for individual test cases.
Basic Test Structure
Here's how to structure a simple test:
describe("App Basic Test", function()
it("should open and capture home screen", function()
-- Open the current app
openAppById(device.currentAppId())
-- Wait for the app to load
local time, frame = wait.forScreen("Home", { timeout = 30000 })
-- Verify we got results
assert.truthy(frame)
assert.truthy(time)
-- Record metrics
metric.record("app_start_time", time)
print("Test completed in " .. tostring(time) .. "ms")
end)
end)
Available Assertions
Our testing framework provides comprehensive assertion methods:
-- Equality checks
assert.is.equal(actual, expected) -- Strict equality
assert.truthy(value) -- Not false or nil
assert.falsy(value) -- false or nil
-- Boolean checks
assert.True(condition) -- Exactly true
assert.False(condition) -- Exactly false
-- Error handling
assert.has_error(function()
error("test error")
end, "test error") -- Function throws expected error
Test Organization
Grouping Related Tests
describe("App Lifecycle", function()
describe("Startup", function()
it("should start cold", function() --[[ test ]] end)
it("should start warm", function() --[[ test ]] end)
end)
describe("Navigation", function()
it("should navigate to search", function() --[[ test ]] end)
it("should navigate to settings", function() --[[ test ]] end)
end)
end)
Setup and Teardown
describe("Video Tests", function()
local originalRateLimit
before(function()
-- Setup before all tests
originalRateLimit = network.getCurrentRateLimit()
end)
after(function()
-- Cleanup after all tests
network.setRateLimit(originalRateLimit)
end)
beforeEach(function()
-- Setup before each test
openAppById(device.currentAppId(), { coldStart = true })
end)
it("should test with clean state", function()
-- Test implementation
end)
end)
Error Handling
describe("Error Handling", function()
it("should handle missing screens gracefully", function()
local success, err = pcall(function()
wait.forScreen("NonExistentScreen", { timeout = 5000 })
end)
assert.falsy(success)
assert.truthy(string.find(err, "timeout"))
end)
end)
Testing Best Practices
- Use descriptive test names that explain the expected behavior
- Always set timeouts to prevent hanging tests
- Record metrics for performance tracking over time
- Clean up after tests to ensure isolation
- Handle device differences explicitly in test logic
- Use appropriate wait conditions based on what you're testing
- Assert meaningful conditions not just "truthy" values
- Include timing measurements for performance analysis
Ready for Real Testing?
Now that you understand test structure and organization, explore comprehensive examples for common testing scenarios:
Next: Test Patterns - Complete examples for app startup, navigation, video playback, AI automation, and more