29
29
from io import StringIO
30
30
from pathlib import Path , PurePath , PureWindowsPath
31
31
from queue import Queue
32
- from typing import TextIO
33
32
34
33
cwd = os .getcwd ()
35
34
debug : str | None = None
@@ -575,38 +574,34 @@ def footer(self, f):
575
574
del os .environ ['_JAVA_OPTIONS' ]
576
575
577
576
578
- # ---[ test discovery ]------------------------------------
579
- # This section figures out which tests to run.
577
+ # ---[ Test Discovery ]------------------------------------
578
+ # This section determines which tests to run based on three
579
+ # mutually exclusive options:
580
+ # 1. Reading test paths from a testlist file (--file or --retry option)
581
+ # 2. Using test paths given as command line arguments
582
+ # 3. Automatically finding all tests (--all option)
580
583
#
581
- # The initial testlist is made by reading from the testlistfile,
582
- # if supplied, or by looking at the test arguments, if supplied,
583
- # or by looking for all test files if the "all" argument is supplied.
584
- # One of the three is required.
584
+ # Test paths can specify either individual test files, or directories to
585
+ # scan for tests. The following test types are recognized:
585
586
#
586
- # Each test path, whichever of the three sources it comes from,
587
- # specifies either a test file or a directory to search for
588
- # SCons tests. SCons code layout assumes that any file under the 'SCons'
589
- # subdirectory that ends with 'Tests.py' is a unit test, and any Python
590
- # script (*.py) under the 'test' subdirectory is an end-to-end test.
591
- # We need to track these because they are invoked differently.
592
- # find_unit_tests and find_e2e_tests are used for this searching.
587
+ # - Unit tests: Files ending in 'Tests.py' under the 'SCons' directory
588
+ # - End-to-end tests: Python scripts (*.py) under the 'test' directory
589
+ # - External tests: End-to-end tests in paths containing a 'test'
590
+ # component (not expected to be local)
593
591
#
594
- # Note that there are some tests under 'SCons' that *begin* with
595
- # 'test_', but they're packaging and installation tests, not
596
- # functional tests, so we don't execute them by default. (They can
597
- # still be executed by hand, though).
592
+ # find_unit_tests() and find_e2e_tests() perform the directory scanning.
598
593
#
599
- # Test exclusions, if specified, are then applied.
600
-
594
+ # After the initial test list is built, any test exclusions specified via
595
+ # --exclude-list are applied to produce the final test set.
601
596
602
597
def scanlist (testfile ):
603
598
""" Process a testlist file """
604
599
data = StringIO (testfile .read_text ())
605
600
tests = [t .strip () for t in data .readlines () if not t .startswith ('#' )]
606
601
# in order to allow scanned lists to work whether they use forward or
607
- # backward slashes, first create the object as a PureWindowsPath which
608
- # accepts either, then use that to make a Path object to use for
609
- # comparisons like "file in scanned_list".
602
+ # backward slashes, on non-Windows first create the object as a
603
+ # PureWindowsPath which accepts either, then use that to make a Path
604
+ # object for use in comparisons like "if file in scanned_list".
610
605
if sys .platform == 'win32' :
611
606
return [Path (t ) for t in tests if t ]
612
607
else :
@@ -635,7 +630,7 @@ def find_e2e_tests(directory):
635
630
if 'sconstest.skip' in filenames :
636
631
continue
637
632
638
- # Slurp in any tests in exclude lists
633
+ # Gather up the data from any exclude lists
639
634
excludes = []
640
635
if ".exclude_tests" in filenames :
641
636
excludefile = Path (dirpath , ".exclude_tests" ).resolve ()
@@ -648,8 +643,7 @@ def find_e2e_tests(directory):
648
643
return sorted (result )
649
644
650
645
651
- # initial selection:
652
- # if we have a testlist file read that, else hunt for tests.
646
+ # Initial test selection:
653
647
unittests = []
654
648
endtests = []
655
649
if args .testlistfile :
@@ -668,15 +662,16 @@ def find_e2e_tests(directory):
668
662
# Clean up path removing leading ./ or .\
669
663
name = str (path )
670
664
if name .startswith ('.' ) and name [1 ] in (os .sep , os .altsep ):
671
- path = path .with_name (tn [2 :])
665
+ path = path .with_name (name [2 :])
672
666
673
667
if path .exists ():
674
668
if path .is_dir ():
675
669
if path .parts [0 ] == "SCons" or path .parts [0 ] == "testing" :
676
670
unittests .extend (find_unit_tests (path ))
677
671
elif path .parts [0 ] == 'test' :
678
672
endtests .extend (find_e2e_tests (path ))
679
- # else: TODO: what if user pointed to a dir outside scons tree?
673
+ elif args .external and 'test' in path .parts :
674
+ endtests .extend (find_e2e_tests (path ))
680
675
else :
681
676
if path .match ("*Tests.py" ):
682
677
unittests .append (path )
@@ -703,7 +698,7 @@ def find_e2e_tests(directory):
703
698
""" )
704
699
sys .exit (1 )
705
700
706
- # ---[ test processing ]-----------------------------------
701
+ # ---[ Test Processing ]-----------------------------------
707
702
tests = [Test (t ) for t in tests ]
708
703
709
704
if args .list_only :
@@ -826,10 +821,11 @@ def run_test(t, io_lock=None, run_async=True):
826
821
827
822
828
823
class RunTest (threading .Thread ):
829
- """ Test Runner class .
824
+ """Test Runner thread .
830
825
831
- One instance will be created for each job thread in multi-job mode
826
+ One will be created for each job in multi-job mode
832
827
"""
828
+
833
829
def __init__ (self , queue = None , io_lock = None , group = None , target = None , name = None ):
834
830
super ().__init__ (group = group , target = target , name = name )
835
831
self .queue = queue
0 commit comments