Object Relational Mapping
Creating Records
Reading Records
Updating Records
Deleting Records
Column Statistics
Dynamic Finders
Getting Paginated Data
Associations
Nested Properties
Object Validation
Object Callbacks
Calculated Properties
Transactions
Dirty Records
Soft Delete
Automatic Time Stamps
Using Multiple Data Sources
wheels test run
Run TestBox tests for your CFWheels application using the TestBox CLI integration.
Note: This command replaces the deprecated
wheels test
command.
Prerequisites
Install TestBox CLI
box install testbox-cli --global
Synopsis
wheels test run [spec] [options]
Description
The wheels test run
command executes your application's TestBox test suite with support, filtering, and various output formats. This is the primary command for running your application tests (as opposed to framework tests).
Options
| Option | Description | Default |
|--------|-------------|---------|
| filter
| Filter tests by pattern or name | |
| group
| Run specific test group | |
| --coverage
| Generate coverage report (boolean flag) | false
|
| format
| Test format format:txt, junit, json | txt
|
| --verbose
| Verbose output (boolean flag) | true
|
| --failFast
| 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"
Run specific test group
wheels test run group="unit"
wheels test run group="integration"
Generate coverage report
wheels test run --coverage
Use different format
wheels test run format=json
wheels test run format=junit
wheels test run format=tap
Stop on first failure
wheels test run --fail-fast
Verbose output with coverage
wheels test run --verbose --coverage format=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="wheels.Testbox" {
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="test@example.com",
username="testuser",
password="secret123"
);
expect(user.save()).toBeTrue();
expect(user.id).toBeGT(0);
});
it("prevents duplicate emails", function() {
var user1 = model("User").create(
email="test@example.com",
username="user1"
);
var user2 = model("User").new(
email="test@example.com",
username="user2"
);
expect(user2.valid()).toBeFalse();
expect(user2.errors.email).toContain("already exists");
});
});
}
}
Controller Test Example
component extends="wheels.Testbox" {
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,
format = "simple",
labels = "",
options = {}
};
}
Reporters
Simple (Default)
wheels test run format=simple
- Colored console output
- Shows progress dots
- Summary at end
txt
wheels test run format=txt
- Plain txt output
- Good for CI systems
- No colors
JSON
wheels test run format=json
√ tests.specs.functions.Example (3 ms)
[Passed: 1] [Failed: 0] [Errors: 0] [Skipped: 0] [Suites/Specs: 1/1]
√ Tests that DummyTest
√ is Returning True (1 ms)
╔═════════════════════════════════════════════════════════════════════╗
║ Passed ║ Failed ║ Errored ║ Skipped ║ Bundles ║ Suites ║ Specs ║
╠═════════════════════════════════════════════════════════════════════╣
║ 1 ║ 0 ║ 0 ║ 0 ║ 1 ║ 1 ║ 1 ║
╚═════════════════════════════════════════════════════════════════════╝
JUnit
wheels test run format=junit outputFile=results.xml
- JUnit XML format
- For CI integration
- Jenkins compatible
TAP
wheels test run format=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 format=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
-
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
- Prerequisites
- Install TestBox CLI
- Synopsis
- Options
- Examples
- Run all tests
- Filter tests by pattern
- Run specific test group
- Generate coverage report
- Use different format
- Stop on first failure
- Verbose output with coverage
- Test Structure
- Writing Tests
- Model Test Example
- Controller Test Example
- Test Configuration
- /tests/Application.cfc
- Reporters
- Simple (Default)
- txt
- JSON
- JUnit
- TAP
- Filtering Tests
- By Bundle
- By Label
- By Name Filter
- Exclude Patterns
- Parallel Execution
- Code Coverage
- Test Helpers
- Database Strategies
- Transaction Rollback
- Database Cleaner
- Fixtures
- CI/CD Integration
- GitHub Actions
- Pre-commit Hook
- Performance Tips
- Common Issues
- Out of Memory
- Test Pollution
- Flaky Tests
- See Also