@@ -1413,6 +1413,129 @@ action.surefire.report.email.InvalidEmailAddressException: Invalid email address
14131413 }
14141414 ] )
14151415 } )
1416+
1417+ it ( 'flaky test with classname and file: multiple failures then success should pass with retries' , async ( ) => {
1418+ // Test that flaky tests are correctly identified using classname and file as part of the key
1419+ // The test_foo test appears 3 times: failure, error, then success
1420+ // It should be marked as success with 2 retries
1421+ const testResult = await parseFile (
1422+ 'test_results/flaky_retries/flaky_with_classname_file.xml' ,
1423+ '' ,
1424+ true , // includePassed
1425+ true , // annotateNotice
1426+ true // checkRetries
1427+ )
1428+ expect ( testResult ) . toBeDefined ( )
1429+ const { totalCount, skippedCount, failedCount, passedCount, retriedCount, globalAnnotations} = testResult ! !
1430+
1431+ // Should have 3 unique tests (test_foo appears once due to deduplication, plus test_bar.test_foo and test_baz)
1432+ expect ( totalCount ) . toBe ( 3 )
1433+ expect ( skippedCount ) . toBe ( 0 )
1434+ expect ( failedCount ) . toBe ( 0 )
1435+ expect ( passedCount ) . toBe ( 3 )
1436+ expect ( retriedCount ) . toBe ( 2 ) // 2 retries for the flaky test (3 occurrences - 1)
1437+
1438+ // Find the flaky test annotation
1439+ const flakyTest = globalAnnotations . find ( a =>
1440+ a . title . includes ( 'test_foo.TestFoo' ) || a . path . includes ( 'test_foo.py' )
1441+ )
1442+ expect ( flakyTest ) . toBeDefined ( )
1443+ expect ( flakyTest ! . status ) . toBe ( 'success' )
1444+ expect ( flakyTest ! . retries ) . toBe ( 2 )
1445+ expect ( flakyTest ! . annotation_level ) . toBe ( 'notice' )
1446+
1447+ // Verify that test_bar.test_foo is NOT merged with test_foo.test_foo (different classname/file)
1448+ const testBarFoo = globalAnnotations . find ( a => a . path . includes ( 'test_bar.py' ) )
1449+ expect ( testBarFoo ) . toBeDefined ( )
1450+ expect ( testBarFoo ! . retries ) . toBe ( 0 ) // Not retried, it's a separate test
1451+ } )
1452+
1453+ it ( 'flaky test with all failures should still be marked as failure with retries' , async ( ) => {
1454+ // Test that when all executions of a flaky test fail, it remains a failure but tracks retries
1455+ const testResult = await parseFile (
1456+ 'test_results/flaky_retries/flaky_all_failures.xml' ,
1457+ '' ,
1458+ false , // includePassed
1459+ false , // annotateNotice
1460+ true // checkRetries
1461+ )
1462+ expect ( testResult ) . toBeDefined ( )
1463+ const { totalCount, skippedCount, failedCount, passedCount, retriedCount, globalAnnotations} = testResult ! !
1464+
1465+ // Should have 1 unique test after deduplication
1466+ expect ( totalCount ) . toBe ( 1 )
1467+ expect ( skippedCount ) . toBe ( 0 )
1468+ expect ( failedCount ) . toBe ( 1 )
1469+ expect ( passedCount ) . toBe ( 0 )
1470+ expect ( retriedCount ) . toBe ( 2 ) // 2 retries (3 occurrences - 1)
1471+
1472+ // Should still have a failure annotation
1473+ expect ( globalAnnotations ) . toHaveLength ( 1 )
1474+ expect ( globalAnnotations [ 0 ] . status ) . toBe ( 'failure' )
1475+ expect ( globalAnnotations [ 0 ] . retries ) . toBe ( 2 )
1476+ expect ( globalAnnotations [ 0 ] . annotation_level ) . toBe ( 'failure' )
1477+ } )
1478+
1479+ it ( 'flaky test with success first should still pass with retries tracked' , async ( ) => {
1480+ // Test that even if success comes first and failures come later,
1481+ // the test is still marked as success with proper retry count
1482+ const testResult = await parseFile (
1483+ 'test_results/flaky_retries/flaky_success_first.xml' ,
1484+ '' ,
1485+ true , // includePassed
1486+ true , // annotateNotice
1487+ true // checkRetries
1488+ )
1489+ expect ( testResult ) . toBeDefined ( )
1490+ const { totalCount, skippedCount, failedCount, passedCount, retriedCount, globalAnnotations} = testResult ! !
1491+
1492+ // Should have 1 unique test after deduplication
1493+ expect ( totalCount ) . toBe ( 1 )
1494+ expect ( skippedCount ) . toBe ( 0 )
1495+ expect ( failedCount ) . toBe ( 0 )
1496+ expect ( passedCount ) . toBe ( 1 )
1497+ expect ( retriedCount ) . toBe ( 2 ) // 2 retries (3 occurrences - 1)
1498+
1499+ // Should be marked as success
1500+ expect ( globalAnnotations ) . toHaveLength ( 1 )
1501+ expect ( globalAnnotations [ 0 ] . status ) . toBe ( 'success' )
1502+ expect ( globalAnnotations [ 0 ] . retries ) . toBe ( 2 )
1503+ expect ( globalAnnotations [ 0 ] . annotation_level ) . toBe ( 'notice' )
1504+ } )
1505+
1506+ it ( 'same test name but different classname/file should NOT be merged' , async ( ) => {
1507+ // Verify that tests with the same name but different classname or file are treated as separate tests
1508+ const testResult = await parseFile (
1509+ 'test_results/flaky_retries/flaky_with_classname_file.xml' ,
1510+ '' ,
1511+ true , // includePassed
1512+ true , // annotateNotice
1513+ true // checkRetries
1514+ )
1515+ expect ( testResult ) . toBeDefined ( )
1516+ const { totalCount, globalAnnotations} = testResult ! !
1517+
1518+ // Should have 3 unique tests:
1519+ // 1. test_foo from test_foo.TestFoo (flaky, merged)
1520+ // 2. test_foo from test_bar.TestBar (separate)
1521+ // 3. test_baz from test_baz.TestBaz
1522+ expect ( totalCount ) . toBe ( 3 )
1523+ expect ( globalAnnotations ) . toHaveLength ( 3 )
1524+
1525+ // Verify we have two different test_foo entries (one from each classname)
1526+ const testFooAnnotations = globalAnnotations . filter ( a => a . title . includes ( 'test_foo' ) )
1527+ expect ( testFooAnnotations ) . toHaveLength ( 2 )
1528+
1529+ // The one from TestFoo should have retries, the one from TestBar should not
1530+ const testFooFromTestFoo = testFooAnnotations . find ( a => a . path . includes ( 'test_foo.py' ) )
1531+ const testFooFromTestBar = testFooAnnotations . find ( a => a . path . includes ( 'test_bar.py' ) )
1532+
1533+ expect ( testFooFromTestFoo ) . toBeDefined ( )
1534+ expect ( testFooFromTestFoo ! . retries ) . toBe ( 2 )
1535+
1536+ expect ( testFooFromTestBar ) . toBeDefined ( )
1537+ expect ( testFooFromTestBar ! . retries ) . toBe ( 0 )
1538+ } )
14161539} )
14171540
14181541describe ( 'parseTestReports' , ( ) => {
0 commit comments