diff --git a/internal/civisibility/integrations/gotesting/instrumentation.go b/internal/civisibility/integrations/gotesting/instrumentation.go index bd35f429c9..08fcaf6553 100644 --- a/internal/civisibility/integrations/gotesting/instrumentation.go +++ b/internal/civisibility/integrations/gotesting/instrumentation.go @@ -162,14 +162,15 @@ func applyAdditionalFeaturesToTestFunc(f func(*testing.T), testInfo *commonInfo) // Target function targetFunc := f - // Flaky test retries - if settings.FlakyTestRetriesEnabled { - targetFunc = applyFlakyTestRetriesAdditionalFeature(targetFunc) - } - // Early flake detection + var earlyFlakeDetectionApplied bool if settings.EarlyFlakeDetection.Enabled { - targetFunc = applyEarlyFlakeDetectionAdditionalFeature(testInfo, targetFunc, settings) + targetFunc, earlyFlakeDetectionApplied = applyEarlyFlakeDetectionAdditionalFeature(testInfo, targetFunc, settings) + } + + // Flaky test retries (only if EFD was not applied and if the feature is enabled) + if !earlyFlakeDetectionApplied && settings.FlakyTestRetriesEnabled { + targetFunc, _ = applyFlakyTestRetriesAdditionalFeature(targetFunc) } // Register the instrumented func as an internal instrumented func (to avoid double instrumentation) @@ -178,7 +179,7 @@ func applyAdditionalFeaturesToTestFunc(f func(*testing.T), testInfo *commonInfo) } // applyFlakyTestRetriesAdditionalFeature applies the flaky test retries feature as a wrapper of a func(*testing.T) -func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) func(*testing.T) { +func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) (func(*testing.T), bool) { flakyRetrySettings := integrations.GetFlakyRetriesSettings() // If the retry count per test is > 1 and if we still have remaining total retry count @@ -235,13 +236,13 @@ func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) func(*t }, execMetaAdjust: nil, // No execMetaAdjust needed }) - } + }, true } - return targetFunc + return targetFunc, false } // applyEarlyFlakeDetectionAdditionalFeature applies the early flake detection feature as a wrapper of a func(*testing.T) -func applyEarlyFlakeDetectionAdditionalFeature(testInfo *commonInfo, targetFunc func(*testing.T), settings *net.SettingsResponseData) func(*testing.T) { +func applyEarlyFlakeDetectionAdditionalFeature(testInfo *commonInfo, targetFunc func(*testing.T), settings *net.SettingsResponseData) (func(*testing.T), bool) { earlyFlakeDetectionData := integrations.GetEarlyFlakeDetectionSettings() if earlyFlakeDetectionData != nil && len(earlyFlakeDetectionData.Tests) > 0 { @@ -327,10 +328,10 @@ func applyEarlyFlakeDetectionAdditionalFeature(testInfo *commonInfo, targetFunc execMeta.isANewTest = true }, }) - } + }, true } } - return targetFunc + return targetFunc, false } // runTestWithRetry encapsulates the common retry logic for test functions. diff --git a/internal/civisibility/integrations/gotesting/testcontroller_test.go b/internal/civisibility/integrations/gotesting/testcontroller_test.go index e48cc551f8..6bd2a10544 100644 --- a/internal/civisibility/integrations/gotesting/testcontroller_test.go +++ b/internal/civisibility/integrations/gotesting/testcontroller_test.go @@ -273,9 +273,8 @@ func runFlakyTestRetriesWithEarlyFlakyTestDetectionTests(m *testing.M) { // 1 TestSkip // 1 TestRetryWithPanic + 3 retry tests from testing_test.go // 1 TestRetryWithFail + 3 retry tests from testing_test.go - // 1 TestRetryAlwaysFail + 10 retry tests from testing_test.go // 1 TestNormalPassingAfterRetryAlwaysFail - // 11 TestEarlyFlakeDetection + 10 retries + // 1 TestEarlyFlakeDetection + 10 EFD retries // 2 normal spans from testing_test.go // check spans by resource name @@ -294,19 +293,19 @@ func runFlakyTestRetriesWithEarlyFlakyTestDetectionTests(m *testing.M) { checkSpansByResourceName(finishedSpans, "testing_test.go.TestRetryWithPanic", 4) checkSpansByResourceName(finishedSpans, "testing_test.go.TestRetryWithFail", 4) checkSpansByResourceName(finishedSpans, "testing_test.go.TestNormalPassingAfterRetryAlwaysFail", 1) - checkSpansByResourceName(finishedSpans, "testing_test.go.TestEarlyFlakeDetection", 21) + checkSpansByResourceName(finishedSpans, "testing_test.go.TestEarlyFlakeDetection", 11) // check spans by tag - checkSpansByTagName(finishedSpans, constants.TestIsNew, 21) - checkSpansByTagName(finishedSpans, constants.TestIsRetry, 26) + checkSpansByTagName(finishedSpans, constants.TestIsNew, 11) + checkSpansByTagName(finishedSpans, constants.TestIsRetry, 16) // check spans by type checkSpansByType(finishedSpans, - 48, + 38, 1, 1, 2, - 44, + 34, 0) fmt.Println("All tests passed.") diff --git a/internal/civisibility/integrations/manual_api_ddtest.go b/internal/civisibility/integrations/manual_api_ddtest.go index 3b0382cd8a..6451b6ac13 100644 --- a/internal/civisibility/integrations/manual_api_ddtest.go +++ b/internal/civisibility/integrations/manual_api_ddtest.go @@ -75,8 +75,8 @@ func createTest(suite *tslvTestSuite, name string, startTime time.Time) DdTest { }, } - // Ensure to close everything before CI visibility exits. In CI visibility mode, we try to never lose data. - PushCiVisibilityCloseAction(func() { t.Close(ResultStatusFail) }) + // Note: if the process is killed some tests will not be closed and will be lost. This is a known limitation. + // We will not close it because there's no a good test status to report in this case, and we don't want to report a false positive (pass, fail, or skip). return t }