Skip to content

Add streaming test results via Server-Sent Events (SSE)#189

Merged
lmajano merged 13 commits into
developmentfrom
feature/streaming-test-results
Mar 12, 2026
Merged

Add streaming test results via Server-Sent Events (SSE)#189
lmajano merged 13 commits into
developmentfrom
feature/streaming-test-results

Conversation

@elpete

@elpete elpete commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds real-time streaming test results output via Server-Sent Events (SSE), allowing test consumers (like testbox-cli) to display test progress as tests execute rather than waiting for the entire test run to complete.

Features

  • StreamingService.cfc - Core SSE service that handles event emission during test execution
  • StreamingRunner.cfm - New runner endpoint that streams test events in real-time
  • Enable with streaming=true URL parameter

Event Types

The SSE stream emits the following events:

  • testRunStart - Emitted when the entire test run begins
  • bundleStart / bundleEnd - Bundle lifecycle events (correlate via path field)
  • suiteStart / suiteEnd - Suite lifecycle events
  • specStart / specEnd - Individual spec lifecycle events
  • testRunEnd - Final event with complete TestBox results

Compatibility

  • Adobe ColdFusion 2021+
  • Lucee 5+
  • BoxLang

Related

Testing

The streaming can be tested by:

  1. Starting a TestBox server
  2. Accessing /tests/runner.cfm?streaming=true
  3. Observing SSE events in browser dev tools or using curl

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

lucee@5 21 Test Results

  1 files  ± 0   24 suites  +1   7s ⏱️ ±0s
362 tests +32  349 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  355 ✅ +32  22 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

lucee@7 21 Test Results

  1 files  ± 0   24 suites  +1   6s ⏱️ -1s
362 tests +32  349 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  355 ✅ +32  22 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

lucee@6 21 Test Results

  1 files  ± 0   24 suites  +1   7s ⏱️ -1s
362 tests +32  349 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  355 ✅ +32  22 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

boxlang@be 21 Test Results

  1 files  ± 0   25 suites  +1   7s ⏱️ ±0s
408 tests +32  387 ✅ +32  21 💤 ±0  0 ❌ ±0 
425 runs  +32  393 ✅ +32  32 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

boxlang@1 21 Test Results

  1 files  ± 0   25 suites  +1   7s ⏱️ -1s
408 tests +32  387 ✅ +32  21 💤 ±0  0 ❌ ±0 
425 runs  +32  393 ✅ +32  32 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

boxlang-cfml@1 21 Test Results

  1 files  ± 0   25 suites  +1   7s ⏱️ -1s
409 tests +32  388 ✅ +32  21 💤 ±0  0 ❌ ±0 
425 runs  +32  394 ✅ +32  31 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

adobe@2023 21 Test Results

  1 files  ± 0   24 suites  +1   7s ⏱️ +2s
361 tests +32  348 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  354 ✅ +32  23 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

adobe@2021 11 Test Results

  1 files  ± 0   24 suites  +1   6s ⏱️ ±0s
361 tests +32  348 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  354 ✅ +32  23 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

adobe@2025 21 Test Results

  1 files  ± 0   24 suites  +1   6s ⏱️ ±0s
344 tests +15  331 ✅ +15  13 💤 ±0  0 ❌ ±0 
360 runs  +15  337 ✅ +15  23 💤 ±0  0 ❌ ±0 

Results for commit f653257. ± Comparison against base commit e14c941.

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown

adobe@2025 21 Test Results

  1 files  ± 0   24 suites  +1   7s ⏱️ -1s
361 tests +32  348 ✅ +32  13 💤 ±0  0 ❌ ±0 
377 runs  +32  354 ✅ +32  23 💤 ±0  0 ❌ ±0 

Results for commit 86a2698. ± Comparison against base commit 556e7cc.

♻️ This comment has been updated with latest results.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds real-time streaming of test results via Server-Sent Events (SSE) to TestBox. It introduces a new StreamingService.cfc utility class and a StreamingRunner.cfm runner endpoint, and enables the feature via a streaming=true URL parameter in the existing test runner files.

