Skip to content

Add artefact name contract characterization spec - #15998

Open
jamesfredley wants to merge 3 commits into
8.0.xfrom
test/artefact-name-precomputation
Open

Add artefact name contract characterization spec#15998
jamesfredley wants to merge 3 commits into
8.0.xfrom
test/artefact-name-precomputation

Conversation

@jamesfredley

@jamesfredley jamesfredley commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a test-only characterization spec locking in public GrailsClass artefact naming behavior
  • cover controllers, services, domains, and url-mappings, including acronym-heavy names, repeated accessor reads, and repeated wrapper construction
  • assert the framework's actual observed names; no production changes and no timing thresholds

Verification

  • :grails-core:test --tests ArtefactNamingContractSpec
  • :grails-core:test
  • git diff --check

This is an AI-generated starting point that pins the naming contract ahead of any GrailsNameUtils precomputation work.

Assisted-by: opencode:gpt-5.6-sol

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Spock characterization spec to lock in the current GrailsClass artefact naming outputs (controllers/services/domains/urlMappings) and stability across repeated accessor reads and wrapper re-construction, to protect future GrailsNameUtils precomputation work.

Changes:

  • Introduce ArtefactNamePrecomputationSpec to assert deterministic naming fields (name, shortName, fullName, packageName, propertyName, logicalPropertyName, naturalName) for representative artefact classes.
  • Add repeated-read and repeated-wrapper-construction checks to ensure naming accessors remain stable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to +59
packageName: BASE_PACKAGE,
propertyName: 'HTMLController',
logicalPropertyName: 'HTML',
naturalName: 'HTMLC ontroller'
],
Comment on lines +79 to +83
packageName: BASE_PACKAGE,
propertyName: 'JSONAPIService',
logicalPropertyName: 'JSONAPI',
naturalName: 'JSONAPIS ervice'
],
Comment on lines +91 to +95
packageName: BASE_PACKAGE,
propertyName: 'URLDomain',
logicalPropertyName: 'URLDomain',
naturalName: 'URLD omain'
],
Comment on lines +136 to +140
packageName: BASE_PACKAGE,
propertyName: 'HTMLController',
logicalPropertyName: 'HTML',
naturalName: 'HTMLC ontroller'
],
Comment on lines +148 to +152
packageName: BASE_PACKAGE,
propertyName: 'JSONAPIService',
logicalPropertyName: 'JSONAPI',
naturalName: 'JSONAPIS ervice'
]
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.3618%. Comparing base (e88612c) to head (603f812).
⚠️ Report is 6 commits behind head on 8.0.x.

Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #15998        +/-   ##
==================================================
+ Coverage     52.3514%   52.3618%   +0.0104%     
- Complexity      18299      18305         +6     
==================================================
  Files            2036       2036                
  Lines           96347      96347                
  Branches        16829      16829                
==================================================
+ Hits            50439      50449        +10     
+ Misses          38485      38475        -10     
  Partials         7423       7423                

see 7 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.

]
}

private GrailsClass grailsClassFor(String artifactType, Class<?> wrapperClass) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Constructing DefaultGrailsControllerClass/DefaultGrailsServiceClass/etc. directly bypasses artefact detection entirely — these constructors accept any class (new DefaultGrailsControllerClass(URLDomain) would work just as well). So this spec pins the naming metadata contract, but not the detection contract (ArtefactHandler.isArtefact), which is the part a precomputation refactor is most likely to disturb.

Consider adding cases that exercise the handlers, e.g.:

  • an abstract FooController is rejected (ControllerArtefactHandler passes allowAbstract=false)
  • URLDomain without @Entity/@Artefact is rejected by DomainClassArtefactHandler.isArtefactClass (domain detection is annotation/location-based; the name plays no role)
  • a suffix match like HTMLController is accepted by ControllerArtefactHandler.isArtefactClass

/**
* Tests for deterministic GrailsClass naming metadata.
*/
class ArtefactNamePrecomputationSpec extends Specification {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"Precomputation" in the spec name is aspirational — nothing here asserts precomputation; the repeated-read/repeated-construction tests pin stability only. That's a fine pre-refactor baseline, but consider a name that says what it locks in, e.g. ArtefactNamingContractSpec, so it doesn't read as if precomputed behavior already exists.

packageName: BASE_PACKAGE,
propertyName: 'HTMLController',
logicalPropertyName: 'HTML',
naturalName: 'HTMLC ontroller'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For the record: expectations like 'HTMLC ontroller' / 'JSONAPIS ervice' / 'URLD omain' are correct characterizations — GrailsNameUtils.getNaturalName genuinely splits acronym-prefixed names after the last uppercase letter. Worth a brief code comment noting these pin known-quirky behavior intentionally, so a future reader doesn't "fix" the expectations (or the algorithm) without realizing this spec exists to catch exactly that change.

@jamesfredley jamesfredley moved this to Todo in Apache Grails Jul 24, 2026
…n spec

Copilot's 5 inline comments claiming the acronym naturalName expectations
were wrong (e.g. 'HTMLC ontroller') are false positives - verified by
running the spec: GrailsNameUtils.getNaturalName genuinely produces those
values, and jdaugherty's review already confirmed this. No change needed
there.

jdaugherty's own feedback was substantive and is addressed here:

- Rename ArtefactNamePrecomputationSpec -> ArtefactNamingContractSpec:
  "precomputed" was aspirational, since nothing in the spec exercises
  actual precomputation, only naming stability.
- Add a comment above the acronym-heavy naturalName assertions explaining
  the quirky-but-intentional GrailsNameUtils splitting behavior they pin,
  so a future reader doesn't "fix" the expectations or the algorithm
  without realizing this spec exists to catch exactly that change.
- Add three cases exercising the artefact detection contract
  (ArtefactHandler#isArtefactClass), which the original spec bypassed
  entirely by constructing GrailsClass wrappers directly: an abstract
  controller is rejected (ControllerArtefactHandler's allowAbstract is
  false), a suffix-matching concrete controller is accepted, and a
  domain-named class with no @Entity/@ArteFact annotation is rejected by
  DomainClassArtefactHandler - this is the part a naming precomputation
  refactor is most likely to disturb, and the prior spec gave it no
  coverage at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@borinquenkid borinquenkid added this to the grails:8.0.0-RC1 milestone Jul 27, 2026
@testlens-app

testlens-app Bot commented Aug 6, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 603f812
▶️ Tests: 47855 executed
⚪️ Checks: 60/60 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

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants