fix: respect TUnitImplicitUsings set in Directory.Build.props#5225
fix: respect TUnitImplicitUsings set in Directory.Build.props#5225
Conversation
Add PowerShell scripts for measuring and comparing TUnit startup performance, useful for tracking JIT overhead improvements: - measure-startup.ps1: wall-clock timing with statistical analysis - count-generated-methods.ps1: static analysis of generated method counts - compare-branches.ps1: side-by-side branch comparison - measure-jit.ps1: JIT trace collection and generated method analysis
Add conditions to avoid overwriting user-set property values, matching the pattern already used in TUnit.Mocks.props.
There was a problem hiding this comment.
Code Review
This is a clean, minimal, and correct fix for issue #5208.
What the fix does
MSBuild evaluates NuGet package .props files after Directory.Build.props, so properties set unconditionally in TUnit.props/TUnit.Assertions.props were silently overwriting any user-defined values. Adding the Condition="'$(Property)' == ''" guard (the MSBuild idiom for "only set if not already defined") correctly implements opt-out behavior.
Changes look correct
TUnit/TUnit.props — Both properties now use the inline condition form on the property element itself:
<TUnitImplicitUsings Condition="'$(TUnitImplicitUsings)' == ''">true</TUnitImplicitUsings>This is idiomatic MSBuild and matches the pattern in TUnit.Mocks.props.
TUnit.Assertions/TUnit.Assertions.props — The condition is placed on the <PropertyGroup> rather than the individual property, which is equivalent since the group only contains one property. Both approaches are correct MSBuild.
Consistency
The fix aligns with the existing pattern in TUnit.Mocks.props:
<TUnitMockImplicitUsings Condition="'$(TUnitMockImplicitUsings)' == ''">enable</TUnitMockImplicitUsings>Good to have all three packages now follow the same convention.
One observation (not a blocker)
In TUnit.Assertions.props, the outer XunitPackageReferenceFound condition is evaluated at MSBuild static evaluation time (before any targets run), at which point it always equals false (its initial value from the same props file). The actual xunit detection happens in a <Target> which runs later. This means the xunit guard on the PropertyGroup may not behave as intended in all scenarios — but this is a pre-existing issue unrelated to this PR and warrants a separate investigation.
Summary
The fix is correct, minimal, and consistent with existing patterns. Approving.
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.21.6 to 1.21.20. <details> <summary>Release notes</summary> _Sourced from [TUnit's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.21.20 <!-- Release notes generated using configuration in .github/release.yml at v1.21.20 --> ## What's Changed ### Other Changes * fix: respect TUnitImplicitUsings set in Directory.Build.props by @thomhurst in thomhurst/TUnit#5225 * feat: covariant assertions for interfaces and non-sealed classes by @thomhurst in thomhurst/TUnit#5226 * feat: support string-to-parseable type conversions in [Arguments] by @thomhurst in thomhurst/TUnit#5227 * feat: add string length range assertions by @thomhurst in thomhurst/TUnit#4935 * Fix BeforeEvery/AfterEvery hooks for Class and Assembly not being executed by @Copilot in thomhurst/TUnit#5239 ### Dependencies * chore(deps): update tunit to 1.21.6 by @thomhurst in thomhurst/TUnit#5228 * chore(deps): update dependency gitversion.msbuild to 6.7.0 by @thomhurst in thomhurst/TUnit#5229 * chore(deps): update dependency gitversion.tool to v6.7.0 by @thomhurst in thomhurst/TUnit#5230 * chore(deps): update aspire to 13.2.0 - autoclosed by @thomhurst in thomhurst/TUnit#5232 * chore(deps): update dependency typescript to v6 by @thomhurst in thomhurst/TUnit#5233 * chore(deps): update dependency polyfill to 9.23.0 by @thomhurst in thomhurst/TUnit#5235 * chore(deps): update dependency polyfill to 9.23.0 by @thomhurst in thomhurst/TUnit#5236 **Full Changelog**: thomhurst/TUnit@v1.21.6...v1.21.20 Commits viewable in [compare view](thomhurst/TUnit@v1.21.6...v1.21.20). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Summary
Fixes #5208
TUnit.propsandTUnit.Assertions.propsunconditionally setTUnitImplicitUsingsandTUnitAssertionsImplicitUsingstotrue, overwriting any value set earlier byDirectory.Build.props(which is imported before NuGet package.propsfiles in MSBuild evaluation order)Condition="'$(Property)' == ''"guards so these properties only default totruewhen not already defined by the userTUnit.Mocks.propsTest plan
TUnitImplicitUsings=falseandTUnitAssertionsImplicitUsings=falsein aDirectory.Build.propsalongside an NUnit+TUnit project and verify it builds without ambiguous reference errors