Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Test Optimization] Support for MSTest v3.8.x #6686

Merged
merged 7 commits into from
Feb 21, 2025

Conversation

tonyredondo
Copy link
Member

@tonyredondo tonyredondo commented Feb 19, 2025

Summary of changes

This PR adds support for MSTest v3.8.x

Reason for change

These new version changed a lot of internal method signatures that break our instrumentation.

Implementation details

Added the missing classes or code to make it work.

Test coverage

Other details

Ticket: SDTEST-1650

@tonyredondo tonyredondo self-assigned this Feb 19, 2025
@andrewlock
Copy link
Member

andrewlock commented Feb 19, 2025

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing the following branches/commits:

Execution-time benchmarks measure the whole time it takes to execute a program. And are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are shown in red. The following thresholds were used for comparing the execution times:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard.

Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph).

gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (69ms)  : 66, 72
     .   : milestone, 69,
    master - mean (73ms)  : 70, 77
     .   : milestone, 73,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (998ms)  : 975, 1020
     .   : milestone, 998,
    master - mean (1,034ms)  : 1004, 1063
     .   : milestone, 1034,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (102ms)  : 100, 104
     .   : milestone, 102,
    master - mean (108ms)  : 105, 111
     .   : milestone, 108,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (674ms)  : 653, 694
     .   : milestone, 674,
    master - mean (698ms)  : 680, 717
     .   : milestone, 698,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (89ms)  : 86, 91
     .   : milestone, 89,
    master - mean (95ms)  : 92, 97
     .   : milestone, 95,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (627ms)  : 608, 646
     .   : milestone, 627,
    master - mean (656ms)  : 639, 672
     .   : milestone, 656,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (191ms)  : 186, 196
     .   : milestone, 191,
    master - mean (191ms)  : 186, 197
     .   : milestone, 191,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (1,108ms)  : 1071, 1146
     .   : milestone, 1108,
    master - mean (1,109ms)  : 1073, 1146
     .   : milestone, 1109,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (271ms)  : 267, 275
     .   : milestone, 271,
    master - mean (273ms)  : 266, 280
     .   : milestone, 273,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (868ms)  : 831, 904
     .   : milestone, 868,
    master - mean (867ms)  : 834, 900
     .   : milestone, 867,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6686) - mean (263ms)  : 258, 267
     .   : milestone, 263,
    master - mean (262ms)  : 258, 267
     .   : milestone, 262,

    section CallTarget+Inlining+NGEN
    This PR (6686) - mean (837ms)  : 806, 868
     .   : milestone, 837,
    master - mean (849ms)  : 822, 877
     .   : milestone, 849,

Loading

@andrewlock
Copy link
Member

andrewlock commented Feb 19, 2025

Benchmarks Report for tracer 🐌

Benchmarks for #6686 compared to master:

  • 1 benchmarks are faster, with geometric mean 1.136
  • 1 benchmarks have fewer allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 7.86μs 43ns 262ns 0.0203 0.00811 0 5.61 KB
