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="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,
         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

  1. Use labels for fast feedback

    wheels test run labels=unit  # Fast
    wheels test run labels=integration  # Slow
  2. Parallel execution

    wheels test run threads=4
  3. 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

Last updated

Was this helpful?