@@ -473,3 +473,110 @@ def assert_tracking_count(self, tracking, count: int):
473473 if attempt > 10 :
474474 break
475475 self .assertEqual (tracking .call_count , count )
476+
477+
478+ class FallbackModeTest (CliTestCase ):
479+ test_files_dir = Path (__file__ ).parent .joinpath ('../data/minitest/' ).resolve ()
480+
481+ def _subset_args (self , rest_file_name , extra_args = ()):
482+ return (
483+ "subset" , "--target" , "50%" ,
484+ "--session" , self .session ,
485+ "--rest" , rest_file_name ,
486+ ) + tuple (extra_args ) + (
487+ "minitest" ,
488+ str (self .test_files_dir ) + "/test/**/*.rb" ,
489+ )
490+
491+ # --- API error cases ---
492+
493+ @responses .activate
494+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
495+ def test_api_error_fallback_stop (self ):
496+ responses .replace (
497+ responses .POST ,
498+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
499+ base = get_base_url (), org = self .organization , ws = self .workspace ),
500+ status = 500 )
501+
502+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
503+ result = self .cli (* self ._subset_args (rest_file .name , ("--fallback-mode" , "stop" )), mix_stderr = False )
504+ self .assertEqual (result .exit_code , 1 )
505+
506+ @responses .activate
507+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
508+ def test_api_error_fallback_random_sample (self ):
509+ responses .replace (
510+ responses .POST ,
511+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
512+ base = get_base_url (), org = self .organization , ws = self .workspace ),
513+ status = 500 )
514+
515+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
516+ result = self .cli (* self ._subset_args (rest_file .name , ("--fallback-mode" , "random-sample" )), mix_stderr = False )
517+ self .assert_success (result )
518+ self .assertIn ("example_test.rb" , result .stdout )
519+
520+ @responses .activate
521+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
522+ def test_api_error_fallback_run_all_default (self ):
523+ responses .replace (
524+ responses .POST ,
525+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
526+ base = get_base_url (), org = self .organization , ws = self .workspace ),
527+ status = 500 )
528+
529+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
530+ result = self .cli (* self ._subset_args (rest_file .name ), mix_stderr = False )
531+ self .assert_success (result )
532+ self .assertIn ("example_test.rb" , result .stdout )
533+
534+ # --- Brainless mode cases ---
535+
536+ @responses .activate
537+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
538+ def test_brainless_fallback_stop (self ):
539+ responses .replace (
540+ responses .POST ,
541+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
542+ base = get_base_url (), org = self .organization , ws = self .workspace ),
543+ json = {"testPaths" : [[{"type" : "file" , "name" : "example_test.rb" }]],
544+ "rest" : [], "subsettingId" : 1 , "isBrainless" : True , "summary" : {}},
545+ status = 200 )
546+
547+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
548+ result = self .cli (* self ._subset_args (rest_file .name , ("--fallback-mode" , "stop" )), mix_stderr = False )
549+ self .assertEqual (result .exit_code , 1 )
550+
551+ @responses .activate
552+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
553+ def test_brainless_fallback_random_sample (self ):
554+ # In brainless mode the server already split the tests, so random-sample keeps the server's result as-is.
555+ responses .replace (
556+ responses .POST ,
557+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
558+ base = get_base_url (), org = self .organization , ws = self .workspace ),
559+ json = {"testPaths" : [[{"type" : "file" , "name" : "example_test.rb" }]],
560+ "rest" : [], "subsettingId" : 1 , "isBrainless" : True , "summary" : {}},
561+ status = 200 )
562+
563+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
564+ result = self .cli (* self ._subset_args (rest_file .name , ("--fallback-mode" , "random-sample" )), mix_stderr = False )
565+ self .assert_success (result )
566+ self .assertIn ("example_test.rb" , result .stdout )
567+
568+ @responses .activate
569+ @mock .patch .dict (os .environ , {"LAUNCHABLE_TOKEN" : CliTestCase .launchable_token })
570+ def test_brainless_fallback_run_all_default (self ):
571+ responses .replace (
572+ responses .POST ,
573+ "{base}/intake/organizations/{org}/workspaces/{ws}/subset" .format (
574+ base = get_base_url (), org = self .organization , ws = self .workspace ),
575+ json = {"testPaths" : [[{"type" : "file" , "name" : "example_test.rb" }]],
576+ "rest" : [], "subsettingId" : 1 , "isBrainless" : True , "summary" : {}},
577+ status = 200 )
578+
579+ with tempfile .NamedTemporaryFile (delete = False ) as rest_file :
580+ result = self .cli (* self ._subset_args (rest_file .name ), mix_stderr = False )
581+ self .assert_success (result )
582+ self .assertIn ("example_test.rb" , result .stdout )
0 commit comments