perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans#6098
Conversation
Replace GetCustomAttributes() + OfType/Any/FirstOrDefault LINQ chains with a single-pass foreach that returns the first IDataSourceAttribute. - ReflectionInstanceFactory: drops the OfType iterator + array allocation per property; common case (no data source) now allocates nothing extra. - StaticPropertyReflectionInitializer: collapses the double attribute-array materialisation (filter + fetch) into one scan per property. Skips ConstructorHelper.cs (#6056, separate open PR).
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Code Review
The change is correct and the optimization rationale is sound. The two touched paths are legitimately hot: they run per-property per-type during reflection-mode discovery/construction, and the old code was doing redundant allocation work (an object[] from GetCustomAttributes(), LINQ iterators, and for StaticPropertyReflectionInitializer a full second scan). The new single-pass helpers eliminate all of that. A few observations follow.
Correctness
Behavioral equivalence is preserved. Both old and new code call the parameterless property.GetCustomAttributes(), which defaults to inherit: true. The is IDataSourceAttribute pattern is the correct way to check against an interface type (the typed-overload GetCustomAttribute<T>() requires T : Attribute, and the GetCustomAttributes(typeof(IDataSourceAttribute), true) overload is the MemberInfo/ICustomAttributeProvider path — not used here, so no inconsistency is introduced). "First match" semantics are the same as FirstOrDefault / [0] on the old arrays.
type parameter removal in InitializeStaticProperty is safe. Inspecting the current file confirms that type was not used inside the method body itself; the containing type appears only in the error message at the call site (line 87: type.FullName), which is correctly kept in the outer foreach scope.
NoDataSource : IDataSourceAttribute (not an Attribute) is unaffected — it was never returned by GetCustomAttributes() before and still won't be.
Minor Design Note: Duplicate Helper
GetFirstDataSourceAttribute(PropertyInfo property) is now copy-pasted identically into two classes:
TUnit.Core.StaticPropertyReflectionInitializer(public, in TUnit.Core)TUnit.Engine.Discovery.ReflectionInstanceFactory(internal, in TUnit.Engine)
Since TUnit.Engine already references TUnit.Core, the method could live once in TUnit.Core.Helpers.DataSourceHelpers (which already contains related helpers like ResolveDataSourceForPropertyAsync). This isn't a blocker — the duplication is small and both copies are private static — but if a third call-site emerges (e.g. when #6056 lands for ConstructorHelper) it would be worth consolidating at that point. Flagging it now so the decision is explicit.
Out-of-Scope Observation (not a blocker)
DataSourceHelpers.cs line 529 uses propertyInfo.GetCustomAttributes(typeof(IDataSourceAttribute), true) then casts the result directly. This is the MemberInfo.ICustomAttributeProvider path and does handle interface types correctly on CoreCLR, but it returns object[] and does an unchecked cast (IDataSourceAttribute)dataSourceAttributes[0]. That code is untouched by this PR and predates it — just noting it so it isn't confused with the approach used here.
Summary
The optimization is well-targeted, correctly scoped to reflection-only paths, and the PR description accurately describes all the trade-offs. The only thing to consider for a future cleanup pass is consolidating the duplicated GetFirstDataSourceAttribute helper once ConstructorHelper (PR #6056) is addressed. Good change overall.
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.45.29 to 1.48.6. <details> <summary>Release notes</summary> _Sourced from [TUnit's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.48.6 <!-- Release notes generated using configuration in .github/release.yml at v1.48.6 --> ## What's Changed ### Other Changes * fix(sourcegen): fully-qualify Linq calls in params array binding (#6140) by @thomhurst in thomhurst/TUnit#6141 ### Dependencies * chore(deps): update tunit to 1.48.0 by @thomhurst in thomhurst/TUnit#6135 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6137 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6138 * chore(deps): update verify to 31.19.0 by @thomhurst in thomhurst/TUnit#6139 **Full Changelog**: thomhurst/TUnit@v1.48.0...v1.48.6 ## 1.48.0 <!-- Release notes generated using configuration in .github/release.yml at v1.48.0 --> ## What's Changed ### Other Changes * feat(html-report): baked-in C# syntax highlighting on Source tab by @slang25 in thomhurst/TUnit#6132 * feat(analyzers): suppress VSTHRD200 on test and hook methods by @thomhurst in thomhurst/TUnit#6123 * fix(source-gen): correct source location for cross-project inherited tests by @slang25 in thomhurst/TUnit#6133 * feat(assertions): add WasCalled to tunit mocks assertions by @robertcoltheart in thomhurst/TUnit#6126 * feat(arguments): bind array values to a single array test parameter by @thomhurst in thomhurst/TUnit#6122 * fix: populate retry/flaky attempt history in HTML report (#6119) by @thomhurst in thomhurst/TUnit#6124 ### Dependencies * chore(deps): update tunit to 1.47.0 by @thomhurst in thomhurst/TUnit#6115 * chore(deps): update dependency microsoft.visualstudio.threading.analyzers to 17.14.15 by @thomhurst in thomhurst/TUnit#6134 **Full Changelog**: thomhurst/TUnit@v1.47.0...v1.48.0 ## 1.47.0 <!-- Release notes generated using configuration in .github/release.yml at v1.47.0 --> ## What's Changed ### Other Changes * perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery hooks by @thomhurst in thomhurst/TUnit#6062 * perf(engine): hoist GetParameters and drop LINQ in reflection discovery by @thomhurst in thomhurst/TUnit#6063 * perf(engine): cache treenode filter path on TestMetadata by @thomhurst in thomhurst/TUnit#6064 * perf: use is T pattern in ReflectionExtensions.HasAttribute fallback (#6060) by @thomhurst in thomhurst/TUnit#6066 * perf: replace OrderBy().ToArray() with Array.Sort in ConstraintKeyScheduler by @thomhurst in thomhurst/TUnit#6067 * perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by @thomhurst in thomhurst/TUnit#6069 * perf: collapse OfType chains in JUnitXmlWriter (#6052) by @thomhurst in thomhurst/TUnit#6070 * perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) by @thomhurst in thomhurst/TUnit#6071 * perf: avoid closure allocation in BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#6040) by @thomhurst in thomhurst/TUnit#6073 * perf: use TryAdd in TestDependencyResolver dependency dedupe by @thomhurst in thomhurst/TUnit#6068 * perf: replace LINQ Any with foreach in TestGenericTypeResolver (#6044) by @thomhurst in thomhurst/TUnit#6072 * perf: avoid Cast<object>().FirstOrDefault() iterator alloc in CastHelper (#6029) by @thomhurst in thomhurst/TUnit#6074 * perf(engine): avoid string round-trip when building nested type names (#6049) by @thomhurst in thomhurst/TUnit#6075 * perf(engine): replace Select+ToArray with manual Type[] build (#6043) by @thomhurst in thomhurst/TUnit#6076 * perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in ClassConstructorHelper by @thomhurst in thomhurst/TUnit#6078 * perf(engine): avoid FirstOrDefault iterator alloc in TestGenericTypeResolver by @thomhurst in thomhurst/TUnit#6079 * perf(engine): use SearchValues<char> for reporter filename sanitization by @thomhurst in thomhurst/TUnit#6090 * perf: dedupe TestDataFormatter.FormatArguments with pooled StringBuilder by @thomhurst in thomhurst/TUnit#6088 * perf(engine): use MemoryExtensions.Split for path parsing in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6085 * perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for dictionary index builds by @thomhurst in thomhurst/TUnit#6086 * perf(engine): replace LINQ Where closure with inline filter in MetadataDependencyExpander BFS by @thomhurst in thomhurst/TUnit#6084 * perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments by @thomhurst in thomhurst/TUnit#6082 * Preserve specialized chaining after null assertions by @thomhurst in thomhurst/TUnit#6008 * perf: use EnumerateLines for line splitting in HtmlReportGenerator by @thomhurst in thomhurst/TUnit#6089 * perf: collapse Replace chain in TestNameFormatter.BuildTestId by @thomhurst in thomhurst/TUnit#6083 * perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span mapping by @thomhurst in thomhurst/TUnit#6093 * perf(assertions): avoid eager interpolated-string alloc in assertion source ctors by @thomhurst in thomhurst/TUnit#6091 * perf: optimize TestNameFormatter argument and bool formatting by @thomhurst in thomhurst/TUnit#6095 * perf: use FrozenSet/FrozenDictionary for read-only static lookups by @thomhurst in thomhurst/TUnit#6099 * perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans by @thomhurst in thomhurst/TUnit#6098 * perf(engine): replace magic-string RequiredAttribute match with type check in ConstructorHelper by @thomhurst in thomhurst/TUnit#6087 * perf(core): replace Select+Func factory chain in DataSourceHelpers by @thomhurst in thomhurst/TUnit#6081 * perf: replace LINQ dependency extraction with manual loop by @thomhurst in thomhurst/TUnit#6096 * perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments by @thomhurst in thomhurst/TUnit#6080 * perf: use [GeneratedRegex] in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6094 * perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by @thomhurst in thomhurst/TUnit#6097 * fix: remove GitVersion MSBuild task, pin local builds to 99.99.99 (#6077) by @thomhurst in thomhurst/TUnit#6101 * HTML Report: source link + code snippet on Source tab (#5993) by @thomhurst in thomhurst/TUnit#6100 * perf(sourcegen): Single-pass attribute classification by @thomhurst in thomhurst/TUnit#6111 * perf(core): eliminate per-test allocations in TestDetails/HookMethod by @thomhurst in thomhurst/TUnit#6109 * perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static SearchValues by @thomhurst in thomhurst/TUnit#6108 * perf(core): de-LINQ data-source expansion by @thomhurst in thomhurst/TUnit#6110 * perf: avoid LINQ chains in TestDependency equality and MethodDataSourceAttribute method matching by @thomhurst in thomhurst/TUnit#6092 * perf(engine): reduce allocations in reflection-mode discovery/execution by @thomhurst in thomhurst/TUnit#6113 * perf(assertions): allocation-free passing path (TUnit.Assertions) by @thomhurst in thomhurst/TUnit#6112 ### Dependencies ... (truncated) ## 1.46.0 <!-- Release notes generated using configuration in .github/release.yml at v1.46.0 --> ## What's Changed ### Other Changes * docs: add Rider VSTest conflict troubleshooting by @smolchanovsky in thomhurst/TUnit#5989 * Populate generated test metadata with full source spans by @Copilot in thomhurst/TUnit#5991 * Add devcontainer configuration by @Copilot in thomhurst/TUnit#5995 * fix: treenode filter pre-filter rejects parenthesised segments (#6026) by @thomhurst in thomhurst/TUnit#6027 * fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by @thomhurst in thomhurst/TUnit#6025 ### Dependencies * chore(deps): update dependency stackexchange.redis to 2.13.10 by @thomhurst in thomhurst/TUnit#5985 * chore(deps): update tunit to 1.45.29 by @thomhurst in thomhurst/TUnit#5986 * chore(deps): update dependency mockolate to 3.2.1 by @thomhurst in thomhurst/TUnit#5987 * chore(deps): update dependency microsoft.playwright to 1.60.0 by @thomhurst in thomhurst/TUnit#5988 * chore(deps): update dependency messagepack to 3.1.6 by @thomhurst in thomhurst/TUnit#5992 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5998 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5997 * chore(deps): update verify to 31.17.0 by @thomhurst in thomhurst/TUnit#6000 * chore(deps): update verify to 31.18.0 by @thomhurst in thomhurst/TUnit#6013 * chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by @thomhurst in thomhurst/TUnit#6016 * chore(deps): update dependency dompurify to v3.4.6 by @thomhurst in thomhurst/TUnit#6015 * chore(deps): update dependency dompurify to v3.4.7 by @thomhurst in thomhurst/TUnit#6019 * chore(deps): update dependency npgsql to 10.0.3 by @thomhurst in thomhurst/TUnit#6020 * chore(deps): update dependency stackexchange.redis to 2.13.17 by @thomhurst in thomhurst/TUnit#6021 * chore(deps): update dependency npgsql.entityframeworkcore.postgresql to 10.0.2 by @thomhurst in thomhurst/TUnit#6022 ## New Contributors * @smolchanovsky made their first contribution in thomhurst/TUnit#5989 **Full Changelog**: thomhurst/TUnit@v1.45.29...v1.46.0 Commits viewable in [compare view](thomhurst/TUnit@v1.45.29...v1.48.6). </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>
Updated [Microsoft.Testing.Extensions.CodeCoverage](https://github.com/microsoft/codecoverage) from 18.6.2 to 18.7.0. <details> <summary>Release notes</summary> _Sourced from [Microsoft.Testing.Extensions.CodeCoverage's releases](https://github.com/microsoft/codecoverage/releases)._ No release notes found for this version range. Commits viewable in [compare view](https://github.com/microsoft/codecoverage/commits). </details> Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.44.39 to 1.48.6. <details> <summary>Release notes</summary> _Sourced from [TUnit's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.48.6 <!-- Release notes generated using configuration in .github/release.yml at v1.48.6 --> ## What's Changed ### Other Changes * fix(sourcegen): fully-qualify Linq calls in params array binding (#6140) by @thomhurst in thomhurst/TUnit#6141 ### Dependencies * chore(deps): update tunit to 1.48.0 by @thomhurst in thomhurst/TUnit#6135 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6137 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6138 * chore(deps): update verify to 31.19.0 by @thomhurst in thomhurst/TUnit#6139 **Full Changelog**: thomhurst/TUnit@v1.48.0...v1.48.6 ## 1.48.0 <!-- Release notes generated using configuration in .github/release.yml at v1.48.0 --> ## What's Changed ### Other Changes * feat(html-report): baked-in C# syntax highlighting on Source tab by @slang25 in thomhurst/TUnit#6132 * feat(analyzers): suppress VSTHRD200 on test and hook methods by @thomhurst in thomhurst/TUnit#6123 * fix(source-gen): correct source location for cross-project inherited tests by @slang25 in thomhurst/TUnit#6133 * feat(assertions): add WasCalled to tunit mocks assertions by @robertcoltheart in thomhurst/TUnit#6126 * feat(arguments): bind array values to a single array test parameter by @thomhurst in thomhurst/TUnit#6122 * fix: populate retry/flaky attempt history in HTML report (#6119) by @thomhurst in thomhurst/TUnit#6124 ### Dependencies * chore(deps): update tunit to 1.47.0 by @thomhurst in thomhurst/TUnit#6115 * chore(deps): update dependency microsoft.visualstudio.threading.analyzers to 17.14.15 by @thomhurst in thomhurst/TUnit#6134 **Full Changelog**: thomhurst/TUnit@v1.47.0...v1.48.0 ## 1.47.0 <!-- Release notes generated using configuration in .github/release.yml at v1.47.0 --> ## What's Changed ### Other Changes * perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery hooks by @thomhurst in thomhurst/TUnit#6062 * perf(engine): hoist GetParameters and drop LINQ in reflection discovery by @thomhurst in thomhurst/TUnit#6063 * perf(engine): cache treenode filter path on TestMetadata by @thomhurst in thomhurst/TUnit#6064 * perf: use is T pattern in ReflectionExtensions.HasAttribute fallback (#6060) by @thomhurst in thomhurst/TUnit#6066 * perf: replace OrderBy().ToArray() with Array.Sort in ConstraintKeyScheduler by @thomhurst in thomhurst/TUnit#6067 * perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by @thomhurst in thomhurst/TUnit#6069 * perf: collapse OfType chains in JUnitXmlWriter (#6052) by @thomhurst in thomhurst/TUnit#6070 * perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) by @thomhurst in thomhurst/TUnit#6071 * perf: avoid closure allocation in BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#6040) by @thomhurst in thomhurst/TUnit#6073 * perf: use TryAdd in TestDependencyResolver dependency dedupe by @thomhurst in thomhurst/TUnit#6068 * perf: replace LINQ Any with foreach in TestGenericTypeResolver (#6044) by @thomhurst in thomhurst/TUnit#6072 * perf: avoid Cast<object>().FirstOrDefault() iterator alloc in CastHelper (#6029) by @thomhurst in thomhurst/TUnit#6074 * perf(engine): avoid string round-trip when building nested type names (#6049) by @thomhurst in thomhurst/TUnit#6075 * perf(engine): replace Select+ToArray with manual Type[] build (#6043) by @thomhurst in thomhurst/TUnit#6076 * perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in ClassConstructorHelper by @thomhurst in thomhurst/TUnit#6078 * perf(engine): avoid FirstOrDefault iterator alloc in TestGenericTypeResolver by @thomhurst in thomhurst/TUnit#6079 * perf(engine): use SearchValues<char> for reporter filename sanitization by @thomhurst in thomhurst/TUnit#6090 * perf: dedupe TestDataFormatter.FormatArguments with pooled StringBuilder by @thomhurst in thomhurst/TUnit#6088 * perf(engine): use MemoryExtensions.Split for path parsing in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6085 * perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for dictionary index builds by @thomhurst in thomhurst/TUnit#6086 * perf(engine): replace LINQ Where closure with inline filter in MetadataDependencyExpander BFS by @thomhurst in thomhurst/TUnit#6084 * perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments by @thomhurst in thomhurst/TUnit#6082 * Preserve specialized chaining after null assertions by @thomhurst in thomhurst/TUnit#6008 * perf: use EnumerateLines for line splitting in HtmlReportGenerator by @thomhurst in thomhurst/TUnit#6089 * perf: collapse Replace chain in TestNameFormatter.BuildTestId by @thomhurst in thomhurst/TUnit#6083 * perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span mapping by @thomhurst in thomhurst/TUnit#6093 * perf(assertions): avoid eager interpolated-string alloc in assertion source ctors by @thomhurst in thomhurst/TUnit#6091 * perf: optimize TestNameFormatter argument and bool formatting by @thomhurst in thomhurst/TUnit#6095 * perf: use FrozenSet/FrozenDictionary for read-only static lookups by @thomhurst in thomhurst/TUnit#6099 * perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans by @thomhurst in thomhurst/TUnit#6098 * perf(engine): replace magic-string RequiredAttribute match with type check in ConstructorHelper by @thomhurst in thomhurst/TUnit#6087 * perf(core): replace Select+Func factory chain in DataSourceHelpers by @thomhurst in thomhurst/TUnit#6081 * perf: replace LINQ dependency extraction with manual loop by @thomhurst in thomhurst/TUnit#6096 * perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments by @thomhurst in thomhurst/TUnit#6080 * perf: use [GeneratedRegex] in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6094 * perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by @thomhurst in thomhurst/TUnit#6097 * fix: remove GitVersion MSBuild task, pin local builds to 99.99.99 (#6077) by @thomhurst in thomhurst/TUnit#6101 * HTML Report: source link + code snippet on Source tab (#5993) by @thomhurst in thomhurst/TUnit#6100 * perf(sourcegen): Single-pass attribute classification by @thomhurst in thomhurst/TUnit#6111 * perf(core): eliminate per-test allocations in TestDetails/HookMethod by @thomhurst in thomhurst/TUnit#6109 * perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static SearchValues by @thomhurst in thomhurst/TUnit#6108 * perf(core): de-LINQ data-source expansion by @thomhurst in thomhurst/TUnit#6110 * perf: avoid LINQ chains in TestDependency equality and MethodDataSourceAttribute method matching by @thomhurst in thomhurst/TUnit#6092 * perf(engine): reduce allocations in reflection-mode discovery/execution by @thomhurst in thomhurst/TUnit#6113 * perf(assertions): allocation-free passing path (TUnit.Assertions) by @thomhurst in thomhurst/TUnit#6112 ### Dependencies ... (truncated) ## 1.46.0 <!-- Release notes generated using configuration in .github/release.yml at v1.46.0 --> ## What's Changed ### Other Changes * docs: add Rider VSTest conflict troubleshooting by @smolchanovsky in thomhurst/TUnit#5989 * Populate generated test metadata with full source spans by @Copilot in thomhurst/TUnit#5991 * Add devcontainer configuration by @Copilot in thomhurst/TUnit#5995 * fix: treenode filter pre-filter rejects parenthesised segments (#6026) by @thomhurst in thomhurst/TUnit#6027 * fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by @thomhurst in thomhurst/TUnit#6025 ### Dependencies * chore(deps): update dependency stackexchange.redis to 2.13.10 by @thomhurst in thomhurst/TUnit#5985 * chore(deps): update tunit to 1.45.29 by @thomhurst in thomhurst/TUnit#5986 * chore(deps): update dependency mockolate to 3.2.1 by @thomhurst in thomhurst/TUnit#5987 * chore(deps): update dependency microsoft.playwright to 1.60.0 by @thomhurst in thomhurst/TUnit#5988 * chore(deps): update dependency messagepack to 3.1.6 by @thomhurst in thomhurst/TUnit#5992 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5998 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5997 * chore(deps): update verify to 31.17.0 by @thomhurst in thomhurst/TUnit#6000 * chore(deps): update verify to 31.18.0 by @thomhurst in thomhurst/TUnit#6013 * chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by @thomhurst in thomhurst/TUnit#6016 * chore(deps): update dependency dompurify to v3.4.6 by @thomhurst in thomhurst/TUnit#6015 * chore(deps): update dependency dompurify to v3.4.7 by @thomhurst in thomhurst/TUnit#6019 * chore(deps): update dependency npgsql to 10.0.3 by @thomhurst in thomhurst/TUnit#6020 * chore(deps): update dependency stackexchange.redis to 2.13.17 by @thomhurst in thomhurst/TUnit#6021 * chore(deps): update dependency npgsql.entityframeworkcore.postgresql to 10.0.2 by @thomhurst in thomhurst/TUnit#6022 ## New Contributors * @smolchanovsky made their first contribution in thomhurst/TUnit#5989 **Full Changelog**: thomhurst/TUnit@v1.45.29...v1.46.0 ## 1.45.29 <!-- Release notes generated using configuration in .github/release.yml at v1.45.29 --> ## What's Changed ### Other Changes * Fix shared fixture lifetime for reused discovery instances by @thomhurst in thomhurst/TUnit#5983 * Preserve override accessibility in generated mocks by @thomhurst in thomhurst/TUnit#5984 ### Dependencies * chore(deps): update tunit to 1.45.22 by @thomhurst in thomhurst/TUnit#5974 * chore(deps): update dependency messagepack to 3.1.5 by @thomhurst in thomhurst/TUnit#5978 * chore(deps): update aspire to 13.3.5 by @thomhurst in thomhurst/TUnit#5980 **Full Changelog**: thomhurst/TUnit@v1.45.22...v1.45.29 ## 1.45.22 <!-- Release notes generated using configuration in .github/release.yml at v1.45.22 --> ## What's Changed ### Other Changes * Remove ".NET" from Aspire references by @antmdvs in thomhurst/TUnit#5968 * Fix chained mock setup behavior by @thomhurst in thomhurst/TUnit#5973 ### Dependencies * chore(deps): update tunit to 1.45.8 by @thomhurst in thomhurst/TUnit#5958 * chore(deps): update dependency nunit to 4.6.1 by @thomhurst in thomhurst/TUnit#5961 * chore(deps): update dependency testcontainers.postgresql to 4.12.0 by @thomhurst in thomhurst/TUnit#5963 * chore(deps): update dependency testcontainers.redis to 4.12.0 by @thomhurst in thomhurst/TUnit#5965 * chore(deps): update dependency testcontainers.kafka to 4.12.0 by @thomhurst in thomhurst/TUnit#5962 * chore(deps): update aspire to 13.3.4 by @thomhurst in thomhurst/TUnit#5966 * chore(deps): bump webpack-dev-server from 5.2.2 to 5.2.4 in /docs by @dependabot[bot] in thomhurst/TUnit#5964 ## New Contributors * @antmdvs made their first contribution in thomhurst/TUnit#5968 **Full Changelog**: thomhurst/TUnit@v1.45.8...v1.45.22 ## 1.45.8 <!-- Release notes generated using configuration in .github/release.yml at v1.45.8 --> ## What's Changed ### Other Changes * fix(aspire): route CreateHttpClient through IHttpClientFactory by @thomhurst in thomhurst/TUnit#5957 ### Dependencies * chore(deps): update tunit to 1.45.0 by @thomhurst in thomhurst/TUnit#5949 * chore(deps): update dependency dompurify to v3.4.5 by @thomhurst in thomhurst/TUnit#5951 * chore(deps): update dependency microsoft.testing.extensions.codecoverage to 18.7.0 by @thomhurst in thomhurst/TUnit#5953 * chore(deps): update dependency coverlet.collector to 10.0.1 by @thomhurst in thomhurst/TUnit#5952 * chore(deps): update dependency polyfill to 10.6.0 by @thomhurst in thomhurst/TUnit#5955 * chore(deps): update dependency polyfill to 10.6.0 by @thomhurst in thomhurst/TUnit#5954 **Full Changelog**: thomhurst/TUnit@v1.45.0...v1.45.8 ## 1.45.0 <!-- Release notes generated using configuration in .github/release.yml at v1.45.0 --> ## What's Changed ### Other Changes * fix(generator): place CallerArgumentExpression before params in [GenerateAssertion] emit by @JohnVerheij in thomhurst/TUnit#5940 * fix(sourcegen): drop covariant TActual when [GenerateAssertion] method has its own type parameters by @JohnVerheij in thomhurst/TUnit#5935 * feat(assertions): add CancellationToken overload to WaitsFor and Eventually by @JohnVerheij in thomhurst/TUnit#5938 * fix(html-report): extract categories using MTP Key=name convention by @thomhurst in thomhurst/TUnit#5946 * feat(html-report): rewrite as split-pane design template by @thomhurst in thomhurst/TUnit#5947 ### Dependencies * chore(deps): update microsoft.testing to 2.2.3 by @thomhurst in thomhurst/TUnit#5927 * chore(deps): update mstest to 4.2.3 by @thomhurst in thomhurst/TUnit#5928 * chore(deps): update tunit to 1.44.39 by @thomhurst in thomhurst/TUnit#5929 * chore(deps): update aspire to 13.3.3 by @thomhurst in thomhurst/TUnit#5933 * chore(deps): update dependency dompurify to v3.4.4 by @thomhurst in thomhurst/TUnit#5944 * chore(deps): update dependency qs to v6.15.2 by @thomhurst in thomhurst/TUnit#5941 **Full Changelog**: thomhurst/TUnit@v1.44.39...v1.45.0 Commits viewable in [compare view](thomhurst/TUnit@v1.44.39...v1.48.6). </details> 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>
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.45.29 to 1.48.6. <details> <summary>Release notes</summary> _Sourced from [TUnit's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.48.6 <!-- Release notes generated using configuration in .github/release.yml at v1.48.6 --> ## What's Changed ### Other Changes * fix(sourcegen): fully-qualify Linq calls in params array binding (#6140) by @thomhurst in thomhurst/TUnit#6141 ### Dependencies * chore(deps): update tunit to 1.48.0 by @thomhurst in thomhurst/TUnit#6135 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6137 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6138 * chore(deps): update verify to 31.19.0 by @thomhurst in thomhurst/TUnit#6139 **Full Changelog**: thomhurst/TUnit@v1.48.0...v1.48.6 ## 1.48.0 <!-- Release notes generated using configuration in .github/release.yml at v1.48.0 --> ## What's Changed ### Other Changes * feat(html-report): baked-in C# syntax highlighting on Source tab by @slang25 in thomhurst/TUnit#6132 * feat(analyzers): suppress VSTHRD200 on test and hook methods by @thomhurst in thomhurst/TUnit#6123 * fix(source-gen): correct source location for cross-project inherited tests by @slang25 in thomhurst/TUnit#6133 * feat(assertions): add WasCalled to tunit mocks assertions by @robertcoltheart in thomhurst/TUnit#6126 * feat(arguments): bind array values to a single array test parameter by @thomhurst in thomhurst/TUnit#6122 * fix: populate retry/flaky attempt history in HTML report (#6119) by @thomhurst in thomhurst/TUnit#6124 ### Dependencies * chore(deps): update tunit to 1.47.0 by @thomhurst in thomhurst/TUnit#6115 * chore(deps): update dependency microsoft.visualstudio.threading.analyzers to 17.14.15 by @thomhurst in thomhurst/TUnit#6134 **Full Changelog**: thomhurst/TUnit@v1.47.0...v1.48.0 ## 1.47.0 <!-- Release notes generated using configuration in .github/release.yml at v1.47.0 --> ## What's Changed ### Other Changes * perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery hooks by @thomhurst in thomhurst/TUnit#6062 * perf(engine): hoist GetParameters and drop LINQ in reflection discovery by @thomhurst in thomhurst/TUnit#6063 * perf(engine): cache treenode filter path on TestMetadata by @thomhurst in thomhurst/TUnit#6064 * perf: use is T pattern in ReflectionExtensions.HasAttribute fallback (#6060) by @thomhurst in thomhurst/TUnit#6066 * perf: replace OrderBy().ToArray() with Array.Sort in ConstraintKeyScheduler by @thomhurst in thomhurst/TUnit#6067 * perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by @thomhurst in thomhurst/TUnit#6069 * perf: collapse OfType chains in JUnitXmlWriter (#6052) by @thomhurst in thomhurst/TUnit#6070 * perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) by @thomhurst in thomhurst/TUnit#6071 * perf: avoid closure allocation in BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#6040) by @thomhurst in thomhurst/TUnit#6073 * perf: use TryAdd in TestDependencyResolver dependency dedupe by @thomhurst in thomhurst/TUnit#6068 * perf: replace LINQ Any with foreach in TestGenericTypeResolver (#6044) by @thomhurst in thomhurst/TUnit#6072 * perf: avoid Cast<object>().FirstOrDefault() iterator alloc in CastHelper (#6029) by @thomhurst in thomhurst/TUnit#6074 * perf(engine): avoid string round-trip when building nested type names (#6049) by @thomhurst in thomhurst/TUnit#6075 * perf(engine): replace Select+ToArray with manual Type[] build (#6043) by @thomhurst in thomhurst/TUnit#6076 * perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in ClassConstructorHelper by @thomhurst in thomhurst/TUnit#6078 * perf(engine): avoid FirstOrDefault iterator alloc in TestGenericTypeResolver by @thomhurst in thomhurst/TUnit#6079 * perf(engine): use SearchValues<char> for reporter filename sanitization by @thomhurst in thomhurst/TUnit#6090 * perf: dedupe TestDataFormatter.FormatArguments with pooled StringBuilder by @thomhurst in thomhurst/TUnit#6088 * perf(engine): use MemoryExtensions.Split for path parsing in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6085 * perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for dictionary index builds by @thomhurst in thomhurst/TUnit#6086 * perf(engine): replace LINQ Where closure with inline filter in MetadataDependencyExpander BFS by @thomhurst in thomhurst/TUnit#6084 * perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments by @thomhurst in thomhurst/TUnit#6082 * Preserve specialized chaining after null assertions by @thomhurst in thomhurst/TUnit#6008 * perf: use EnumerateLines for line splitting in HtmlReportGenerator by @thomhurst in thomhurst/TUnit#6089 * perf: collapse Replace chain in TestNameFormatter.BuildTestId by @thomhurst in thomhurst/TUnit#6083 * perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span mapping by @thomhurst in thomhurst/TUnit#6093 * perf(assertions): avoid eager interpolated-string alloc in assertion source ctors by @thomhurst in thomhurst/TUnit#6091 * perf: optimize TestNameFormatter argument and bool formatting by @thomhurst in thomhurst/TUnit#6095 * perf: use FrozenSet/FrozenDictionary for read-only static lookups by @thomhurst in thomhurst/TUnit#6099 * perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans by @thomhurst in thomhurst/TUnit#6098 * perf(engine): replace magic-string RequiredAttribute match with type check in ConstructorHelper by @thomhurst in thomhurst/TUnit#6087 * perf(core): replace Select+Func factory chain in DataSourceHelpers by @thomhurst in thomhurst/TUnit#6081 * perf: replace LINQ dependency extraction with manual loop by @thomhurst in thomhurst/TUnit#6096 * perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments by @thomhurst in thomhurst/TUnit#6080 * perf: use [GeneratedRegex] in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6094 * perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by @thomhurst in thomhurst/TUnit#6097 * fix: remove GitVersion MSBuild task, pin local builds to 99.99.99 (#6077) by @thomhurst in thomhurst/TUnit#6101 * HTML Report: source link + code snippet on Source tab (#5993) by @thomhurst in thomhurst/TUnit#6100 * perf(sourcegen): Single-pass attribute classification by @thomhurst in thomhurst/TUnit#6111 * perf(core): eliminate per-test allocations in TestDetails/HookMethod by @thomhurst in thomhurst/TUnit#6109 * perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static SearchValues by @thomhurst in thomhurst/TUnit#6108 * perf(core): de-LINQ data-source expansion by @thomhurst in thomhurst/TUnit#6110 * perf: avoid LINQ chains in TestDependency equality and MethodDataSourceAttribute method matching by @thomhurst in thomhurst/TUnit#6092 * perf(engine): reduce allocations in reflection-mode discovery/execution by @thomhurst in thomhurst/TUnit#6113 * perf(assertions): allocation-free passing path (TUnit.Assertions) by @thomhurst in thomhurst/TUnit#6112 ### Dependencies ... (truncated) ## 1.46.0 <!-- Release notes generated using configuration in .github/release.yml at v1.46.0 --> ## What's Changed ### Other Changes * docs: add Rider VSTest conflict troubleshooting by @smolchanovsky in thomhurst/TUnit#5989 * Populate generated test metadata with full source spans by @Copilot in thomhurst/TUnit#5991 * Add devcontainer configuration by @Copilot in thomhurst/TUnit#5995 * fix: treenode filter pre-filter rejects parenthesised segments (#6026) by @thomhurst in thomhurst/TUnit#6027 * fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by @thomhurst in thomhurst/TUnit#6025 ### Dependencies * chore(deps): update dependency stackexchange.redis to 2.13.10 by @thomhurst in thomhurst/TUnit#5985 * chore(deps): update tunit to 1.45.29 by @thomhurst in thomhurst/TUnit#5986 * chore(deps): update dependency mockolate to 3.2.1 by @thomhurst in thomhurst/TUnit#5987 * chore(deps): update dependency microsoft.playwright to 1.60.0 by @thomhurst in thomhurst/TUnit#5988 * chore(deps): update dependency messagepack to 3.1.6 by @thomhurst in thomhurst/TUnit#5992 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5998 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5997 * chore(deps): update verify to 31.17.0 by @thomhurst in thomhurst/TUnit#6000 * chore(deps): update verify to 31.18.0 by @thomhurst in thomhurst/TUnit#6013 * chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by @thomhurst in thomhurst/TUnit#6016 * chore(deps): update dependency dompurify to v3.4.6 by @thomhurst in thomhurst/TUnit#6015 * chore(deps): update dependency dompurify to v3.4.7 by @thomhurst in thomhurst/TUnit#6019 * chore(deps): update dependency npgsql to 10.0.3 by @thomhurst in thomhurst/TUnit#6020 * chore(deps): update dependency stackexchange.redis to 2.13.17 by @thomhurst in thomhurst/TUnit#6021 * chore(deps): update dependency npgsql.entityframeworkcore.postgresql to 10.0.2 by @thomhurst in thomhurst/TUnit#6022 ## New Contributors * @smolchanovsky made their first contribution in thomhurst/TUnit#5989 **Full Changelog**: thomhurst/TUnit@v1.45.29...v1.46.0 Commits viewable in [compare view](thomhurst/TUnit@v1.45.29...v1.48.6). </details> Updated [TUnit.AspNetCore](https://github.com/thomhurst/TUnit) from 1.45.29 to 1.48.6. <details> <summary>Release notes</summary> _Sourced from [TUnit.AspNetCore's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.48.6 <!-- Release notes generated using configuration in .github/release.yml at v1.48.6 --> ## What's Changed ### Other Changes * fix(sourcegen): fully-qualify Linq calls in params array binding (#6140) by @thomhurst in thomhurst/TUnit#6141 ### Dependencies * chore(deps): update tunit to 1.48.0 by @thomhurst in thomhurst/TUnit#6135 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6137 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6138 * chore(deps): update verify to 31.19.0 by @thomhurst in thomhurst/TUnit#6139 **Full Changelog**: thomhurst/TUnit@v1.48.0...v1.48.6 ## 1.48.0 <!-- Release notes generated using configuration in .github/release.yml at v1.48.0 --> ## What's Changed ### Other Changes * feat(html-report): baked-in C# syntax highlighting on Source tab by @slang25 in thomhurst/TUnit#6132 * feat(analyzers): suppress VSTHRD200 on test and hook methods by @thomhurst in thomhurst/TUnit#6123 * fix(source-gen): correct source location for cross-project inherited tests by @slang25 in thomhurst/TUnit#6133 * feat(assertions): add WasCalled to tunit mocks assertions by @robertcoltheart in thomhurst/TUnit#6126 * feat(arguments): bind array values to a single array test parameter by @thomhurst in thomhurst/TUnit#6122 * fix: populate retry/flaky attempt history in HTML report (#6119) by @thomhurst in thomhurst/TUnit#6124 ### Dependencies * chore(deps): update tunit to 1.47.0 by @thomhurst in thomhurst/TUnit#6115 * chore(deps): update dependency microsoft.visualstudio.threading.analyzers to 17.14.15 by @thomhurst in thomhurst/TUnit#6134 **Full Changelog**: thomhurst/TUnit@v1.47.0...v1.48.0 ## 1.47.0 <!-- Release notes generated using configuration in .github/release.yml at v1.47.0 --> ## What's Changed ### Other Changes * perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery hooks by @thomhurst in thomhurst/TUnit#6062 * perf(engine): hoist GetParameters and drop LINQ in reflection discovery by @thomhurst in thomhurst/TUnit#6063 * perf(engine): cache treenode filter path on TestMetadata by @thomhurst in thomhurst/TUnit#6064 * perf: use is T pattern in ReflectionExtensions.HasAttribute fallback (#6060) by @thomhurst in thomhurst/TUnit#6066 * perf: replace OrderBy().ToArray() with Array.Sort in ConstraintKeyScheduler by @thomhurst in thomhurst/TUnit#6067 * perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by @thomhurst in thomhurst/TUnit#6069 * perf: collapse OfType chains in JUnitXmlWriter (#6052) by @thomhurst in thomhurst/TUnit#6070 * perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) by @thomhurst in thomhurst/TUnit#6071 * perf: avoid closure allocation in BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#6040) by @thomhurst in thomhurst/TUnit#6073 * perf: use TryAdd in TestDependencyResolver dependency dedupe by @thomhurst in thomhurst/TUnit#6068 * perf: replace LINQ Any with foreach in TestGenericTypeResolver (#6044) by @thomhurst in thomhurst/TUnit#6072 * perf: avoid Cast<object>().FirstOrDefault() iterator alloc in CastHelper (#6029) by @thomhurst in thomhurst/TUnit#6074 * perf(engine): avoid string round-trip when building nested type names (#6049) by @thomhurst in thomhurst/TUnit#6075 * perf(engine): replace Select+ToArray with manual Type[] build (#6043) by @thomhurst in thomhurst/TUnit#6076 * perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in ClassConstructorHelper by @thomhurst in thomhurst/TUnit#6078 * perf(engine): avoid FirstOrDefault iterator alloc in TestGenericTypeResolver by @thomhurst in thomhurst/TUnit#6079 * perf(engine): use SearchValues<char> for reporter filename sanitization by @thomhurst in thomhurst/TUnit#6090 * perf: dedupe TestDataFormatter.FormatArguments with pooled StringBuilder by @thomhurst in thomhurst/TUnit#6088 * perf(engine): use MemoryExtensions.Split for path parsing in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6085 * perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for dictionary index builds by @thomhurst in thomhurst/TUnit#6086 * perf(engine): replace LINQ Where closure with inline filter in MetadataDependencyExpander BFS by @thomhurst in thomhurst/TUnit#6084 * perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments by @thomhurst in thomhurst/TUnit#6082 * Preserve specialized chaining after null assertions by @thomhurst in thomhurst/TUnit#6008 * perf: use EnumerateLines for line splitting in HtmlReportGenerator by @thomhurst in thomhurst/TUnit#6089 * perf: collapse Replace chain in TestNameFormatter.BuildTestId by @thomhurst in thomhurst/TUnit#6083 * perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span mapping by @thomhurst in thomhurst/TUnit#6093 * perf(assertions): avoid eager interpolated-string alloc in assertion source ctors by @thomhurst in thomhurst/TUnit#6091 * perf: optimize TestNameFormatter argument and bool formatting by @thomhurst in thomhurst/TUnit#6095 * perf: use FrozenSet/FrozenDictionary for read-only static lookups by @thomhurst in thomhurst/TUnit#6099 * perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans by @thomhurst in thomhurst/TUnit#6098 * perf(engine): replace magic-string RequiredAttribute match with type check in ConstructorHelper by @thomhurst in thomhurst/TUnit#6087 * perf(core): replace Select+Func factory chain in DataSourceHelpers by @thomhurst in thomhurst/TUnit#6081 * perf: replace LINQ dependency extraction with manual loop by @thomhurst in thomhurst/TUnit#6096 * perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments by @thomhurst in thomhurst/TUnit#6080 * perf: use [GeneratedRegex] in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6094 * perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by @thomhurst in thomhurst/TUnit#6097 * fix: remove GitVersion MSBuild task, pin local builds to 99.99.99 (#6077) by @thomhurst in thomhurst/TUnit#6101 * HTML Report: source link + code snippet on Source tab (#5993) by @thomhurst in thomhurst/TUnit#6100 * perf(sourcegen): Single-pass attribute classification by @thomhurst in thomhurst/TUnit#6111 * perf(core): eliminate per-test allocations in TestDetails/HookMethod by @thomhurst in thomhurst/TUnit#6109 * perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static SearchValues by @thomhurst in thomhurst/TUnit#6108 * perf(core): de-LINQ data-source expansion by @thomhurst in thomhurst/TUnit#6110 * perf: avoid LINQ chains in TestDependency equality and MethodDataSourceAttribute method matching by @thomhurst in thomhurst/TUnit#6092 * perf(engine): reduce allocations in reflection-mode discovery/execution by @thomhurst in thomhurst/TUnit#6113 * perf(assertions): allocation-free passing path (TUnit.Assertions) by @thomhurst in thomhurst/TUnit#6112 ### Dependencies ... (truncated) ## 1.46.0 <!-- Release notes generated using configuration in .github/release.yml at v1.46.0 --> ## What's Changed ### Other Changes * docs: add Rider VSTest conflict troubleshooting by @smolchanovsky in thomhurst/TUnit#5989 * Populate generated test metadata with full source spans by @Copilot in thomhurst/TUnit#5991 * Add devcontainer configuration by @Copilot in thomhurst/TUnit#5995 * fix: treenode filter pre-filter rejects parenthesised segments (#6026) by @thomhurst in thomhurst/TUnit#6027 * fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by @thomhurst in thomhurst/TUnit#6025 ### Dependencies * chore(deps): update dependency stackexchange.redis to 2.13.10 by @thomhurst in thomhurst/TUnit#5985 * chore(deps): update tunit to 1.45.29 by @thomhurst in thomhurst/TUnit#5986 * chore(deps): update dependency mockolate to 3.2.1 by @thomhurst in thomhurst/TUnit#5987 * chore(deps): update dependency microsoft.playwright to 1.60.0 by @thomhurst in thomhurst/TUnit#5988 * chore(deps): update dependency messagepack to 3.1.6 by @thomhurst in thomhurst/TUnit#5992 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5998 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5997 * chore(deps): update verify to 31.17.0 by @thomhurst in thomhurst/TUnit#6000 * chore(deps): update verify to 31.18.0 by @thomhurst in thomhurst/TUnit#6013 * chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by @thomhurst in thomhurst/TUnit#6016 * chore(deps): update dependency dompurify to v3.4.6 by @thomhurst in thomhurst/TUnit#6015 * chore(deps): update dependency dompurify to v3.4.7 by @thomhurst in thomhurst/TUnit#6019 * chore(deps): update dependency npgsql to 10.0.3 by @thomhurst in thomhurst/TUnit#6020 * chore(deps): update dependency stackexchange.redis to 2.13.17 by @thomhurst in thomhurst/TUnit#6021 * chore(deps): update dependency npgsql.entityframeworkcore.postgresql to 10.0.2 by @thomhurst in thomhurst/TUnit#6022 ## New Contributors * @smolchanovsky made their first contribution in thomhurst/TUnit#5989 **Full Changelog**: thomhurst/TUnit@v1.45.29...v1.46.0 Commits viewable in [compare view](thomhurst/TUnit@v1.45.29...v1.48.6). </details> 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>
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.45.29 to 1.48.6. <details> <summary>Release notes</summary> _Sourced from [TUnit.Core's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.48.6 <!-- Release notes generated using configuration in .github/release.yml at v1.48.6 --> ## What's Changed ### Other Changes * fix(sourcegen): fully-qualify Linq calls in params array binding (#6140) by @thomhurst in thomhurst/TUnit#6141 ### Dependencies * chore(deps): update tunit to 1.48.0 by @thomhurst in thomhurst/TUnit#6135 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6137 * chore(deps): update dependency polyfill to 10.7.1 by @thomhurst in thomhurst/TUnit#6138 * chore(deps): update verify to 31.19.0 by @thomhurst in thomhurst/TUnit#6139 **Full Changelog**: thomhurst/TUnit@v1.48.0...v1.48.6 ## 1.48.0 <!-- Release notes generated using configuration in .github/release.yml at v1.48.0 --> ## What's Changed ### Other Changes * feat(html-report): baked-in C# syntax highlighting on Source tab by @slang25 in thomhurst/TUnit#6132 * feat(analyzers): suppress VSTHRD200 on test and hook methods by @thomhurst in thomhurst/TUnit#6123 * fix(source-gen): correct source location for cross-project inherited tests by @slang25 in thomhurst/TUnit#6133 * feat(assertions): add WasCalled to tunit mocks assertions by @robertcoltheart in thomhurst/TUnit#6126 * feat(arguments): bind array values to a single array test parameter by @thomhurst in thomhurst/TUnit#6122 * fix: populate retry/flaky attempt history in HTML report (#6119) by @thomhurst in thomhurst/TUnit#6124 ### Dependencies * chore(deps): update tunit to 1.47.0 by @thomhurst in thomhurst/TUnit#6115 * chore(deps): update dependency microsoft.visualstudio.threading.analyzers to 17.14.15 by @thomhurst in thomhurst/TUnit#6134 **Full Changelog**: thomhurst/TUnit@v1.47.0...v1.48.0 ## 1.47.0 <!-- Release notes generated using configuration in .github/release.yml at v1.47.0 --> ## What's Changed ### Other Changes * perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery hooks by @thomhurst in thomhurst/TUnit#6062 * perf(engine): hoist GetParameters and drop LINQ in reflection discovery by @thomhurst in thomhurst/TUnit#6063 * perf(engine): cache treenode filter path on TestMetadata by @thomhurst in thomhurst/TUnit#6064 * perf: use is T pattern in ReflectionExtensions.HasAttribute fallback (#6060) by @thomhurst in thomhurst/TUnit#6066 * perf: replace OrderBy().ToArray() with Array.Sort in ConstraintKeyScheduler by @thomhurst in thomhurst/TUnit#6067 * perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by @thomhurst in thomhurst/TUnit#6069 * perf: collapse OfType chains in JUnitXmlWriter (#6052) by @thomhurst in thomhurst/TUnit#6070 * perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) by @thomhurst in thomhurst/TUnit#6071 * perf: avoid closure allocation in BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#6040) by @thomhurst in thomhurst/TUnit#6073 * perf: use TryAdd in TestDependencyResolver dependency dedupe by @thomhurst in thomhurst/TUnit#6068 * perf: replace LINQ Any with foreach in TestGenericTypeResolver (#6044) by @thomhurst in thomhurst/TUnit#6072 * perf: avoid Cast<object>().FirstOrDefault() iterator alloc in CastHelper (#6029) by @thomhurst in thomhurst/TUnit#6074 * perf(engine): avoid string round-trip when building nested type names (#6049) by @thomhurst in thomhurst/TUnit#6075 * perf(engine): replace Select+ToArray with manual Type[] build (#6043) by @thomhurst in thomhurst/TUnit#6076 * perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in ClassConstructorHelper by @thomhurst in thomhurst/TUnit#6078 * perf(engine): avoid FirstOrDefault iterator alloc in TestGenericTypeResolver by @thomhurst in thomhurst/TUnit#6079 * perf(engine): use SearchValues<char> for reporter filename sanitization by @thomhurst in thomhurst/TUnit#6090 * perf: dedupe TestDataFormatter.FormatArguments with pooled StringBuilder by @thomhurst in thomhurst/TUnit#6088 * perf(engine): use MemoryExtensions.Split for path parsing in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6085 * perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for dictionary index builds by @thomhurst in thomhurst/TUnit#6086 * perf(engine): replace LINQ Where closure with inline filter in MetadataDependencyExpander BFS by @thomhurst in thomhurst/TUnit#6084 * perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments by @thomhurst in thomhurst/TUnit#6082 * Preserve specialized chaining after null assertions by @thomhurst in thomhurst/TUnit#6008 * perf: use EnumerateLines for line splitting in HtmlReportGenerator by @thomhurst in thomhurst/TUnit#6089 * perf: collapse Replace chain in TestNameFormatter.BuildTestId by @thomhurst in thomhurst/TUnit#6083 * perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span mapping by @thomhurst in thomhurst/TUnit#6093 * perf(assertions): avoid eager interpolated-string alloc in assertion source ctors by @thomhurst in thomhurst/TUnit#6091 * perf: optimize TestNameFormatter argument and bool formatting by @thomhurst in thomhurst/TUnit#6095 * perf: use FrozenSet/FrozenDictionary for read-only static lookups by @thomhurst in thomhurst/TUnit#6099 * perf: avoid GetCustomAttributes() + LINQ chain for per-property attribute scans by @thomhurst in thomhurst/TUnit#6098 * perf(engine): replace magic-string RequiredAttribute match with type check in ConstructorHelper by @thomhurst in thomhurst/TUnit#6087 * perf(core): replace Select+Func factory chain in DataSourceHelpers by @thomhurst in thomhurst/TUnit#6081 * perf: replace LINQ dependency extraction with manual loop by @thomhurst in thomhurst/TUnit#6096 * perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments by @thomhurst in thomhurst/TUnit#6080 * perf: use [GeneratedRegex] in MetadataFilterMatcher by @thomhurst in thomhurst/TUnit#6094 * perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by @thomhurst in thomhurst/TUnit#6097 * fix: remove GitVersion MSBuild task, pin local builds to 99.99.99 (#6077) by @thomhurst in thomhurst/TUnit#6101 * HTML Report: source link + code snippet on Source tab (#5993) by @thomhurst in thomhurst/TUnit#6100 * perf(sourcegen): Single-pass attribute classification by @thomhurst in thomhurst/TUnit#6111 * perf(core): eliminate per-test allocations in TestDetails/HookMethod by @thomhurst in thomhurst/TUnit#6109 * perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static SearchValues by @thomhurst in thomhurst/TUnit#6108 * perf(core): de-LINQ data-source expansion by @thomhurst in thomhurst/TUnit#6110 * perf: avoid LINQ chains in TestDependency equality and MethodDataSourceAttribute method matching by @thomhurst in thomhurst/TUnit#6092 * perf(engine): reduce allocations in reflection-mode discovery/execution by @thomhurst in thomhurst/TUnit#6113 * perf(assertions): allocation-free passing path (TUnit.Assertions) by @thomhurst in thomhurst/TUnit#6112 ### Dependencies ... (truncated) ## 1.46.0 <!-- Release notes generated using configuration in .github/release.yml at v1.46.0 --> ## What's Changed ### Other Changes * docs: add Rider VSTest conflict troubleshooting by @smolchanovsky in thomhurst/TUnit#5989 * Populate generated test metadata with full source spans by @Copilot in thomhurst/TUnit#5991 * Add devcontainer configuration by @Copilot in thomhurst/TUnit#5995 * fix: treenode filter pre-filter rejects parenthesised segments (#6026) by @thomhurst in thomhurst/TUnit#6027 * fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by @thomhurst in thomhurst/TUnit#6025 ### Dependencies * chore(deps): update dependency stackexchange.redis to 2.13.10 by @thomhurst in thomhurst/TUnit#5985 * chore(deps): update tunit to 1.45.29 by @thomhurst in thomhurst/TUnit#5986 * chore(deps): update dependency mockolate to 3.2.1 by @thomhurst in thomhurst/TUnit#5987 * chore(deps): update dependency microsoft.playwright to 1.60.0 by @thomhurst in thomhurst/TUnit#5988 * chore(deps): update dependency messagepack to 3.1.6 by @thomhurst in thomhurst/TUnit#5992 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5998 * chore(deps): update dependency polyfill to 10.7.0 by @thomhurst in thomhurst/TUnit#5997 * chore(deps): update verify to 31.17.0 by @thomhurst in thomhurst/TUnit#6000 * chore(deps): update verify to 31.18.0 by @thomhurst in thomhurst/TUnit#6013 * chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by @thomhurst in thomhurst/TUnit#6016 * chore(deps): update dependency dompurify to v3.4.6 by @thomhurst in thomhurst/TUnit#6015 * chore(deps): update dependency dompurify to v3.4.7 by @thomhurst in thomhurst/TUnit#6019 * chore(deps): update dependency npgsql to 10.0.3 by @thomhurst in thomhurst/TUnit#6020 * chore(deps): update dependency stackexchange.redis to 2.13.17 by @thomhurst in thomhurst/TUnit#6021 * chore(deps): update dependency npgsql.entityframeworkcore.postgresql to 10.0.2 by @thomhurst in thomhurst/TUnit#6022 ## New Contributors * @smolchanovsky made their first contribution in thomhurst/TUnit#5989 **Full Changelog**: thomhurst/TUnit@v1.45.29...v1.46.0 Commits viewable in [compare view](thomhurst/TUnit@v1.45.29...v1.48.6). </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>
@
What
Replaces
GetCustomAttributes()+ LINQ (OfType/Any/FirstOrDefault) per-property attribute scans with a single-passforeachthat returns the firstIDataSourceAttribute.ReflectionInstanceFactory.InjectPropertiesAsync— wasGetCustomAttributes().OfType<IDataSourceAttribute>().ToArray(). Now a single-pass helper. Drops theOfTypeiterator + materialised array; for the common case (property with no data source) nothing extra is allocated.StaticPropertyReflectionInitializer— previously materialised the attribute array twice per property (once in a.Where(HasDataSourceAttribute)filter, again viaFirstOrDefaultinsideInitializeStaticProperty). Collapsed into a single scan per property; the resolved attribute is passed straight through.Per the issue,
ConstructorHelper.csis intentionally not modified here — it is covered by separate open PR #6056.Why
GetCustomAttributes()allocates anobject[], and the LINQ chain layers iterators + lambdas + a final array on top. These run per property per type during reflection-mode discovery/construction (a hot path), and for the common no-data-source case it was pure waste.Validation
dotnet build TUnit.Coreanddotnet build TUnit.Engine(-p:DisableGitVersionTask=true): 0 warnings, 0 errors across net8.0/net9.0/net10.0/netstandard2.0.Closes #6055
@