@@ -377,19 +377,19 @@ def parse_executed_tests(self, output):
377
377
return list (match .group (1 ) for match in parser )
378
378
379
379
def check_executed_tests (self , output , tests , skipped = (), failed = (),
380
- omitted = (), randomize = False , interrupted = False ):
380
+ env_changed = (), omitted = (),
381
+ randomize = False , interrupted = False ,
382
+ fail_env_changed = False ):
381
383
if isinstance (tests , str ):
382
384
tests = [tests ]
383
385
if isinstance (skipped , str ):
384
386
skipped = [skipped ]
385
387
if isinstance (failed , str ):
386
388
failed = [failed ]
389
+ if isinstance (env_changed , str ):
390
+ env_changed = [env_changed ]
387
391
if isinstance (omitted , str ):
388
392
omitted = [omitted ]
389
- ntest = len (tests )
390
- nskipped = len (skipped )
391
- nfailed = len (failed )
392
- nomitted = len (omitted )
393
393
394
394
executed = self .parse_executed_tests (output )
395
395
if randomize :
@@ -415,11 +415,17 @@ def list_regex(line_format, tests):
415
415
regex = list_regex ('%s test%s failed' , failed )
416
416
self .check_line (output , regex )
417
417
418
+ if env_changed :
419
+ regex = list_regex ('%s test%s altered the execution environment' ,
420
+ env_changed )
421
+ self .check_line (output , regex )
422
+
418
423
if omitted :
419
424
regex = list_regex ('%s test%s omitted' , omitted )
420
425
self .check_line (output , regex )
421
426
422
- good = ntest - nskipped - nfailed - nomitted
427
+ good = (len (tests ) - len (skipped ) - len (failed )
428
+ - len (omitted ) - len (env_changed ))
423
429
if good :
424
430
regex = r'%s test%s OK\.$' % (good , plural (good ))
425
431
if not skipped and not failed and good > 1 :
@@ -429,10 +435,12 @@ def list_regex(line_format, tests):
429
435
if interrupted :
430
436
self .check_line (output , 'Test suite interrupted by signal SIGINT.' )
431
437
432
- if nfailed :
438
+ if failed :
433
439
result = 'FAILURE'
434
440
elif interrupted :
435
441
result = 'INTERRUPTED'
442
+ elif fail_env_changed and env_changed :
443
+ result = 'ENV CHANGED'
436
444
else :
437
445
result = 'SUCCESS'
438
446
self .check_line (output , 'Tests result: %s' % result )
@@ -604,7 +612,7 @@ def test_failing(self):
604
612
test_failing = self .create_test ('failing' , code = code )
605
613
tests = [test_ok , test_failing ]
606
614
607
- output = self .run_tests (* tests , exitcode = 1 )
615
+ output = self .run_tests (* tests , exitcode = 2 )
608
616
self .check_executed_tests (output , tests , failed = test_failing )
609
617
610
618
def test_resources (self ):
@@ -703,7 +711,7 @@ def test_fromfile(self):
703
711
def test_interrupted (self ):
704
712
code = TEST_INTERRUPTED
705
713
test = self .create_test ('sigint' , code = code )
706
- output = self .run_tests (test , exitcode = 1 )
714
+ output = self .run_tests (test , exitcode = 130 )
707
715
self .check_executed_tests (output , test , omitted = test ,
708
716
interrupted = True )
709
717
@@ -732,7 +740,7 @@ def test_slow_interrupted(self):
732
740
args = ("--slowest" , "-j2" , test )
733
741
else :
734
742
args = ("--slowest" , test )
735
- output = self .run_tests (* args , exitcode = 1 )
743
+ output = self .run_tests (* args , exitcode = 130 )
736
744
self .check_executed_tests (output , test ,
737
745
omitted = test , interrupted = True )
738
746
@@ -772,9 +780,43 @@ def test_run(self):
772
780
builtins.__dict__['RUN'] = 1
773
781
""" )
774
782
test = self .create_test ('forever' , code = code )
775
- output = self .run_tests ('--forever' , test , exitcode = 1 )
783
+ output = self .run_tests ('--forever' , test , exitcode = 2 )
776
784
self .check_executed_tests (output , [test ]* 3 , failed = test )
777
785
786
+ def check_leak (self , code , what ):
787
+ test = self .create_test ('huntrleaks' , code = code )
788
+
789
+ filename = 'reflog.txt'
790
+ self .addCleanup (support .unlink , filename )
791
+ output = self .run_tests ('--huntrleaks' , '3:3:' , test ,
792
+ exitcode = 2 ,
793
+ stderr = subprocess .STDOUT )
794
+ self .check_executed_tests (output , [test ], failed = test )
795
+
796
+ line = 'beginning 6 repetitions\n 123456\n ......\n '
797
+ self .check_line (output , re .escape (line ))
798
+
799
+ line2 = '%s leaked [1, 1, 1] %s, sum=3\n ' % (test , what )
800
+ self .assertIn (line2 , output )
801
+
802
+ with open (filename ) as fp :
803
+ reflog = fp .read ()
804
+ self .assertIn (line2 , reflog )
805
+
806
+ @unittest .skipUnless (Py_DEBUG , 'need a debug build' )
807
+ def test_huntrleaks (self ):
808
+ # test --huntrleaks
809
+ code = textwrap .dedent ("""
810
+ import unittest
811
+
812
+ GLOBAL_LIST = []
813
+
814
+ class RefLeakTest(unittest.TestCase):
815
+ def test_leak(self):
816
+ GLOBAL_LIST.append(object())
817
+ """ )
818
+ self .check_leak (code , 'references' )
819
+
778
820
@unittest .skipUnless (Py_DEBUG , 'need a debug build' )
779
821
def test_huntrleaks_fd_leak (self ):
780
822
# test --huntrleaks for file descriptor leak
@@ -799,24 +841,7 @@ def test_leak(self):
799
841
fd = os.open(__file__, os.O_RDONLY)
800
842
# bug: never cloes the file descriptor
801
843
""" )
802
- test = self .create_test ('huntrleaks' , code = code )
803
-
804
- filename = 'reflog.txt'
805
- self .addCleanup (support .unlink , filename )
806
- output = self .run_tests ('--huntrleaks' , '3:3:' , test ,
807
- exitcode = 1 ,
808
- stderr = subprocess .STDOUT )
809
- self .check_executed_tests (output , [test ], failed = test )
810
-
811
- line = 'beginning 6 repetitions\n 123456\n ......\n '
812
- self .check_line (output , re .escape (line ))
813
-
814
- line2 = '%s leaked [1, 1, 1] file descriptors, sum=3\n ' % test
815
- self .assertIn (line2 , output )
816
-
817
- with open (filename ) as fp :
818
- reflog = fp .read ()
819
- self .assertIn (line2 , reflog )
844
+ self .check_leak (code , 'file descriptors' )
820
845
821
846
def test_list_tests (self ):
822
847
# test --list-tests
@@ -837,19 +862,28 @@ def test_method2(self):
837
862
pass
838
863
""" )
839
864
testname = self .create_test (code = code )
865
+
866
+ # Test --list-cases
840
867
all_methods = ['%s.Tests.test_method1' % testname ,
841
868
'%s.Tests.test_method2' % testname ]
842
869
output = self .run_tests ('--list-cases' , testname )
843
870
self .assertEqual (output .splitlines (), all_methods )
844
871
872
+ # Test --list-cases with --match
873
+ all_methods = ['%s.Tests.test_method1' % testname ]
874
+ output = self .run_tests ('--list-cases' ,
875
+ '-m' , 'test_method1' ,
876
+ testname )
877
+ self .assertEqual (output .splitlines (), all_methods )
878
+
845
879
def test_crashed (self ):
846
880
# Any code which causes a crash
847
881
code = 'import faulthandler; faulthandler._sigsegv()'
848
882
crash_test = self .create_test (name = "crash" , code = code )
849
883
ok_test = self .create_test (name = "ok" )
850
884
851
885
tests = [crash_test , ok_test ]
852
- output = self .run_tests ("-j2" , * tests , exitcode = 1 )
886
+ output = self .run_tests ("-j2" , * tests , exitcode = 2 )
853
887
self .check_executed_tests (output , tests , failed = crash_test ,
854
888
randomize = True )
855
889
@@ -898,6 +932,25 @@ def test_method4(self):
898
932
subset = ['test_method1' , 'test_method3' ]
899
933
self .assertEqual (methods , subset )
900
934
935
+ def test_env_changed (self ):
936
+ code = textwrap .dedent ("""
937
+ import unittest
938
+
939
+ class Tests(unittest.TestCase):
940
+ def test_env_changed(self):
941
+ open("env_changed", "w").close()
942
+ """ )
943
+ testname = self .create_test (code = code )
944
+
945
+ # don't fail by default
946
+ output = self .run_tests (testname )
947
+ self .check_executed_tests (output , [testname ], env_changed = testname )
948
+
949
+ # fail with --fail-env-changed
950
+ output = self .run_tests ("--fail-env-changed" , testname , exitcode = 3 )
951
+ self .check_executed_tests (output , [testname ], env_changed = testname ,
952
+ fail_env_changed = True )
953
+
901
954
902
955
if __name__ == '__main__' :
903
956
unittest .main ()
0 commit comments