@@ -48,7 +48,9 @@ const {
48
48
TEST_MANAGEMENT_IS_DISABLED ,
49
49
DD_CAPABILITIES_TEST_IMPACT_ANALYSIS ,
50
50
DD_CAPABILITIES_EARLY_FLAKE_DETECTION ,
51
- DD_CAPABILITIES_AUTO_TEST_RETRIES
51
+ DD_CAPABILITIES_AUTO_TEST_RETRIES ,
52
+ TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX ,
53
+ TEST_HAS_FAILED_ALL_RETRIES
52
54
} = require ( '../../packages/dd-trace/src/plugins/util/test' )
53
55
const { DD_HOST_CPU_COUNT } = require ( '../../packages/dd-trace/src/plugins/util/env' )
54
56
const { ERROR_MESSAGE } = require ( '../../packages/dd-trace/src/constants' )
@@ -2566,6 +2568,147 @@ describe('mocha CommonJS', function () {
2566
2568
} )
2567
2569
2568
2570
context ( 'test management' , ( ) => {
2571
+ context ( 'attempt to fix' , ( ) => {
2572
+ beforeEach ( ( ) => {
2573
+ receiver . setTestManagementTests ( {
2574
+ mocha : {
2575
+ suites : {
2576
+ 'ci-visibility/test-management/test-attempt-to-fix-1.js' : {
2577
+ tests : {
2578
+ 'attempt to fix tests can attempt to fix a test' : {
2579
+ properties : {
2580
+ attempt_to_fix : true
2581
+ }
2582
+ }
2583
+ }
2584
+ }
2585
+ }
2586
+ }
2587
+ } )
2588
+ } )
2589
+
2590
+ const getTestAssertions = ( isAttemptToFix ) =>
2591
+ receiver
2592
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
2593
+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
2594
+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
2595
+ const testSession = events . find ( event => event . type === 'test_session_end' ) . content
2596
+
2597
+ if ( isAttemptToFix ) {
2598
+ assert . propertyVal ( testSession . meta , TEST_MANAGEMENT_ENABLED , 'true' )
2599
+ } else {
2600
+ assert . notProperty ( testSession . meta , TEST_MANAGEMENT_ENABLED )
2601
+ }
2602
+
2603
+ const resourceNames = tests . map ( span => span . resource )
2604
+
2605
+ assert . includeMembers ( resourceNames ,
2606
+ [
2607
+ 'ci-visibility/test-management/test-attempt-to-fix-1.js.attempt to fix tests can attempt to fix a test'
2608
+ ]
2609
+ )
2610
+
2611
+ const retriedTests = tests . filter (
2612
+ test => test . meta [ TEST_NAME ] === 'attempt to fix tests can attempt to fix a test'
2613
+ )
2614
+
2615
+ for ( let i = 0 ; i < retriedTests . length ; i ++ ) {
2616
+ const test = retriedTests [ i ]
2617
+ if ( isAttemptToFix && i !== 0 ) {
2618
+ assert . propertyVal ( test . meta , TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX , 'true' )
2619
+ assert . propertyVal ( test . meta , TEST_IS_RETRY , 'true' )
2620
+ assert . propertyVal ( test . meta , TEST_RETRY_REASON , 'attempt_to_fix' )
2621
+ } else {
2622
+ assert . notProperty ( test . meta , TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX )
2623
+ assert . notProperty ( test . meta , TEST_IS_RETRY )
2624
+ assert . notProperty ( test . meta , TEST_RETRY_REASON )
2625
+ }
2626
+
2627
+ if ( isAttemptToFix && i === retriedTests . length - 1 ) {
2628
+ assert . propertyVal ( test . meta , TEST_HAS_FAILED_ALL_RETRIES , 'true' )
2629
+ }
2630
+ }
2631
+ } )
2632
+
2633
+ const runAttemptToFixTest = ( done , isAttemptToFix , isQuarantined , extraEnvVars = { } ) => {
2634
+ let stdout = ''
2635
+ const testAssertionsPromise = getTestAssertions ( isAttemptToFix )
2636
+
2637
+ childProcess = exec (
2638
+ runTestsWithCoverageCommand ,
2639
+ {
2640
+ cwd,
2641
+ env : {
2642
+ ...getCiVisAgentlessConfig ( receiver . port ) ,
2643
+ TESTS_TO_RUN : JSON . stringify ( [
2644
+ './test-management/test-attempt-to-fix-1.js'
2645
+ ] ) ,
2646
+ SHOULD_CHECK_RESULTS : '1' ,
2647
+ ...extraEnvVars
2648
+ } ,
2649
+ stdio : 'inherit'
2650
+ }
2651
+ )
2652
+
2653
+ childProcess . stdout . on ( 'data' , ( data ) => {
2654
+ stdout += data
2655
+ } )
2656
+
2657
+ childProcess . on ( 'exit' , exitCode => {
2658
+ testAssertionsPromise . then ( ( ) => {
2659
+ assert . include ( stdout , 'I am running when attempt to fix' )
2660
+ if ( isAttemptToFix && isQuarantined ) {
2661
+ // even though a test fails, the exit code is 0 because the test is quarantined
2662
+ assert . equal ( exitCode , 0 )
2663
+ } else {
2664
+ assert . equal ( exitCode , 1 )
2665
+ }
2666
+ done ( )
2667
+ } ) . catch ( done )
2668
+ } )
2669
+ }
2670
+
2671
+ it ( 'can attempt to fix tests' , ( done ) => {
2672
+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2673
+
2674
+ runAttemptToFixTest ( done , true , false )
2675
+ } )
2676
+
2677
+ it ( 'does not attempt to fix tests if test management is not enabled' , ( done ) => {
2678
+ receiver . setSettings ( { test_management : { enabled : false , attempt_to_fix_retries : 3 } } )
2679
+
2680
+ runAttemptToFixTest ( done , false , false )
2681
+ } )
2682
+
2683
+ it ( 'does not enable attempt to fix tests if DD_TEST_MANAGEMENT_ENABLED is set to false' , ( done ) => {
2684
+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2685
+
2686
+ runAttemptToFixTest ( done , false , false , { DD_TEST_MANAGEMENT_ENABLED : '0' } )
2687
+ } )
2688
+
2689
+ it ( 'does not fail retry if a test is quarantined' , ( done ) => {
2690
+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2691
+ receiver . setTestManagementTests ( {
2692
+ mocha : {
2693
+ suites : {
2694
+ 'ci-visibility/test-management/test-attempt-to-fix-1.js' : {
2695
+ tests : {
2696
+ 'attempt to fix tests can attempt to fix a test' : {
2697
+ properties : {
2698
+ attempt_to_fix : true ,
2699
+ quarantined : true
2700
+ }
2701
+ }
2702
+ }
2703
+ }
2704
+ }
2705
+ }
2706
+ } )
2707
+
2708
+ runAttemptToFixTest ( done , true , true )
2709
+ } )
2710
+ } )
2711
+
2569
2712
context ( 'disabled' , ( ) => {
2570
2713
beforeEach ( ( ) => {
2571
2714
receiver . setTestManagementTests ( {
0 commit comments