Skip to main content

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

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

  1. Use descriptive test names that explain the expected behavior
  2. Always set timeouts to prevent hanging tests
  3. Record metrics for performance tracking over time
  4. Clean up after tests to ensure isolation
  5. Handle device differences explicitly in test logic
  6. Use appropriate wait conditions based on what you're testing
  7. Assert meaningful conditions not just "truthy" values
  8. 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