|
| 1 | +# Copilot Instructions for TestBox |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +TestBox is the leading BDD/TDD testing framework for BoxLang and CFML applications. It supports both BDD (Behavior-Driven Development) and xUnit testing styles, providing a comprehensive testing ecosystem with built-in mocking capabilities (MockBox), multiple reporters, and CLI/web test runners. BoxLang is now the primary focus while maintaining full CFML compatibility. |
| 6 | + |
| 7 | +## Architecture & Core Components |
| 8 | + |
| 9 | +### Core Testing Engine |
| 10 | +- **TestBox.cfc** (`system/TestBox.cfc`): Main orchestrator handling test execution, bundle discovery, and result aggregation |
| 11 | +- **BaseSpec.cfc** (`system/BaseSpec.cfc`): Base class for all test specs - provides both BDD DSL (`describe()`, `it()`, `beforeEach()`) and xUnit methods (`setup()`, `test*()`, `tearDown()`) |
| 12 | +- **Expectation.cfc** (`system/Expectation.cfc`): BDD assertion engine with fluent matcher API (`expect().toBe()`, `expect().notToBeEmpty()`) |
| 13 | +- **MockBox.cfc** (`system/MockBox.cfc`): Standalone mocking framework for creating spies, stubs, and mocks |
| 14 | + |
| 15 | +### Multi-Language Support Pattern |
| 16 | +- **BoxLang Primary**: `.bx` files supported with dedicated `BoxLangRunner.bx` CLI runner |
| 17 | +- **CFML Compatibility**: `.cfc` files with traditional CFML runners (`BDDRunner.cfc`, `UnitRunner.cfc`) |
| 18 | +- **File Discovery**: Default bundle pattern `*Spec*.cfc|*Test*.cfc|*Spec*.bx|*Test*.bx` |
| 19 | + |
| 20 | +### Code Formatting Standards |
| 21 | +- **Spacing Requirements**: All code must include spacing on all markers for improved readability (`.cfformat.json`) |
| 22 | +- **Key Rules**: Padding in brackets `( condition )`, function calls `func( arg )`, structs `{ key : value }`, arrays `[ item, item ]` |
| 23 | +- **Operators**: Binary operators require padding `a + b`, `x == y` |
| 24 | +- **Alignment**: Consecutive assignments, properties, and parameters are aligned |
| 25 | +- **Indentation**: 4-space tabs, max 115 columns, double quotes for strings |
| 26 | + |
| 27 | +### Reporter Architecture |
| 28 | +- **Interface-Driven**: All reporters implement `IReporter.cfc` interface |
| 29 | +- **Multi-Format Output**: HTML, JSON, XML, Console, TAP, JUnit, ANT-JUnit formats |
| 30 | +- **Context-Aware**: CLI mode defaults to `text` reporter, web mode defaults to `simple` reporter |
| 31 | + |
| 32 | +## Critical Developer Workflows |
| 33 | + |
| 34 | +### Test Bundle Structure Pattern |
| 35 | +```javascript |
| 36 | +// BDD Style - All test specs must extend BaseSpec |
| 37 | +component extends="testbox.system.BaseSpec" { |
| 38 | + function run() { |
| 39 | + describe("Feature Name", function() { |
| 40 | + beforeEach(function() { /* setup */ }); |
| 41 | + it("should do something", function() { |
| 42 | + expect(actual).toBe(expected); |
| 43 | + }); |
| 44 | + }); |
| 45 | + } |
| 46 | +} |
| 47 | + |
| 48 | +// xUnit Style - Traditional unit testing approach |
| 49 | +component extends="testbox.system.BaseSpec" { |
| 50 | + function setup() { |
| 51 | + // Global setup before each test |
| 52 | + } |
| 53 | + |
| 54 | + function testSomething() { |
| 55 | + var actual = someFunction(); |
| 56 | + $assert.isEqual(expected, actual); |
| 57 | + } |
| 58 | + |
| 59 | + function tearDown() { |
| 60 | + // Cleanup after each test |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +### CLI Testing via BoxLang Runner |
| 66 | +```bash |
| 67 | +# Primary CLI execution method |
| 68 | +./testbox/bin/run # Run default tests.specs |
| 69 | +./testbox/bin/run --directory=my.tests # Specific directory |
| 70 | +./testbox/bin/run --bundles=my.bundle # Specific bundles |
| 71 | +./testbox/bin/run --reporter=json # Custom reporter |
| 72 | +``` |
| 73 | + |
| 74 | +### Web Testing Setup |
| 75 | +- **HTMLRunner.cfm**: Web-based test execution endpoint |
| 76 | +- **Application.cfc**: Sets up TestBox mappings and routes |
| 77 | +- **URL Parameters**: `?method=runRemote&bundles=...&reporter=...` |
| 78 | + |
| 79 | +### Build & Development Commands |
| 80 | +```bash |
| 81 | +# Format code (BoxLang + CFML) |
| 82 | +box run-script format |
| 83 | + |
| 84 | +# Multi-engine testing |
| 85 | +box run-script start:lucee |
| 86 | +box run-script start:2023 |
| 87 | + |
| 88 | +# Release process |
| 89 | +box run-script release |
| 90 | +``` |
| 91 | + |
| 92 | +## Key Implementation Patterns |
| 93 | + |
| 94 | +### Dual Testing Approach |
| 95 | +- **BDD Style**: Uses `describe()`, `it()`, `beforeEach()`, `afterEach()` for behavior specification |
| 96 | +- **xUnit Style**: Uses `setup()`, `test*()`, `tearDown()` methods for traditional unit testing |
| 97 | +- **Assertion Methods**: BDD uses `expect()` fluent API, xUnit uses `$assert` object methods |
| 98 | +- **Mixed Usage**: Both styles can coexist within the same test bundle |
| 99 | + |
| 100 | +### BDD DSL Implementation |
| 101 | +- **Suite Nesting**: `describe()` blocks create nested test suites stored in `this.$suites` array |
| 102 | +- **Execution Context**: `this.$suiteContext` tracks current suite being defined |
| 103 | +- **Lifecycle Hooks**: `beforeEach()`, `afterEach()`, `beforeAll()`, `afterAll()` stored per suite |
| 104 | + |
| 105 | +### xUnit Pattern Implementation |
| 106 | +- **Method Discovery**: Test methods automatically discovered by `test*` prefix convention |
| 107 | +- **Lifecycle Methods**: `setup()` and `tearDown()` called before/after each test method |
| 108 | +- **Global Hooks**: `beforeTests()` and `afterTests()` for bundle-level setup/cleanup |
| 109 | +- **Assertion Object**: `$assert` provides traditional assertion methods (`isEqual()`, `isTrue()`, `isNull()`) |
| 110 | + |
| 111 | +### MockBox Integration Pattern |
| 112 | +```javascript |
| 113 | +// MockBox is integrated into BaseSpec - comprehensive mocking framework |
| 114 | +var mockService = createMock( "path.to.Service" ); |
| 115 | +mockService.$( "methodName" ).$results( "mockValue" ); |
| 116 | +mockService.$( "methodName", "arg1" ).$args( "arg1" ).$results( "specificResult" ); |
| 117 | + |
| 118 | +// Advanced mocking capabilities |
| 119 | +var spy = createSpy( targetObject, "methodName" ); |
| 120 | +var stub = createStub().$( "getData" ).$results( mockData ); |
| 121 | +var emptyMock = createEmptyMock( "com.interfaces.IService" ); |
| 122 | + |
| 123 | +// Verification patterns |
| 124 | +expect( mockService.$callLog().getData ).toHaveLength( 1 ); |
| 125 | +expect( mockService.$times( 2, "methodName" ) ).toBeTrue(); |
| 126 | +``` |
| 127 | + |
| 128 | +### Expectation Chaining Architecture |
| 129 | +- **Fluent API**: `expect(actual).toBe(expected).toHaveLength(3)` |
| 130 | +- **Negation Pattern**: Dynamic `not` prefix (`expect().notToBe()`) |
| 131 | +- **Custom Matchers**: Register via `registerMatcher(name, closure)` |
| 132 | + |
| 133 | +### Coverage Service Integration |
| 134 | +- **CoverageService.cfc**: Built-in code coverage analysis |
| 135 | +- **Configuration**: Via `options.coverage` struct in TestBox constructor |
| 136 | +- **Integration**: Automatic coverage collection during test execution |
| 137 | + |
| 138 | +### Dependency Management |
| 139 | +- **cbstreams**: Functional programming utilities for data manipulation and stream processing |
| 140 | +- **cbMockData**: Full-featured data mocking library providing realistic test data generation (names, addresses, numbers, dates, lorem text) |
| 141 | +- **globber**: File pattern matching and discovery utilities for test bundle location |
| 142 | +- **MockBox**: Integrated mocking framework (spies, stubs, mocks) with verification capabilities |
| 143 | +- **Installation**: Dependencies auto-installed to `system/modules/` via CommandBox package manager |
| 144 | + |
| 145 | +## Testing Conventions |
| 146 | + |
| 147 | +### File Organization |
| 148 | +- **Test Location**: `tests/specs/` directory by convention |
| 149 | +- **Naming**: `*Test.cfc`, `*Spec.cfc`, `*Test.bx`, `*Spec.bx` patterns |
| 150 | +- **Suite Structure**: Mirror source code directory structure in test folders |
| 151 | + |
| 152 | +### Label-Based Filtering |
| 153 | +```javascript |
| 154 | +// Suite labeling for selective execution |
| 155 | +describe("Feature", { labels: "slow,integration" }, function() { |
| 156 | + it("test case", { labels: "unit" }, function() { /* */ }); |
| 157 | +}); |
| 158 | + |
| 159 | +// CLI filtering: --labels=unit --excludes=slow |
| 160 | +``` |
| 161 | + |
| 162 | +### Focused Testing |
| 163 | +- **fdescribe()** / **fit()**: Focus execution on specific suites/specs |
| 164 | +- **xdescribe()** / **xit()**: Skip suites/specs during development |
| 165 | + |
| 166 | +## Integration Points |
| 167 | + |
| 168 | +### ColdBox Framework Integration |
| 169 | +- **Enhanced BaseSpec**: ColdBox provides extended base spec with framework-specific helpers |
| 170 | +- **Application Testing**: Built-in request/response simulation for integration tests |
| 171 | +- **Service Mocking**: Deep integration with WireBox for dependency injection testing |
| 172 | + |
| 173 | +### CommandBox Integration |
| 174 | +- **TestBox CLI**: `testbox-cli` package provides `testbox run` commands |
| 175 | +- **File Watching**: Automatic test re-execution on file changes |
| 176 | +- **CI/CD Integration**: JUnit/TAP/JSON output formats for build systems |
| 177 | + |
| 178 | +### Standalone Usage |
| 179 | +- **Framework Agnostic**: Can test any BoxLang/CFML application |
| 180 | +- **Mapping Requirements**: Requires `/testbox` mapping to system directory |
| 181 | +- **Web Server**: Can run via any CFML web server (Lucee, Adobe CF, CommandBox) |
| 182 | + |
| 183 | +## Development Commands |
| 184 | + |
| 185 | +```bash |
| 186 | +# Core development workflow |
| 187 | +box install # Install dependencies |
| 188 | +box run-script format # Format all code (.cfformat.json rules) |
| 189 | +box run-script format:check # Check formatting without changes |
| 190 | +box run-script format:watch # Auto-format on file changes |
| 191 | +box run-script start:lucee # Start development server |
| 192 | +./testbox/bin/run # Run tests via BoxLang CLI |
| 193 | + |
| 194 | +# Multi-engine testing |
| 195 | +box run-script start:adobe # Adobe CF 2025 |
| 196 | +box run-script start:boxlang # BoxLang server |
| 197 | +box run-script log:lucee # View server logs |
| 198 | +box run-script log:adobe # View Adobe CF logs |
| 199 | +box run-script log:boxlang # View BoxLang logs |
| 200 | +``` |
0 commit comments