master StartStopWithChild netcoreapp3.1 10.1μs 55.5ns 324ns 0.0199 0.00996 0 5.8 KB
master StartStopWithChild net472 15.9μs 38.1ns 142ns 1.04 0.307 0.0944 6.21 KB
#6686 StartStopWithChild net6.0 8.26μs 47.8ns 388ns 0.0152 0.00762 0 5.61 KB
#6686 StartStopWithChild netcoreapp3.1 10.9μs 61.1ns 400ns 0.0162 0.0054 0 5.8 KB
#6686 StartStopWithChild net472 16.1μs 37.6ns 146ns 1.03 0.299 0.0968 6.21 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 492μs 486ns 1.82μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 700μs 282ns 1.05μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 848μs 626ns 2.34μs 0.422 0 0 3.3 KB
#6686 WriteAndFlushEnrichedTraces net6.0 491μs 271ns 1.01μs 0 0 0 2.7 KB
#6686 WriteAndFlushEnrichedTraces netcoreapp3.1 650μs 539ns 2.09μs 0 0 0 2.7 KB
#6686 WriteAndFlushEnrichedTraces net472 863μs 1.73μs 6.7μs 0.428 0 0 3.3 KB
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net6.0 132μs 417ns 1.61μs 0.135 0 0 14.47 KB
master SendRequest netcoreapp3.1 147μs 396ns 1.53μs 0.22 0 0 17.27 KB
master SendRequest net472 0.00199ns 0.000288ns 0.00112ns 0 0 0 0 b
#6686 SendRequest net6.0 127μs 299ns 1.12μs 0.187 0 0 14.47 KB
#6686 SendRequest netcoreapp3.1 147μs 233ns 872ns 0.22 0 0 17.27 KB
#6686 SendRequest net472 0.00322ns 0.00116ns 0.00448ns 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #6686

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0 41.87 KB 41.55 KB -317 B -0.76%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 608μs 3.32μs 18.8μs 0.604 0 0 41.87 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 670μs 3.78μs 27.5μs 0.338 0 0 41.69 KB
master WriteAndFlushEnrichedTraces net472 840μs 2.83μs 10.6μs 8.22 2.47 0.411 53.34 KB
#6686 WriteAndFlushEnrichedTraces net6.0 573μs 3.09μs 18.3μs 0.579 0 0 41.55 KB
#6686 WriteAndFlushEnrichedTraces netcoreapp3.1 643μs 2.24μs 8.39μs 0.324 0 0 41.76 KB
#6686 WriteAndFlushEnrichedTraces net472 885μs 4.17μs 17.2μs 8.62 2.59 0.431 53.3 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net6.0 1.44μs 2.09ns 8.1ns 0.0138 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 1.75μs 2.38ns 9.22ns 0.0139 0 0 1.02 KB
master ExecuteNonQuery net472 2.07μs 4.15ns 16.1ns 0.156 0.00103 0 987 B
#6686 ExecuteNonQuery net6.0 1.32μs 1.26ns 4.88ns 0.0144 0 0 1.02 KB
#6686 ExecuteNonQuery netcoreapp3.1 1.84μs 1.58ns 6.11ns 0.0138 0 0 1.02 KB
#6686 ExecuteNonQuery net472 2.1μs 2.1ns 8.13ns 0.156 0.00106 0 987 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net6.0 1.21μs 0.404ns 1.51ns 0.0139 0 0 976 B
master CallElasticsearch netcoreapp3.1 1.5μs 0.958ns 3.59ns 0.0128 0 0 976 B
master CallElasticsearch net472 2.46μs 2.36ns 9.14ns 0.158 0 0 995 B
master CallElasticsearchAsync net6.0 1.37μs 1.01ns 3.76ns 0.013 0 0 952 B
master CallElasticsearchAsync netcoreapp3.1 1.71μs 0.965ns 3.61ns 0.0139 0 0 1.02 KB
master CallElasticsearchAsync net472 2.67μs 1.97ns 7.63ns 0.166 0 0 1.05 KB
#6686 CallElasticsearch net6.0 1.12μs 2.02ns 7.81ns 0.0133 0 0 976 B
#6686 CallElasticsearch netcoreapp3.1 1.57μs 1.32ns 4.96ns 0.0134 0 0 976 B
#6686 CallElasticsearch net472 2.48μs 1.8ns 6.98ns 0.157 0 0 995 B
#6686 CallElasticsearchAsync net6.0 1.31μs 0.64ns 2.48ns 0.0131 0 0 952 B
#6686 CallElasticsearchAsync netcoreapp3.1 1.71μs 1.21ns 4.7ns 0.0137 0 0 1.02 KB
#6686 CallElasticsearchAsync net472 2.63μs 1.96ns 7.6ns 0.166 0 0 1.05 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net6.0 1.44μs 1.02ns 3.96ns 0.013 0 0 952 B
master ExecuteAsync netcoreapp3.1 1.71μs 0.954ns 3.7ns 0.012 0 0 952 B
master ExecuteAsync net472 1.86μs 0.559ns 2.09ns 0.145 0 0 915 B
#6686 ExecuteAsync net6.0 1.39μs 0.473ns 1.77ns 0.0131 0 0 952 B
#6686 ExecuteAsync netcoreapp3.1 1.68μs 0.328ns 1.14ns 0.0126 0 0 952 B
#6686 ExecuteAsync net472 1.9μs 0.989ns 3.83ns 0.145 0 0 915 B
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net6.0 4.41μs 1.19ns 4.47ns 0.0331 0 0 2.31 KB
master SendAsync netcoreapp3.1 5.35μs 3.47ns 13ns 0.0374 0 0 2.85 KB
master SendAsync net472 7.37μs 2.03ns 7.85ns 0.495 0 0 3.12 KB
#6686 SendAsync net6.0 4.63μs 1.85ns 6.92ns 0.0324 0 0 2.31 KB
#6686 SendAsync netcoreapp3.1 5.37μs 4.82ns 17.4ns 0.0374 0 0 2.85 KB
#6686 SendAsync net472 7.41μs 2.95ns 11ns 0.495 0 0 3.12 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 1.58μs 0.493ns 1.78ns 0.023 0 0 1.64 KB
master EnrichedLog netcoreapp3.1 2.19μs 1.07ns 3.99ns 0.0228 0 0 1.64 KB
master EnrichedLog net472 2.67μs 4.35ns 16.9ns 0.25 0 0 1.57 KB
#6686 EnrichedLog net6.0 1.62μs 1.07ns 4ns 0.0229 0 0 1.64 KB
#6686 EnrichedLog netcoreapp3.1 2.18μs 2.16ns 8.37ns 0.0219 0 0 1.64 KB
#6686 EnrichedLog net472 2.55μs 1.03ns 3.7ns 0.25 0 0 1.57 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 112μs 212ns 822ns 0.0558 0 0 4.28 KB
master EnrichedLog netcoreapp3.1 117μs 148ns 573ns 0.0582 0 0 4.28 KB
master EnrichedLog net472 151μs 82.1ns 307ns 0.681 0.227 0 4.46 KB
#6686 EnrichedLog net6.0 114μs 123ns 445ns 0.0566 0 0 4.28 KB
#6686 EnrichedLog netcoreapp3.1 120μs 337ns 1.31μs 0 0 0 4.28 KB
#6686 EnrichedLog net472 150μs 228ns 852ns 0.672 0.224 0 4.46 KB
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 3.11μs 0.496ns 1.72ns 0.0311 0 0 2.2 KB
master EnrichedLog netcoreapp3.1 4.2μs 2.35ns 8.79ns 0.0294 0 0 2.2 KB
master EnrichedLog net472 5.03μs 1.01ns 3.79ns 0.32 0 0 2.02 KB
#6686 EnrichedLog net6.0 3.03μs 0.709ns 2.65ns 0.0305 0 0 2.2 KB
#6686 EnrichedLog netcoreapp3.1 4.25μs 3.1ns 12ns 0.0296 0 0 2.2 KB
#6686 EnrichedLog net472 4.8μs 1.66ns 6.21ns 0.32 0 0 2.02 KB
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 1.27μs 0.38ns 1.47ns 0.0159 0 0 1.14 KB
master SendReceive netcoreapp3.1 1.77μs 0.486ns 1.68ns 0.015 0 0 1.14 KB
master SendReceive net472 2.12μs 2.85ns 11.1ns 0.183 0 0 1.16 KB
#6686 SendReceive net6.0 1.32μs 0.983ns 3.68ns 0.0157 0 0 1.14 KB
#6686 SendReceive netcoreapp3.1 1.8μs 0.937ns 3.51ns 0.0149 0 0 1.14 KB
#6686 SendReceive net472 1.95μs 0.946ns 3.54ns 0.183 0 0 1.16 KB
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.77μs 1.19ns 4.44ns 0.022 0 0 1.6 KB
master EnrichedLog netcoreapp3.1 3.97μs 5.6ns 20.9ns 0.0217 0 0 1.65 KB
master EnrichedLog net472 4.3μs 3.26ns 12.6ns 0.323 0 0 2.04 KB
#6686 EnrichedLog net6.0 2.72μs 0.964ns 3.74ns 0.0218 0 0 1.6 KB
#6686 EnrichedLog netcoreapp3.1 3.95μs 1.68ns 6.3ns 0.0216 0 0 1.65 KB
#6686 EnrichedLog net472 4.2μs 2.83ns 10.6ns 0.323 0 0 2.04 KB
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 391ns 0.461ns 1.79ns 0.00817 0 0 576 B
master StartFinishSpan netcoreapp3.1 557ns 0.82ns 3.18ns 0.00784 0 0 576 B
master StartFinishSpan net472 584ns 1.27ns 4.91ns 0.0915 0 0 578 B
master StartFinishScope net6.0 515ns 0.487ns 1.89ns 0.00983 0 0 696 B
master StartFinishScope netcoreapp3.1 742ns 1.68ns 6.07ns 0.00932 0 0 696 B
master StartFinishScope net472 839ns 2.27ns 8.78ns 0.105 0 0 658 B
#6686 StartFinishSpan net6.0 387ns 0.591ns 2.29ns 0.00813 0 0 576 B
#6686 StartFinishSpan netcoreapp3.1 575ns 1.86ns 6.97ns 0.00766 0 0 576 B
#6686 StartFinishSpan net472 634ns 1.43ns 5.55ns 0.0915 0 0 578 B
#6686 StartFinishScope net6.0 479ns 0.723ns 2.8ns 0.00983 0 0 696 B
#6686 StartFinishScope netcoreapp3.1 816ns 1.82ns 7.06ns 0.00953 0 0 696 B
#6686 StartFinishScope net472 806ns 1.91ns 7.42ns 0.104 0 0 658 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #6686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑net6.0 1.136 731.18 643.60

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 733ns 1.3ns 5.05ns 0.00951 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 907ns 1.48ns 5.73ns 0.00936 0 0 696 B
master RunOnMethodBegin net472 1.16μs 1.52ns 5.88ns 0.105 0 0 658 B
#6686 RunOnMethodBegin net6.0 643ns 0.83ns 3.21ns 0.00989 0 0 696 B
#6686 RunOnMethodBegin netcoreapp3.1 850ns 1.2ns 4.34ns 0.0091 0 0 696 B
#6686 RunOnMethodBegin net472 1.07μs 3.54ns 13.7ns 0.104 0 0 658 B