Changes:

  • New StreamingService.cfc: Core SSE service that emits progress events (testRunStart, bundleStart/End, suiteStart/End, specStart/End, testRunEnd) during test execution via writeOutput/cfflush.
  • New StreamingRunner.cfm: Runner endpoint that initializes SSE headers, runs TestBox with streaming callbacks, and emits a final testRunEnd event with the full results memento.
  • Updated tests/runner.cfm and cfml/tests/runner.cfm: Added url.streaming parameter and conditional routing to either StreamingRunner.cfm or the existing HTMLRunner.cfm.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
system/util/StreamingService.cfc New core SSE service: sets response headers, streams events as JSON-encoded SSE, provides TestBox lifecycle callbacks
system/runners/StreamingRunner.cfm New runner that wires StreamingService to TestBox and streams testRunStart/testRunEnd framing events
tests/runner.cfm Adds url.streaming param and conditional include for StreamingRunner vs HTMLRunner
cfml/tests/runner.cfm Same streaming conditional routing for the CFML-specific test runner
tests/specs/streaming/StreamingServiceTest.cfc New unit tests for StreamingService callbacks and event data structures
server-boxlang-cfml@1.json Whitespace/indentation normalization only — no functional change

Comment thread system/util/StreamingService.cfc
Comment thread tests/specs/streaming/StreamingServiceTest.cfc Outdated
Comment thread system/runners/StreamingRunner.cfm
Comment thread system/util/StreamingService.cfc Outdated
Comment thread system/util/StreamingService.cfc
Comment thread system/util/StreamingService.cfc Outdated
Comment thread system/runners/StreamingRunner.cfm Outdated
@elpete elpete self-assigned this Mar 3, 2026
elpete added 2 commits March 9, 2026 13:19
Implement real-time test progress streaming for CI tools like CommandBox to display
incremental progress instead of waiting for entire test suite completion.

- Add StreamingService.cfc with SSE utilities and TestBox callbacks
- Add StreamingRunner.cfm endpoint activated via ?streaming=true URL param
- Update runner.cfm files to support streaming mode
- Add comprehensive unit tests for StreamingService
@elpete elpete force-pushed the feature/streaming-test-results branch from 6b60e95 to 855cb7b Compare March 9, 2026 19:20
elpete added 11 commits March 9, 2026 18:37
…events

The bundle stats (including id) are not available when onBundleStart fires,
so consumers should use the 'path' field for correlation instead.
Use savecontent to capture actual output from streamEvent instead of
testing manually constructed strings.
Wrap writeOutput/cfflush in try/catch to prevent client disconnects from
interrupting test execution. Errors are logged to testbox-streaming log file.
When a test suite uses asyncAll=true, spec events are invoked from cfthread
and won't be streamed in real-time since writeOutput/cfflush don't affect
the parent request's HTTP response buffer.
Instead of assuming the last bundleStats entry corresponds to the current
bundle, match by path using the target's metadata. Falls back to last entry
if no match is found.
If an exception propagates out of runRaw(), stream an 'error' event before
rethrowing so SSE consumers can detect the failure instead of waiting
indefinitely for testRunEnd.
Generate id using hash(path) so consumers can correlate bundleStart
and bundleEnd events. This id is deterministic and available before
internal bundle stats are created.
- Add flushEnabled property (default true) to StreamingService
- Skip cfflush when flushEnabled is false to prevent response commit
- Update tests to disable flushing and fix bundleEnd id assertion
The SSE format test was failing on Lucee because savecontent doesn't
capture writeOutput from nested method calls. Added formatSSEEvent()
method that returns the formatted string directly, which streamEvent()
now uses internally. Tests now call formatSSEEvent() directly instead
of relying on savecontent to capture writeOutput.
Implement thread-safe event queuing using ConcurrentLinkedQueue so SSE
streaming works when specs run in parallel cfthread blocks. Events are
auto-queued when detected inside a thread, then drained to output after
thread joins via onAsyncDrain callback.
@lmajano lmajano merged commit acd98e8 into development Mar 12, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants