|
Testing
How to write tests for Software Construction Toolkit.
Contents
IntroductionThe testing infrastructure for the Software Construction Toolkit is built on the testing infrastructure for SCons. Since build tools are typically intertwined with their environment and external programs, the SCons infrastructure centers on end-to-end functional tests. We have extended the SCons infrastructure to enable both small tests and test coverage. Tests are located in the tests/ subdirectory.
RequirementsWriting and running Software Construction tests requires the following:
Set the following variables:
How to run testsTo run one test: bin/runtest.py test/<testname>.py To run all tests: bin/runtest.py -a By default, tests don't print much information. Run with --verbose=3 to dump more information: bin/runtest.py --verbose=3 test/<testname>.py Since tests clean up after themselves, you can't normally see what files were being generated. To stop runtest from doing this, add PRESERVE=1 to your shell environment before running the tests: export PRESERVE=1 bin/runtest.py test/<testname>.py or on Windows: set PRESERVE=1 bin\runtest.bat test/<testname>.py The test framework will then leave its temporary files, and will tell you where it put them.
How to add a testHere is the smallest functional test, broken down into sections: Standard python header, including docstring. #!/usr/bin/python2.4 """your_test_description""" All tests must import TestFramework. import TestFramework The SConscript file for your test is implemented in the test as a function. SCons globals that you need should be copied from the scons_globals dict. def TestSConstruct(scons_globals):
"""Test SConstruct file.
Args:
scons_globals: Global variables dict from the SConscript file.
"""
# Get globals from SCons
Environment = scons_globals['Environment']
# Construct the root environment
root_env = Environment(
tools=['component_setup'],
)
# The rest of your test would go hereThe main routine does the following:
def main():
test = TestFramework.TestFramework()
test.subdir('your_test_name')
base = 'your_test_name/'
test.WriteSConscript(base + 'SConstruct', TestSConstruct)
test.run(chdir=base)
test.pass_test()Python boilerplate to run main(). if __name__ == '__main__': main()
Test size definitionsTests are classified by size:
Example testThis is the previous example, combined for easier copy-pasting to get you started. #!/usr/bin/python2.4
"""your_test_description"""
import TestFramework
def TestSConstruct(scons_globals):
"""Test SConstruct file.
Args:
scons_globals: Global variables dict from the SConscript file.
"""
# Get globals from SCons
Environment = scons_globals['Environment']
# Construct the root environment
root_env = Environment(
tools=['component_setup'],
TOOL_ROOT=TestFramework.ToolRoot(),
)
# The rest of your test would go here
def main():
test = TestFramework.TestFramework()
test.subdir('your_test_name')
base = 'your_test_name/'
test.WriteSConscript(base + 'SConstruct', TestSConstruct)
test.run(chdir=base)
test.pass_test()
Using unittest to write small testsYou can also import the unittest module and write small tests inside your TestSConstruct function. #!/usr/bin/python2.4
"""Test for defer."""
import unittest
import SCons.Errors
import TestFramework
class DeferTests(unittest.TestCase):
"""Tests for defer module."""
def setUp(self):
"""Per-test setup."""
self.call_list = []
self.env = self.root_env.Clone()
def testDeferReentrancy(self):
"""Test re-entrant calls to ExecuteDefer()."""
def Sub1(env):
env.ExecuteDefer()
env = self.env
env.Defer(Sub1)
self.assertRaises(SCons.Errors.UserError, env.ExecuteDefer)
def TestSConstruct(scons_globals):
"""Test SConstruct file.
Args:
scons_globals: Global variables dict from the SConscript file.
"""
# Get globals from SCons
Environment = scons_globals['Environment']
env = Environment(tools=['environment_tools', 'defer'])
# Run unit tests
TestFramework.RunUnitTests(DeferTests, root_env=env)
def main():
test = TestFramework.TestFramework()
test.subdir('defer')
base = 'defer/'
test.WriteSConscript(base + 'SConstruct', TestSConstruct)
test.run(chdir=base, stderr=None)
test.pass_test()
if __name__ == '__main__':
main()
|