Skip to content

Add testing support option to introduce latency#15937

Open
jdaugherty wants to merge 1 commit into
8.0.xfrom
feat/latency-testing
Open

Add testing support option to introduce latency#15937
jdaugherty wants to merge 1 commit into
8.0.xfrom
feat/latency-testing

Conversation

@jdaugherty

Copy link
Copy Markdown
Contributor

Description

Adds a new testing support library, grails-testing-support-latency, that injects artificial
latency into a running Grails application so that requests randomly take longer.

Why: Functional tests are prone to timing bugs — assertions that race a click-triggered
navigation, missing waits, response-ordering assumptions. These pass reliably on fast local
machines and fail intermittently on slower CI infrastructure (see the recent
User1FunctionalSpec.'edit report 20' flake in the spring-security ACL functional test app,
which only reproduced when the server response was slow). Slowing responses down widens the
window in which these bugs occur, turning rare flakes into deterministic failures that can be
found and fixed locally.

What:

  • New module grails-testing-support-latency (org.apache.grails:grails-testing-support-latency):
    • LatencyFilter — a OncePerRequestFilter that delays each matched request by a random
      amount between a configurable minimum and maximum, for a configurable fraction of requests,
      with an optional fixed seed for reproducible delay sequences. Invalid configuration
      (negative delays, max-delay < min-delay, probability outside 0..1) fails fast at startup.
    • LatencyProperties — bound from the grails.testing.latency prefix (enabled, min-delay,
      max-delay, probability, url-patterns, seed) with Spring Duration binding.
    • LatencyAutoConfiguration — conditional on grails.testing.latency.enabled=true, so the
      library is completely inert unless explicitly switched on; registers the filter at highest
      precedence so the delay covers the entire request pipeline.
  • New example app grails-test-examples/latency that enables latency for /slow/* only and
    confirms end-to-end behavior against the running application: matched requests take at least
    the configured minimum, unmatched requests do not.
  • Documentation: a new "Simulating Latency" section in the Functional Testing guide (dependency,
    activation, full property table, YAML example, CI usage pattern, production warning) and a
    "Latency Testing Support" entry in the What's New section.
  • Module registered in settings.gradle and gradle/publish-root-config.gradle; the BOM picks
    it up automatically via the subprojects constraint loop.

Verification performed:

  • ./gradlew :grails-testing-support-latency:build — 10 unit tests passing (delay bounds,
    zero-probability passthrough, configuration validation, conditional auto-configuration)
  • ./gradlew :grails-test-examples-latency:integrationTest — 2 end-to-end tests passing
  • ./gradlew :grails-testing-support-latency:codeStyle — clean
  • ./gradlew :grails-doc:publishGuide -x aggregateGroovydoc — docs build clean, new sections render

Contributor Checklist

Issue and Scope

  • This PR is linked to an existing issue — no issue exists yet; background is provided in
    the Description above. Happy to open a ticket for the release changelog if preferred.
  • This PR addresses the complete scope of the change: library, tests, example app, and
    documentation are all included.
  • This PR contains a single, focused change.
  • This PR targets the correct branch: it is a new feature (new module, no changes to any
    existing API) targeting 8.0.x.

Code Quality

  • I have added or updated tests: unit tests for the filter and auto-configuration, plus a
    dedicated example app with integration tests confirming runtime behavior.
  • I have verified that all existing tests pass by running ./gradlew build --rerun-tasks.
    (Targeted builds above are green; full rerun not yet executed.)
  • My code follows the project's code style guidelines (codeStyle passes on the new module).
  • This PR does not include mass reformatting, style-only changes, or refactoring.
  • Generative AI tooling was used (Claude Code with Claude Fable 5); all output was reviewed,
    and verified against the project's quality standards via the test and style checks above.

Licensing and Attribution

  • All contributed code is provided under the Apache License 2.0, and every new source file
    (Groovy, Gradle, YAML, XML, AsciiDoc) includes the Apache license header.
  • I have the necessary rights to submit this contribution.
  • Generative AI use is disclosed per the ASF generative tooling policy: this contribution was
    prepared with assistance from Claude Code (Anthropic), with human review of all changes.

Documentation

  • User-facing documentation added: "Simulating Latency" section in the Functional Testing guide.
  • What's New section updated with a "Latency Testing Support" entry.
  • No breaking changes or upgrade actions — the module is new, opt-in, and inert by default, so
    no Upgrade Notes changes are needed.
  • The PR description explains what was changed and why.

@jdaugherty

Copy link
Copy Markdown
Contributor Author

@jamesfredley this gives us a way to reproduce the test run failures locally. The idea is we can add these to our test apps to introduce latency, then have AI iterate to fix the flakiness so this isn't a problem going forward.

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.3450%. Comparing base (23045cd) to head (8f75d23).

Files with missing lines Patch % Lines
...apache/grails/testing/latency/LatencyFilter.groovy 92.0000% 0 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #15937        +/-   ##
==================================================
+ Coverage     49.3287%   49.3450%   +0.0163%     
- Complexity      16768      16791        +23     
==================================================
  Files            1985       1987         +2     
  Lines           93327      93357        +30     
  Branches        16336      16343         +7     
==================================================
+ Hits            46037      46067        +30     
+ Misses          40165      40164         -1     
- Partials         7125       7126         +1     
Files with missing lines Coverage Δ
...ls/testing/latency/LatencyAutoConfiguration.groovy 100.0000% <100.0000%> (ø)
...apache/grails/testing/latency/LatencyFilter.groovy 92.0000% <92.0000%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@testlens-app

testlens-app Bot commented Jul 8, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 8f75d23
▶️ Tests: 8333 executed
⚪️ Checks: 61/61 completed


Learn more about TestLens at testlens.app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant