Included gomill framework for SGF and GTP support, and sketched out SGF game-loading code.
This commit is contained in:
parent
700a6a2f32
commit
692dc294d6
119 changed files with 27458 additions and 3 deletions
158
gomill/gomill_tests/test_framework.py
Normal file
158
gomill/gomill_tests/test_framework.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
"""Generic (non-gomill-specific) test framework code."""
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
import unittest as unittest2
|
||||
else:
|
||||
try:
|
||||
import unittest2
|
||||
except ImportError, e:
|
||||
e.unittest2_missing = True
|
||||
raise
|
||||
|
||||
# This makes TestResult ignore lines from this module in tracebacks
|
||||
__unittest = True
|
||||
|
||||
class SupporterError(StandardError):
|
||||
"""Exception raised by support objects when something goes wrong.
|
||||
|
||||
This is raised to indicate things like sequencing errors detected by mock
|
||||
objects.
|
||||
|
||||
"""
|
||||
|
||||
class FrameworkTestCase(unittest2.TestCase):
|
||||
"""unittest2-style TestCase implementation with a few tweaks."""
|
||||
|
||||
# This is default in unittest2 but not python 2.7 unittest, so force it on.
|
||||
longMessage = True
|
||||
|
||||
def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
|
||||
"""Variant implementation of standard assertItemsEqual.
|
||||
|
||||
This uses the unorderable_list_difference check even if the lists are
|
||||
sortable: I prefer its output.
|
||||
|
||||
"""
|
||||
expected = list(expected_seq)
|
||||
actual = list(actual_seq)
|
||||
missing, unexpected = unittest2.util.unorderable_list_difference(
|
||||
expected, actual, ignore_duplicate=False
|
||||
)
|
||||
errors = []
|
||||
if missing:
|
||||
errors.append('Expected, but missing:\n %s' %
|
||||
unittest2.util.safe_repr(missing))
|
||||
if unexpected:
|
||||
errors.append('Unexpected, but present:\n %s' %
|
||||
unittest2.util.safe_repr(unexpected))
|
||||
if errors:
|
||||
standardMsg = '\n'.join(errors)
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
|
||||
class SimpleTestCase(FrameworkTestCase):
|
||||
"""TestCase which runs a single function.
|
||||
|
||||
Instantiate with the test function, which takes a TestCase parameter, eg:
|
||||
def test_xxx(tc):
|
||||
tc.assertEqual(2+2, 4)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, fn):
|
||||
FrameworkTestCase.__init__(self)
|
||||
self.fn = fn
|
||||
try:
|
||||
self.name = fn.__module__.split(".", 1)[-1] + "." + fn.__name__
|
||||
except AttributeError:
|
||||
self.name = str(fn)
|
||||
|
||||
def runTest(self):
|
||||
self.fn(self)
|
||||
|
||||
def id(self):
|
||||
return self.name
|
||||
|
||||
def shortDescription(self):
|
||||
return None
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return "<SimpleTestCase: %s>" % self.name
|
||||
|
||||
|
||||
class ParameterisedTestCase(FrameworkTestCase):
|
||||
"""Parameterised testcase.
|
||||
|
||||
Subclasses should define:
|
||||
test_name -- short string
|
||||
parameter_names -- list of identifiers
|
||||
runTest
|
||||
|
||||
"""
|
||||
def __init__(self, code, *parameters):
|
||||
FrameworkTestCase.__init__(self)
|
||||
self.code = code
|
||||
self.name = "%s.%s:%s" % (self.__class__.__module__.split(".", 1)[-1],
|
||||
self.test_name, code)
|
||||
for name, value in zip(self.parameter_names, parameters):
|
||||
setattr(self, name, value)
|
||||
|
||||
def runTest(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def id(self):
|
||||
return self.name
|
||||
|
||||
def shortDescription(self):
|
||||
return None
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s: %s>" % (self.__class__.__name__, self.name)
|
||||
|
||||
|
||||
|
||||
def _function_sort_key(fn):
|
||||
try:
|
||||
return fn.__code__.co_firstlineno
|
||||
except AttributeError:
|
||||
return str(fn)
|
||||
|
||||
def make_simple_tests(source, prefix="test_", testcase_class=SimpleTestCase):
|
||||
"""Make test cases from a module's test_xxx functions.
|
||||
|
||||
source -- dict (usually a module's globals()).
|
||||
prefix -- string (default "test_")
|
||||
testcase_class -- SimpleTestCase subclass to use
|
||||
|
||||
Returns a list of TestCase objects.
|
||||
|
||||
This makes a TestCase for each function in the values of 'source' whose
|
||||
name begins with 'prefix'.
|
||||
|
||||
The list is in the order of function definition (using the line number
|
||||
attribute).
|
||||
|
||||
"""
|
||||
functions = [value for name, value in source.iteritems()
|
||||
if name.startswith(prefix) and callable(value)]
|
||||
functions.sort(key=_function_sort_key)
|
||||
return [testcase_class(fn) for fn in functions]
|
||||
|
||||
|
||||
class Fixture(object):
|
||||
"""A testing fixture.
|
||||
|
||||
Instantiate fixture objects with a TestCase parameter.
|
||||
|
||||
The fixture arranges for any necessary cleanup to be performed by calling
|
||||
TestCase.addCleanUp.
|
||||
|
||||
"""
|
Loading…
Add table
Add a link
Reference in a new issue