testtools-dev team mailing list archive
-
testtools-dev team
-
Mailing list archive
-
Message #00952
Re: [Merge] lp:~jml/testtools/extract-factory into lp:testtools
Does the factory need to be exposed at all?
On 15/12/2011 10:19 PM, "Jonathan Lange" <jml@xxxxxxxxx> wrote:
Jonathan Lange has proposed merging lp:~jml/testtools/extract-factory into
lp:testtools.
Requested ...
Your team testtools developers is subscribed to branch lp:testtools.
=== modified file 'NEWS'
--- NEWS 2011-12-05 15:33:37 +0000
+++ NEWS 2011-12-15 11:18:22 +0000
@@ -14,6 +14,14 @@
``MatchesAll`` with keyword arguments, then this change might affect your
test results. (Jonathan Lange)
+* ``TestCase`` now has a ``factory`` attribute, set to an instance of
+ ``ObjectFactory``. It now uses this instance for generating unique
strings
+ and integers. (Jonathan Lange)
+
+* ``TestCase.getUniqueInteger`` and ``TestCase.getUniqueString`` are now
+ deprecated. Use ``TestCase.factory.getUniqueInteger`` and
+ ``TestCase.factory.getUniqueString`` instead. (Jonathan Lange)
+
Improvements
------------
=== modified file 'doc/for-test-authors.rst'
--- doc/for-test-authors.rst 2011-12-07 11:32:45 +0000
+++ doc/for-test-authors.rst 2011-12-15 11:18:22 +0000
@@ -1240,17 +1240,19 @@
fine. However, sometimes it's useful to be able to create arbitrary
objects
at will, without having to make up silly sample data.
-To help with this, ``testtools.TestCase`` implements creation methods
called
-``getUniqueString`` and ``getUniqueInteger``. They return strings and
-integers that are unique within the context of the test that can be used to
-assemble more complex objects. Here's a basic example where
-``getUniqueString`` is used instead of saying "foo" or "bar" or whatever::
+To help with this, ``testtools.TestCase`` comes with an ``ObjectFactory``
that
+you can access as the ``factory`` attribute within your test
+case. ``ObjectFactory`` implements creation methods called
``getUniqueString``
+and ``getUniqueInteger``. They return strings and integers that are unique
+within the context of the test that can be used to assemble more complex
+objects. Here's a basic example where ``getUniqueString`` is used instead
of
+saying "foo" or "bar" or whatever::
class SomeTest(TestCase):
def test_full_name(self):
- first_name = self.getUniqueString()
- last_name = self.getUniqueString()
+ first_name = self.factory.getUniqueString()
+ last_name = self.factory.getUniqueString()
p = Person(first_name, last_name)
self.assertEqual(p.full_name, "%s %s" % (first_name, last_name))
@@ -1260,13 +1262,15 @@
class TestCoupleLogic(TestCase):
def make_arbitrary_person(self):
- return Person(self.getUniqueString(), self.getUniqueString())
+ return Person(
+ self.factory.getUniqueString(),
+ self.factory.getUniqueString())
def test_get_invitation(self):
a = self.make_arbitrary_person()
b = self.make_arbitrary_person()
couple = Couple(a, b)
- event_name = self.getUniqueString()
+ event_name = self.factory.getUniqueString()
invitation = couple.get_invitation(event_name)
self.assertEqual(
invitation,
=== modified file 'testtools/__init__.py'
--- testtools/__init__.py 2011-09-14 10:36:41 +0000
+++ testtools/__init__.py 2011-12-15 11:18:22 +0000
@@ -12,6 +12,7 @@
'iterate_tests',
'MultipleExceptions',
'MultiTestResult',
+ 'ObjectFactory',
'PlaceHolder',
'run_test_with',
'TestCase',
@@ -27,6 +28,7 @@
'try_imports',
]
+from testtools.factory import ObjectFactory
from testtools.helpers import (
try_import,
try_imports,
=== added file 'testtools/factory.py'
--- testtools/factory.py 1970-01-01 00:00:00 +0000
+++ testtools/factory.py 2011-12-15 11:18:22 +0000
@@ -0,0 +1,48 @@
+# Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
+
+__all__ = [
+ 'ObjectFactory',
+ ]
+
+import itertools
+
+from testtools.compat import advance_iterator
+
+# XXX: Are we happy with the name ObjectFactory?
+
+# XXX: Is this a good opportunity to change the getUniqueInteger and
+# getUniqueString methods here to be get_unique_integer and
get_unique_string?
+
+class ObjectFactory(object):
+
+ DEFAULT_PREFIX = 'unique'
+
+ def __init__(self, prefix=None):
+ if prefix is None:
+ prefix = self.DEFAULT_PREFIX
+ self._prefix = prefix
+ self._unique_id_gen = itertools.count(1)
+
+ def getUniqueInteger(self):
+ """Get an integer unique to this test.
+
+ Returns an integer that is guaranteed to be unique to this
instance.
+ Use this when you need an arbitrary integer in your test, or as a
+ helper for custom anonymous factory methods.
+ """
+ return advance_iterator(self._unique_id_gen)
+
+ def getUniqueString(self, prefix=None):
+ """Get a string unique to this test.
+
+ Returns a string that is guaranteed to be unique to this instance.
Use
+ this when you need an arbitrary string in your test, or as a helper
+ for custom anonymous factory methods.
+
+ :param prefix: The prefix of the string. If not provided, defaults
+ to the id of the tests.
+ :return: A bytestring of '<prefix>-<unique_int>'.
+ """
+ if prefix is None:
+ prefix = self._prefix
+ return '%s-%d' % (prefix, self.getUniqueInteger())
=== modified file 'testtools/testcase.py'
--- testtools/testcase.py 2011-12-05 15:21:33 +0000
+++ testtools/testcase.py 2011-12-15 11:18:22 +0000
@@ -28,6 +28,7 @@
advance_iterator,
reraise,
)
+from testtools.factory import ObjectFactory
from testtools.matchers import (
Annotate,
Contains,
@@ -168,7 +169,6 @@
runTest = kwargs.pop('runTest', None)
super(TestCase, self).__init__(*args, **kwargs)
self._cleanups = []
- self._unique_id_gen = itertools.count(1)
# Generators to ensure unique traceback ids. Maps traceback label
to
# iterators.
self._traceback_id_gens = {}
@@ -193,6 +193,13 @@
if sys.version_info < (2, 6):
# Catch old-style string exceptions with None as the instance
self.exception_handlers.append((type(None), self._report_error))
+ # XXX: We could have a class variable factory_factory (except with
a
+ # better name) and then instead write:
+ # self.factory = self.factory_factory(self)
+ # Which would allow others to plugin in their factories more
easily,
+ # rather than using the TestCaseWithFactory mixin pattern. Just a
+ # thought.
+ self.factory = ObjectFactory(self.id())
def __eq__(self, other):
eq = getattr(unittest.TestCase, '__eq__', None)
@@ -446,16 +453,20 @@
raise _UnexpectedSuccess(reason)
def getUniqueInteger(self):
- """Get an integer unique to this test.
+ """DEPRECATED - Get an integer unique to this test.
+
+ Use ``self.factory.getUniqueInteger()`` instead.
Returns an integer that is guaranteed to be unique to this instance.
Use this when you need an arbitrary integer in your test, or as a
helper for custom anonymous factory methods.
"""
- return advance_iterator(self._unique_id_gen)
+ return self.factory.getUniqueInteger()
def getUniqueString(self, prefix=None):
- """Get a string unique to this test.
+ """DEPRECATED - Get a string unique to this test.
+
+ Use ``self.factory.getUniqueString()`` instead.
Returns a string that is guaranteed to be unique to this instance.
Use
this when you need an arbitrary string in your test, or as a helper
@@ -465,9 +476,7 @@
to the id of the tests.
:return: A bytestring of '<prefix>-<unique_int>'.
"""
- if prefix is None:
- prefix = self.id()
- return '%s-%d' % (prefix, self.getUniqueInteger())
+ return self.factory.getUniqueString(prefix=prefix)
def onException(self, exc_info, tb_label='traceback'):
"""Called when an exception propogates from test code.
=== modified file 'testtools/tests/__init__.py'
--- testtools/tests/__init__.py 2011-08-15 13:48:10 +0000
+++ testtools/tests/__init__.py 2011-12-15 11:18:22 +0000
@@ -12,6 +12,7 @@
test_content_type,
test_deferredruntest,
test_distutilscmd,
+ test_factory,
test_fixturesupport,
test_helpers,
test_matchers,
@@ -29,6 +30,7 @@
test_content_type,
test_deferredruntest,
test_distutilscmd,
+ test_factory,
test_fixturesupport,
test_helpers,
test_matchers,
=== added file 'testtools/tests/test_factory.py'
--- testtools/tests/test_factory.py 1970-01-01 00:00:00 +0000
+++ testtools/tests/test_factory.py 2011-12-15 11:18:22 +0000
@@ -0,0 +1,47 @@
+from testtools import TestCase
+from testtools.factory import ObjectFactory
+from testtools.matchers import Equals
+
+
+class TestFactory(TestCase):
+
+ def test_getUniqueInteger(self):
+ # getUniqueInteger returns an integer that increments each time you
+ # call it.
+ factory = ObjectFactory()
+ one = factory.getUniqueInteger()
+ self.assertEqual(1, one)
+ two = factory.getUniqueInteger()
+ self.assertEqual(2, two)
+
+ def test_getUniqueString_default_prefix(self):
+ # If no other parameters are given, getUniqueString returns a
string
+ # starting with the default prefix followed by a unique integer.
+ factory = ObjectFactory()
+ name_one = factory.getUniqueString()
+ self.assertEqual('%s-%d' % (factory.DEFAULT_PREFIX, 1), name_one)
+ name_two = factory.getUniqueString()
+ self.assertEqual('%s-%d' % (factory.DEFAULT_PREFIX, 2), name_two)
+
+ def test_getUniqueString_early_prefix(self):
+ # An optional prefix can be given to the factory. If so, then all
+ # getUniqueString calls use that as a prefix by default.
+ factory = ObjectFactory(prefix=self.id())
+ name_one = factory.getUniqueString()
+ self.assertEqual('%s-%d' % (self.id(), 1), name_one)
+ name_two = factory.getUniqueString()
+ self.assertEqual('%s-%d' % (self.id(), 2), name_two)
+
+ def test_getUniqueString_late_prefix(self):
+ # If getUniqueString is given an argument, it uses that argument as
+ # the prefix of the unique string, rather than the test id.
+ factory = ObjectFactory()
+ name_one = factory.getUniqueString('foo')
+ self.assertThat(name_one, Equals('foo-1'))
+ name_two = factory.getUniqueString('bar')
+ self.assertThat(name_two, Equals('bar-2'))
+
+
+def test_suite():
+ from unittest import TestLoader
+ return TestLoader().loadTestsFromName(__name__)
_______________________________________________
Mailing list: https://launchpad.net/~testtools-dev
Post to : testtools-dev@xxxxxxxxxxxxxxxxxxx
Unsubscribe : https://launchpad.net/~testtools-dev
More help : https://help.launchpad.net/ListHelp
--
https://code.launchpad.net/~jml/testtools/extract-factory/+merge/85833
Your team testtools developers is subscribed to branch lp:testtools.
Follow ups
References