|
UnitTesting
IntroductionThe majority of the Python code used by this framework, is not loaded through the Python module and package system. Instead, it is loaded through the code reloading framework which as described in the CodeReloading wiki page, automatically puts code changes in place. Before any of the code can be used, the code reloading system needs to go through process of starting up, where it loads all the scripts it manages into memory. During this process scripts that depend on others that are not yet loaded are set aside and processed later. Eventually, either the game starts up after scripts are retried as their dependencies become available, or dependencies are simply not present and the game does not start up. The important thing to take away from this is that scripts cannot be tested in isolation because they are part of a whole. If they are to be tested, it needs to be after the code reloading system has gone through the script loading and dependency resolution process. Script LoadingWhen a script is successfully loaded by the code reloading system, it can be unit tested before its contents are put into place. The code reloading system looks for unit tests to run in two different places. The first place is within the script itself and the second place is in a secondary file named in a particlar fashion. Inline TestsTests within a loaded script are easily identified because they are expected to be subclasses of unittest.TestCase. The code reloading system simply iterates through the contents of the freshly loaded script and extracts these subclasses. import unittest
# Main script contents go here.
if False:
class TestSupportClass:
pass
class ATestCase(unittest.TestCase):
def setUp(self):
pass
def testSomething(self):
self.failUnless("TestSupportClass" not in globals(), "Get that shit out of here")Note: Any supporting objects at the top-level of the script that are for the use of test cases will be exported from the script as objects that can be imported from its namespace. An example of this would be if the if False: above were removed. If you require these objects, seriously consider using external test files instead. External Test FilesThe code reloading system takes the name of the script that was loaded, and inserts _unittest before the .py suffix. So for a script names user.py, the code reloading system would have an external unit test filename of user_unittest.py. If this file exists in the same directory as the script it relates to, then it is loaded and tests are extracted from it. import unittest
someValue = 1
def AFunction():
print "ding dong"
class ATestCase(unittest.TestCase):
def setUp(self):
pass
def testSomething(self):
AFunction()
self.failUnless(someValue == 1)The advantage of this approach is that supporting values or objects added at the top-level of the test script to support the tests, do not polute the namespaces the real script is exported to. The contents of a test script are not added to the script they test. |