Skip to content

Expand Fluent Syntax Elements Test Coverage - #486

Merged
alexanderlinne merged 11 commits into
mainfrom
expand-fluent-syntax-elements-test-coverage
Aug 28, 2026
Merged

alexanderlinne merged 11 commits into
mainfrom
expand-fluent-syntax-elements-test-coverage

Conversation

@alexanderlinne

Copy link
Copy Markdown
Collaborator

No description provided.

Return type was the only multi-argument method member element without an
"Empty arguments" section, so the count-zero ternary in all four
IEnumerable<Type> overloads was never taken and the IObjectProvider overloads
never saw an empty provider.

Both directions behave as expected and are now pinned: the positive form yields
"have return type of no types (impossible)" and violates for every input, the
negation yields "do not have return type of no types (always true)" and holds
vacuously. The IObjectProvider overload routes through
ObjectProvider.FormatDescription instead and reads "Types that are any of no
objects (always empty)"; neither wording leaves a dangling phrase.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
TypeArchitecture loads exactly one assembly, so the "Multiple assemblies" blocks
in ResideInAssemblyTest and NotResideInAssemblyTest passed the same matching
assembly twice. The first operand of the condition was therefore always
decisive, the moreAssemblies lambda never ran, and the whole moreAssemblies slot
of ResideInAssembly and NotResideInAssembly went untested.

A second loaded assembly is required to fix this: GetAssemblyOfAssembly throws
for an assembly that is not part of the architecture, so an unloaded assembly
cannot be used as the non-matching argument. Add TypeAndClassArchitecture and a
matching helper, and move the multiple-assembly cases into dedicated tests where
the first argument is a loaded assembly the subject does not reside in.

Both overload families stay covered, since only the System.Reflection.Assembly
one has the short-circuiting lambda.

Also pin AssemblyDoesNotExistInArchitecture, which no test asserted.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
BeImmutable and NotBeImmutable both exclude static members, but the condition
side only ever ran over MutableClass, OtherMutableClass and ImmutableClass, none
of which has one, so the exclusion in NotBeImmutable was never taken. The
predicate side runs over every class in the architecture and did take it, which
is why the identical expression in ClassPredicatesDefinition was already fully
covered.

Add a class whose instance members are all read-only but which has one mutable
static field, and assert it in both directions. Also mirror the existing
"only static members" section into NotBeImmutableTest, which had no counterpart.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
…uments

The singular/plural twin in the failure message needs more than one forbidden
argument on the *same* attribute instance. The existing "Multiple arguments"
block passes two values of which only one matches, so failedArguments.Count was
always 1 and only the singular spelling was ever produced by this method. Both
spellings did appear in the snapshot, but the plural ones came from sibling
methods.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
…tity

Architecture.GetOrCreateObjects keys the rule evaluation cache on the object
provider's hash code and runtime type, so a wrong Equals or GetHashCode hands
one rule another rule's analyzed objects. Nothing tested either: Equals(null)
and Equals against a foreign type were never called, and the syntax element
tests all build their architectures WithoutRuleEvaluationCache, so they never
reach the cached path at all.

The new test builds an architecture with the cache enabled and asserts that two
providers with different predicates do not hand out each other's objects, while
an equal but distinct provider still resolves to the same set.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
FieldMembers() was the only fluent entry point without a single test, so all
of its syntax element classes were unreachable from the test suite.

There are no field specific syntax elements, so the new file is a routing
smoke test rather than a per-element suite: it proves that the chain reaches
the shared member and object syntax, and a second test drives both
conjunctions, which are the only classes there with behaviour of their own.

The file joins the two other wide syntax element test files in
.csharpierignore, because a // csharpier-ignore comment on the class is not
honoured under a file-scoped namespace.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
13 "Multiple inputs" blocks passed a single input in their no-violations
case, so they never exercised the multi-input path. Add an Other* class
per uncovered getter/setter visibility, get-only, write-only and init-only
case, and use it as the second input.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
A bare GivenObjects (not a "...That()" conjunction) passed as an object
provider routes through GivenObjects.FormatDescription instead of a
"...WithDescription" conjunction's custom description. And a provider
backed by a CombinedArchRuleCreator can't produce a filtered object list,
so GetObjects() turns the internal exception into the user-facing
CannotGetObjectsOfCombinedArchRuleException. Both paths were reachable
through the public fluent API but untested.

Split into two tests, BareObjectProviderDescriptionTest and
GetObjectsOnCombinedArchRuleTest, since they cover unrelated code paths
that only happened to share a name.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
Extend DescriptionTests with a predicate-side and condition-side custom
description and Because reason per rule type. These "...ConjunctionWithDescription"
constructors are only ever reached reflectively via ConjunctionFactory.Create, so
a wrong constructor signature fails at runtime, not compile time - exactly what
these tests would catch.

While covering it, found that GivenInterfacesConjunction passed itself instead
of GivenInterfacesConjunctionWithDescription as the Because()/As() return type,
unlike every other rule type. That left GivenInterfacesConjunctionWithDescription
completely unreachable. Fix it to match its siblings.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
BeDeclaredIn()/BeCalledBy()/BeAssignableTo() and their siblings' parameterless
overloads (sugar for an empty ObjectProvider) were never called by any test;
only the equivalent new List<...>() forms were. Add the parameterless form
next to each existing "Empty arguments" block.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
AddObjectPredicate.HaveAnyAttributesWithArguments(object, params
object[]) was a leftover from the "Refactor attribute with arguments
fluent syntax methods" cleanup (2edbb5a), which removed the equivalent
sugar from HaveAttributeWithArguments and the DoNot* variants but
missed this one. It was never part of IAddObjectPredicate, and the
condition side (AddObjectCondition) never had a matching overload at
all, so it was a one-off asymmetry rather than a designed API surface.

Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.42%. Comparing base (7d902ca) to head (e122e19).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #486      +/-   ##
==========================================
+ Coverage   82.50%   83.42%   +0.92%     
==========================================
  Files         259      259              
  Lines       12395    12394       -1     
  Branches     1206     1206              
==========================================
+ Hits        10226    10340     +114     
+ Misses       1798     1696     -102     
+ Partials      371      358      -13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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