@andrewlock andrewlock force-pushed the tony/testoptimization-add-MSTestV2-3.8.x-support branch from d86b72a to eafa170 Compare February 20, 2025 16:43
@tonyredondo tonyredondo marked this pull request as ready for review February 21, 2025 09:13
@tonyredondo tonyredondo requested review from a team as code owners February 21, 2025 09:13
Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

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

Still in progress, will finish soon!

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Testing.MsTestV2;

[DuckCopy]
internal struct AssemblyInfoExceptionsStruct
Copy link
Member

Choose a reason for hiding this comment

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

nit: don't need to add them in now, but I like when we include links to the github types these are duck typing, makes it easier to verify nullability annotations are correct etc + we'll need an explicit link for AOT in the (distant) future

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh man for AOT I probably will need to redo everything to split between versions, 2.x.0 is totally different to 3.[0-7] and different to 3.8.x . That means I'm 80% sure that this ducktype proxy maps with different types for different versions 😬

}

lock (instance.Instance!)
string? assemblyName;
if (testContext.TryDuckCast<TestContextStruct>(out var context) && context.TestMethod is { AssemblyName: { } contextAssemblyName })
Copy link
Member

Choose a reason for hiding this comment

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

nit: should the second part of the if be inside the outer one?

i.e. is there ever a case where we can duck cast as TestContextStruct, but assembly is null, and so we should also try to duck cast ITestAssemblyInfoWithAssembly? Or is it either/or with the duck casting?

