wheels test run
Run TestBox tests for your application with advanced features.
Synopsis
wheels test run [spec] [options]
Description
The wheels test run
command executes your application's TestBox test suite with support for watching, filtering, and various output formats. This is the primary command for running your application tests (as opposed to framework tests).
Options
filter
Filter tests by pattern or name
group
Run specific test group
--coverage
Generate coverage report (boolean flag)
false
reporter
Test reporter format: console, junit, json, tap
console
--watch
Watch for file changes and rerun tests (boolean flag)
false
--verbose
Verbose output (boolean flag)
false
--fail-fast
Stop on first test failure (boolean flag)
false
Examples
Run all tests
wheels test run
Filter tests by pattern
wheels test run filter="User"
wheels test run filter="test_user_validation"
Watch mode
wheels test run --watch
Run specific test group
wheels test run group="unit"
wheels test run group="integration"
Generate coverage report
wheels test run --coverage
Use different reporter
wheels test run reporter=json
wheels test run reporter=junit
wheels test run reporter=tap
Stop on first failure
wheels test run --fail-fast
Verbose output with coverage
wheels test run --verbose --coverage reporter=console
Test Structure
Standard test directory layout:
/tests/
├── Application.cfc # Test configuration
├── models/ # Model tests
│ ├── UserTest.cfc
│ └── ProductTest.cfc
├── controllers/ # Controller tests
│ ├── UsersTest.cfc
│ └── ProductsTest.cfc
├── views/ # View tests
├── integration/ # Integration tests
└── helpers/ # Test helpers
Writing Tests
Model Test Example
component extends="testbox.system.BaseSpec" {
function run() {
describe("User Model", function() {
beforeEach(function() {
// Reset test data
application.wirebox.getInstance("User").deleteAll();
});
it("validates required fields", function() {
var user = model("User").new();
expect(user.valid()).toBeFalse();
expect(user.errors).toHaveKey("email");
expect(user.errors).toHaveKey("username");
});
it("saves with valid data", function() {
var user = model("User").new(
email="[email protected]",
username="testuser",
password="secret123"
);
expect(user.save()).toBeTrue();
expect(user.id).toBeGT(0);
});
it("prevents duplicate emails", function() {
var user1 = model("User").create(
email="[email protected]",
username="user1"
);
var user2 = model("User").new(
email="[email protected]",
username="user2"
);
expect(user2.valid()).toBeFalse();
expect(user2.errors.email).toContain("already exists");
});
});
}
}
Controller Test Example
component extends="testbox.system.BaseSpec" {
function run() {
describe("Products Controller", function() {
it("lists all products", function() {
// Create test data
var product = model("Product").create(name="Test Product");
// Make request
var event = execute(
event="products.index",
renderResults=true
);
// Assert response
expect(event.getRenderedContent()).toInclude("Test Product");
expect(event.getValue("products")).toBeArray();
});
it("requires auth for create", function() {
var event = execute(
event="products.create",
renderResults=false
);
expect(event.getValue("relocate_URI")).toBe("/login");
});
});
}
}
Test Configuration
/tests/Application.cfc
component {
this.name = "WheelsTestingSuite" & Hash(GetCurrentTemplatePath());
// Use test datasource
this.datasources["wheelstestdb"] = {
url = "jdbc:h2:mem:wheelstestdb;MODE=MySQL"
};
this.datasource = "wheelstestdb";
// Test settings
this.testbox = {
testBundles = "tests",
recurse = true,
reporter = "simple",
labels = "",
options = {}
};
}
Watch Mode
Watch mode reruns tests on file changes:
wheels test run --watch
Output:
[TestBox Watch] Monitoring for changes...
[TestBox Watch] Watching: /tests, /models, /controllers
[14:23:45] Change detected: models/User.cfc
[14:23:45] Running tests...
✓ User Model > validates required fields (12ms)
✓ User Model > saves with valid data (45ms)
✓ User Model > prevents duplicate emails (23ms)
Tests: 3 passed, 0 failed
Time: 80ms
[TestBox Watch] Waiting for changes...
Reporters
Simple (Default)
wheels test run reporter=simple
Colored console output
Shows progress dots
Summary at end
Text
wheels test run reporter=text
Plain text output
Good for CI systems
No colors
JSON
wheels test run reporter=json
{
"totalDuration": 523,
"totalSpecs": 25,
"totalPass": 24,
"totalFail": 1,
"totalError": 0,
"totalSkipped": 0
}
JUnit
wheels test run reporter=junit outputFile=results.xml
JUnit XML format
For CI integration
Jenkins compatible
TAP
wheels test run reporter=tap
Test Anything Protocol
Cross-language format
Filtering Tests
By Bundle
# Run only model tests
wheels test run bundles=models
# Run multiple bundles
wheels test run bundles=models,controllers
By Label
it("can authenticate", function() {
// test code
}).labels("auth,critical");
# Run only critical tests
wheels test run labels=critical
# Run auth OR api tests
wheels test run labels=auth,api
By Name Filter
# Run tests matching pattern
wheels test run filter="user"
wheels test run filter="validate*"
Exclude Patterns
# Skip slow tests
wheels test run excludes="*slow*,*integration*"
Parallel Execution
Run tests in parallel threads:
wheels test run threads=4
Benefits:
Faster execution
Better CPU utilization
Finds concurrency issues
Code Coverage
Generate coverage reports:
wheels test run --coverage coverageOutputDir=coverage/
View report:
open coverage/index.html
Test Helpers
Create reusable test utilities:
// /tests/helpers/TestHelper.cfc
component {
function createTestUser(struct overrides={}) {
var defaults = {
email: "test#CreateUUID()#@example.com",
username: "user#CreateUUID()#",
password: "testpass123"
};
return model("User").create(
argumentCollection = defaults.append(arguments.overrides)
);
}
function loginAs(required user) {
session.userId = arguments.user.id;
session.isAuthenticated = true;
}
}
Database Strategies
Transaction Rollback
function beforeAll() {
transaction action="begin";
}
function afterAll() {
transaction action="rollback";
}
Database Cleaner
function beforeEach() {
queryExecute("DELETE FROM users");
queryExecute("DELETE FROM products");
}
Fixtures
function loadFixtures() {
var users = deserializeJSON(
fileRead("/tests/fixtures/users.json")
);
for (var userData in users) {
model("User").create(userData);
}
}
CI/CD Integration
GitHub Actions
- name: Run tests
run: |
wheels test run reporter=junit outputFile=test-results.xml
- name: Upload results
uses: actions/upload-artifact@v4
with:
name: test-results
path: test-results.xml
Pre-commit Hook
#!/bin/bash
# .git/hooks/pre-commit
echo "Running tests..."
wheels test run labels=unit
if [ $? -ne 0 ]; then
echo "Tests failed. Commit aborted."
exit 1
fi
Performance Tips
Use labels for fast feedback
wheels test run labels=unit # Fast wheels test run labels=integration # Slow
Parallel execution
wheels test run threads=4
Watch specific directories
wheels test run tests/models --watch
Skip slow tests during development
wheels test run excludes="*integration*"
Common Issues
Out of Memory
# Increase memory
box server set jvm.heapSize=1024
box server restart
Test Pollution
Use
beforeEach
/afterEach
Reset global state
Use transactions
Flaky Tests
Avoid time-dependent tests
Mock external services
Use fixed test data
See Also
wheels test - Run framework tests
wheels test coverage - Generate coverage
wheels test debug - Debug tests
wheels generate test - Generate test files
Last updated
Was this helpful?