@@ -49,7 +49,10 @@ const {
4949 TEST_MANAGEMENT_IS_DISABLED ,
5050 DD_CAPABILITIES_TEST_IMPACT_ANALYSIS ,
5151 DD_CAPABILITIES_EARLY_FLAKE_DETECTION ,
52- DD_CAPABILITIES_AUTO_TEST_RETRIES
52+ DD_CAPABILITIES_AUTO_TEST_RETRIES ,
53+ TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX ,
54+ TEST_HAS_FAILED_ALL_RETRIES ,
55+ TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED
5356} = require ( '../../packages/dd-trace/src/plugins/util/test' )
5457const { DD_HOST_CPU_COUNT } = require ( '../../packages/dd-trace/src/plugins/util/env' )
5558
@@ -2031,6 +2034,229 @@ versions.forEach(version => {
20312034 } )
20322035
20332036 context ( 'test management' , ( ) => {
2037+ context ( 'attempt to fix' , ( ) => {
2038+ beforeEach ( ( ) => {
2039+ receiver . setTestManagementTests ( {
2040+ cucumber : {
2041+ suites : {
2042+ 'ci-visibility/features-test-management/attempt-to-fix.feature' : {
2043+ tests : {
2044+ 'Say attempt to fix' : {
2045+ properties : {
2046+ attempt_to_fix : true
2047+ }
2048+ }
2049+ }
2050+ }
2051+ }
2052+ }
2053+ } )
2054+ } )
2055+
2056+ const getTestAssertions = ( {
2057+ isAttemptToFix,
2058+ isQuarantined,
2059+ isDisabled,
2060+ shouldAlwaysPass,
2061+ shouldFailSometimes
2062+ } ) =>
2063+ receiver
2064+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
2065+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
2066+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
2067+ const testSession = events . find ( event => event . type === 'test_session_end' ) . content
2068+
2069+ if ( isAttemptToFix ) {
2070+ assert . propertyVal ( testSession . meta , TEST_MANAGEMENT_ENABLED , 'true' )
2071+ } else {
2072+ assert . notProperty ( testSession . meta , TEST_MANAGEMENT_ENABLED )
2073+ }
2074+
2075+ const retriedTests = tests . filter (
2076+ test => test . meta [ TEST_NAME ] === 'Say attempt to fix'
2077+ )
2078+
2079+ if ( isAttemptToFix ) {
2080+ // 3 retries + 1 initial run
2081+ assert . equal ( retriedTests . length , 4 )
2082+ } else {
2083+ assert . equal ( retriedTests . length , 1 )
2084+ }
2085+
2086+ for ( let i = 0 ; i < retriedTests . length ; i ++ ) {
2087+ const isFirstAttempt = i === 0
2088+ const isLastAttempt = i === retriedTests . length - 1
2089+ const test = retriedTests [ i ]
2090+
2091+ assert . equal (
2092+ test . resource ,
2093+ 'ci-visibility/features-test-management/attempt-to-fix.feature.Say attempt to fix'
2094+ )
2095+
2096+ if ( isDisabled ) {
2097+ assert . propertyVal ( test . meta , TEST_MANAGEMENT_IS_DISABLED , 'true' )
2098+ } else if ( isQuarantined ) {
2099+ assert . propertyVal ( test . meta , TEST_MANAGEMENT_IS_QUARANTINED , 'true' )
2100+ } else {
2101+ assert . notProperty ( test . meta , TEST_MANAGEMENT_IS_DISABLED )
2102+ assert . notProperty ( test . meta , TEST_MANAGEMENT_IS_QUARANTINED )
2103+ }
2104+
2105+ if ( isAttemptToFix ) {
2106+ assert . propertyVal ( test . meta , TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX , 'true' )
2107+ if ( ! isFirstAttempt ) {
2108+ assert . propertyVal ( test . meta , TEST_IS_RETRY , 'true' )
2109+ assert . propertyVal ( test . meta , TEST_RETRY_REASON , 'attempt_to_fix' )
2110+ }
2111+ if ( isLastAttempt ) {
2112+ if ( shouldFailSometimes ) {
2113+ assert . notProperty ( test . meta , TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED )
2114+ assert . notProperty ( test . meta , TEST_HAS_FAILED_ALL_RETRIES )
2115+ } else if ( shouldAlwaysPass ) {
2116+ assert . propertyVal ( test . meta , TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED , 'true' )
2117+ } else {
2118+ assert . propertyVal ( test . meta , TEST_HAS_FAILED_ALL_RETRIES , 'true' )
2119+ }
2120+ }
2121+ } else {
2122+ assert . notProperty ( test . meta , TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX )
2123+ assert . notProperty ( test . meta , TEST_IS_RETRY )
2124+ assert . notProperty ( test . meta , TEST_RETRY_REASON )
2125+ }
2126+ }
2127+ } )
2128+
2129+ const runTest = ( done , {
2130+ isAttemptToFix,
2131+ isQuarantined,
2132+ isDisabled,
2133+ extraEnvVars,
2134+ shouldAlwaysPass,
2135+ shouldFailSometimes
2136+ } = { } ) => {
2137+ const testAssertions = getTestAssertions ( {
2138+ isAttemptToFix,
2139+ isQuarantined,
2140+ isDisabled,
2141+ shouldAlwaysPass,
2142+ shouldFailSometimes
2143+ } )
2144+ let stdout = ''
2145+
2146+ childProcess = exec (
2147+ './node_modules/.bin/cucumber-js ci-visibility/features-test-management/attempt-to-fix.feature' ,
2148+ {
2149+ cwd,
2150+ env : {
2151+ ...getCiVisAgentlessConfig ( receiver . port ) ,
2152+ ...extraEnvVars ,
2153+ ...( shouldAlwaysPass ? { SHOULD_ALWAYS_PASS : '1' } : { } ) ,
2154+ ...( shouldFailSometimes ? { SHOULD_FAIL_SOMETIMES : '1' } : { } )
2155+ } ,
2156+ stdio : 'inherit'
2157+ }
2158+ )
2159+
2160+ childProcess . stdout . on ( 'data' , ( data ) => {
2161+ stdout += data . toString ( )
2162+ } )
2163+
2164+ childProcess . on ( 'exit' , exitCode => {
2165+ testAssertions . then ( ( ) => {
2166+ assert . include ( stdout , 'I am running' )
2167+ if ( isQuarantined || isDisabled || shouldAlwaysPass ) {
2168+ assert . equal ( exitCode , 0 )
2169+ } else {
2170+ assert . equal ( exitCode , 1 )
2171+ }
2172+ done ( )
2173+ } ) . catch ( done )
2174+ } )
2175+ }
2176+
2177+ it ( 'can attempt to fix and mark last attempt as failed if every attempt fails' , ( done ) => {
2178+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2179+
2180+ runTest ( done , { isAttemptToFix : true } )
2181+ } )
2182+
2183+ it ( 'can attempt to fix and mark last attempt as passed if every attempt passes' , ( done ) => {
2184+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2185+
2186+ runTest ( done , { isAttemptToFix : true , shouldAlwaysPass : true } )
2187+ } )
2188+
2189+ it ( 'can attempt to fix and not mark last attempt if attempts both pass and fail' , ( done ) => {
2190+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2191+
2192+ runTest ( done , { isAttemptToFix : true , shouldFailSometimes : true } )
2193+ } )
2194+
2195+ it ( 'does not attempt to fix tests if test management is not enabled' , ( done ) => {
2196+ receiver . setSettings ( { test_management : { enabled : false , attempt_to_fix_retries : 3 } } )
2197+
2198+ runTest ( done )
2199+ } )
2200+
2201+ it ( 'does not enable attempt to fix tests if DD_TEST_MANAGEMENT_ENABLED is set to false' , ( done ) => {
2202+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2203+
2204+ runTest ( done , {
2205+ extraEnvVars : { DD_TEST_MANAGEMENT_ENABLED : '0' }
2206+ } )
2207+ } )
2208+
2209+ it ( 'does not fail retry if a test is quarantined' , ( done ) => {
2210+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2211+ receiver . setTestManagementTests ( {
2212+ cucumber : {
2213+ suites : {
2214+ 'ci-visibility/features-test-management/attempt-to-fix.feature' : {
2215+ tests : {
2216+ 'Say attempt to fix' : {
2217+ properties : {
2218+ attempt_to_fix : true ,
2219+ quarantined : true
2220+ }
2221+ }
2222+ }
2223+ }
2224+ }
2225+ }
2226+ } )
2227+
2228+ runTest ( done , {
2229+ isAttemptToFix : true ,
2230+ isQuarantined : true
2231+ } )
2232+ } )
2233+
2234+ it ( 'does not fail retry if a test is disabled' , ( done ) => {
2235+ receiver . setSettings ( { test_management : { enabled : true , attempt_to_fix_retries : 3 } } )
2236+ receiver . setTestManagementTests ( {
2237+ cucumber : {
2238+ suites : {
2239+ 'ci-visibility/features-test-management/attempt-to-fix.feature' : {
2240+ tests : {
2241+ 'Say attempt to fix' : {
2242+ properties : {
2243+ attempt_to_fix : true ,
2244+ disabled : true
2245+ }
2246+ }
2247+ }
2248+ }
2249+ }
2250+ }
2251+ } )
2252+
2253+ runTest ( done , {
2254+ isAttemptToFix : true ,
2255+ isDisabled : true
2256+ } )
2257+ } )
2258+ } )
2259+
20342260 context ( 'disabled' , ( ) => {
20352261 beforeEach ( ( ) => {
20362262 receiver . setTestManagementTests ( {
0 commit comments