Copy link
Member Author

Choose a reason for hiding this comment

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

changed in a565f84

@@ -83,4 +93,11 @@ internal static CallTargetReturn OnMethodEnd<TTarget>(TTarget instance, Exceptio
private static void EmptyCleanUpMethod()
{
}

#pragma warning disable SA1201
internal interface ITestAssemblyInfoWithAssembly : ITestAssemblyInfo
Copy link
Member

Choose a reason for hiding this comment

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

Is there any value in deriving from ITestAssemblyInfo here? You're only accessing the Assembly - doesn't that mean you're doing more work mapping other members you're never going to use?

Copy link
Member Author

Choose a reason for hiding this comment

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

you're totally right! done in a565f84

return new CallTargetReturn<TReturn?>(returnValue);
}

if (returnValue is IList { Count: > 0 } lstResults)
Copy link
Member

Choose a reason for hiding this comment

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

Is it worth using ICollection here if all you need is a Count and enumerate?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, done in a565f84

Comment on lines 58 to 65
if (state.State is StrongBox<MethodInfoCacheItem?> box)
{
methodInfoCacheItem = box.Value ?? MsTestIntegration.IsTestMethodRunnableThreadLocal.Value;
}
else
{
methodInfoCacheItem = MsTestIntegration.IsTestMethodRunnableThreadLocal.Value;
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this is a little neater? Undecided

Suggested change
if (state.State is StrongBox<MethodInfoCacheItem?> box)
{
methodInfoCacheItem = box.Value ?? MsTestIntegration.IsTestMethodRunnableThreadLocal.Value;
}
else
{
methodInfoCacheItem = MsTestIntegration.IsTestMethodRunnableThreadLocal.Value;
}
if (state.State is StrongBox<MethodInfoCacheItem?> box && box.Value is { } value)
{
methodInfoCacheItem = value;
}
else
{
methodInfoCacheItem = MsTestIntegration.IsTestMethodRunnableThreadLocal.Value;
}

Copy link
Member Author

Choose a reason for hiding this comment

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

I like that, changed in a565f84

Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

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

Nice work! 💪

// We need to check if the test is failing because a Class initialization error
if (testMethodInfo.Parent?.Instance.TryDuckCast<ClassInfoInitializationExceptionStruct>(out var classInfoInitializationExceptionStruct) == true)
{
if (classInfoInitializationExceptionStruct.ClassInitializationException is { } classInitializationException &&
Copy link
Member

Choose a reason for hiding this comment

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

Is it expected that duck typing to ClassInfoInitializationExceptionStruct could succeed, but Exception is null? 🤔

Copy link
Member Author

@tonyredondo tonyredondo Feb 21, 2025

Choose a reason for hiding this comment

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

yes because here ClassInfoInitializationExceptionStruct is extracted from a TestClassInfo so it can have an exception or not. TestClassInfo has a lot of properties regarding the class of the test method. So here we are just checking if the ClassInitializationException property inside TestClassInfo has a value, and use that value as an error in the test.

@tonyredondo tonyredondo merged commit 2860cab into master Feb 21, 2025
148 of 151 checks passed
@tonyredondo tonyredondo deleted the tony/testoptimization-add-MSTestV2-3.8.x-support branch February 21, 2025 14:02
@github-actions github-actions bot added this to the vNext-v3 milestone Feb 21, 2025
@andrewlock andrewlock added type:enhancement Improvement to an existing feature area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) area:ci-visibility area:integrations labels Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) area:ci-visibility area:integrations type:enhancement Improvement to an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants