2 TestSCons.py: a testing framework for the SCons software construction
5 A TestSCons environment object is created via the usual invocation:
9 TestScons is a subclass of TestCmd, and hence has available all of its
10 methods and attributes, as well as any overridden or additional methods
11 or attributes defined in this subclass.
14 # Copyright 2001, 2002 Steven Knight
16 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25 class TestFailed(Exception):
26 def __init__(self, args=None):
29 class TestNoResult(Exception):
30 def __init__(self, args=None):
33 if os.name == 'posix':
34 def _failed(self, status = 0):
35 if self.status is None:
37 if os.WIFSIGNALED(status):
39 return _status(self) != status
41 if os.WIFEXITED(self.status):
42 return os.WEXITSTATUS(self.status)
46 def _failed(self, status = 0):
47 return not self.status is None and self.status != status
51 class TestSCons(TestCmd.TestCmd):
52 """Class for testing SCons.
54 This provides a common place for initializing SCons tests,
55 eliminating the need to begin every test with the same repeated
59 def __init__(self, **kw):
60 """Initialize an SCons testing object.
62 If they're not overridden by keyword arguments, this
63 initializes the object with the following default values:
65 program = 'scons' if it exists,
67 interpreter = 'python'
68 match = TestCmd.match_exact
71 The workdir value means that, by default, a temporary workspace
72 directory is created for a TestSCons environment. In addition,
73 this method changes directory (chdir) to the workspace directory,
74 so an explicit "chdir = '.'" on all of the run() method calls
77 if not kw.has_key('program'):
78 kw['program'] = os.environ.get('SCONS')
80 if os.path.exists('scons'):
81 kw['program'] = 'scons'
83 kw['program'] = 'scons.py'
84 if not kw.has_key('interpreter') and not os.environ.get('SCONS_EXEC'):
85 kw['interpreter'] = sys.executable
86 if not kw.has_key('match'):
87 kw['match'] = TestCmd.match_exact
88 if not kw.has_key('workdir'):
90 apply(TestCmd.TestCmd.__init__, [self], kw)
91 os.chdir(self.workdir)
93 def run(self, options = None, arguments = None,
94 stdout = None, stderr = '', status = 0, **kw):
97 This is the same as the base TestCmd.run() method, with
100 stdout The expected standard output from
101 the command. A value of None means
102 don't test standard output.
104 stderr The expected error output from
105 the command. A value of None means
106 don't test error output.
108 status The expected exit status from the
111 By default, this does not test standard output (stdout = None),
112 and expects that error output is empty (stderr = "").
115 arguments = options + " " + arguments
116 kw['arguments'] = arguments
118 apply(TestCmd.TestCmd.run, [self], kw)
120 print "STDOUT ============"
122 print "STDERR ============"
125 if _failed(self, status):
128 expect = " (expected %d)" % status
129 print "%s returned %d%s" % (self.program, _status(self), expect)
130 print "STDOUT ============"
132 print "STDERR ============"
135 if not stdout is None and not self.match(self.stdout(), stdout):
136 print "Expected STDOUT =========="
138 print "Actual STDOUT ============"
140 stderr = self.stderr()
142 print "STDERR ==================="
145 if not stderr is None and not self.match(self.stderr(), stderr):
146 print "STDOUT ==================="
148 print "Expected STDERR =========="
150 print "Actual STDERR ============"
154 def detect(self, var, prog):
156 Detect a program named 'prog' by first checking the construction
157 variable named 'var' and finally searching the path. If either method
158 fails to detect the program, then false is returned, otherwise
159 the programs full path is returned.
162 import SCons.Environment
164 return SCons.Environment.Environment()[var] == prog and self.where_is(prog)
168 def wrap_stdout(self, build_str = "", read_str = ""):
169 """Wraps standard output string(s) in the normal
170 "Reading ... done" and "Building ... done" strings
172 return "scons: Reading SConscript files ...\n" + \
174 "scons: done reading SConscript files.\n" + \
175 "scons: Building targets ...\n" + \
177 "scons: done building targets.\n"
179 def up_to_date(self, options = None, arguments = None, **kw):
181 for arg in string.split(arguments):
182 s = s + 'scons: "%s" is up to date.\n' % arg
184 arguments = options + " " + arguments
185 kw['arguments'] = arguments
186 kw['stdout'] = self.wrap_stdout(build_str = s)
187 apply(self.run, [], kw)