summaryrefslogtreecommitdiff
path: root/testtools
diff options
context:
space:
mode:
authorBrant Knudson <bknudson@us.ibm.com>2015-12-09 13:12:01 -0600
committerRobert Collins <robertc@robertcollins.net>2016-02-29 12:28:49 +1300
commit4d4bc6f384a920daf1710101ac2a5dc68c49fc01 (patch)
treedf84d2c5241ff2ec1cf62ed67d9aa4dee946a8a6 /testtools
parent11e50d3fc2e89b902e1b464f0a60bab2a1620442 (diff)
downloadtesttools-4d4bc6f384a920daf1710101ac2a5dc68c49fc01.tar.gz
Add unique_text_generator
This provides a way to make it easier to test with unicode text strings. The value returned will be like TestCase.getUniqueString but the value is six.text_type and contains unicode. Change-Id: I3f144e1294a801b23793f7a2520465e15f3a5222
Diffstat (limited to 'testtools')
-rw-r--r--testtools/__init__.py2
-rw-r--r--testtools/testcase.py40
-rw-r--r--testtools/tests/test_testcase.py49
3 files changed, 90 insertions, 1 deletions
diff --git a/testtools/__init__.py b/testtools/__init__.py
index 336df24..d6c15d2 100644
--- a/testtools/__init__.py
+++ b/testtools/__init__.py
@@ -42,6 +42,7 @@ __all__ = [
'TimestampingStreamResult',
'try_import',
'try_imports',
+ 'unique_text_generator',
]
# Compat - removal announced in 0.9.25.
@@ -77,6 +78,7 @@ else:
skip,
skipIf,
skipUnless,
+ unique_text_generator,
)
from testtools.testresult import (
CopyStreamResult,
diff --git a/testtools/testcase.py b/testtools/testcase.py
index 97160e0..1e131ee 100644
--- a/testtools/testcase.py
+++ b/testtools/testcase.py
@@ -13,6 +13,7 @@ __all__ = [
'skipIf',
'skipUnless',
'TestCase',
+ 'unique_text_generator',
]
import copy
@@ -29,6 +30,7 @@ from extras import (
fixtures = try_import('fixtures')
# To let setup.py work, make this a conditional import.
unittest = try_imports(['unittest2', 'unittest'])
+import six
from testtools import (
content,
@@ -182,6 +184,44 @@ def gather_details(source_dict, target_dict):
target_dict[name] = _copy_content(content_object)
+def _mods(i, mod):
+ (q, r) = divmod(i, mod)
+ while True:
+ yield r
+ if not q:
+ break
+ (q, r) = divmod(q, mod)
+
+
+def _unique_text(base_cp, cp_range, index):
+ s = six.text_type('')
+ for m in _mods(index, cp_range):
+ s += six.unichr(base_cp + m)
+ return s
+
+
+def unique_text_generator(prefix):
+ """Generates unique text values.
+
+ Generates text values that are unique. Use this when you need arbitrary
+ text in your test, or as a helper for custom anonymous factory methods.
+
+ :param prefix: The prefix for text.
+ :return: text that looks like '<prefix>-<text_with_unicode>'.
+ :rtype: six.text_type
+ """
+ # 0x1e00 is the start of a range of glyphs that are easy to see are
+ # unicode since they've got circles and dots and other diacriticals.
+ # 0x1eff is the end of the range of these diacritical chars.
+ BASE_CP = 0x1e00
+ CP_RANGE = 0x1f00 - BASE_CP
+ index = 0
+ while True:
+ unique_text = _unique_text(BASE_CP, CP_RANGE, index)
+ yield six.text_type('%s-%s') % (prefix, unique_text)
+ index = index + 1
+
+
class TestCase(unittest.TestCase):
"""Extensions to the basic TestCase.
diff --git a/testtools/tests/test_testcase.py b/testtools/tests/test_testcase.py
index 9153680..f0aa881 100644
--- a/testtools/tests/test_testcase.py
+++ b/testtools/tests/test_testcase.py
@@ -7,6 +7,8 @@ from pprint import pformat
import sys
import unittest
+import six
+
from testtools import (
DecorateTestCaseResult,
ErrorHolder,
@@ -1117,7 +1119,7 @@ class TestExpectedFailure(TestWithDetails):
class TestUniqueFactories(TestCase):
- """Tests for getUniqueString and getUniqueInteger."""
+ """Tests for getUniqueString, getUniqueInteger, unique_text_generator."""
run_test_with = FullStackRunTest
@@ -1145,6 +1147,51 @@ class TestUniqueFactories(TestCase):
name_two = self.getUniqueString('bar')
self.assertThat(name_two, Equals('bar-2'))
+ def test_unique_text_generator(self):
+ # unique_text_generator yields the prefix's id followed by unique
+ # unicode string.
+ prefix = self.getUniqueString()
+ unique_text_generator = testcase.unique_text_generator(prefix)
+ first_result = next(unique_text_generator)
+ self.assertEqual(six.text_type('%s-%s') % (prefix, _u('\u1e00')),
+ first_result)
+ # The next value yielded by unique_text_generator is different.
+ second_result = next(unique_text_generator)
+ self.assertEqual(six.text_type('%s-%s') % (prefix, _u('\u1e01')),
+ second_result)
+
+ def test_mods(self):
+ # given a number and max, generate a list that's the mods.
+ # The list should contain no numbers >= mod
+ self.assertEqual([0], list(testcase._mods(0, 5)))
+ self.assertEqual([1], list(testcase._mods(1, 5)))
+ self.assertEqual([2], list(testcase._mods(2, 5)))
+ self.assertEqual([3], list(testcase._mods(3, 5)))
+ self.assertEqual([4], list(testcase._mods(4, 5)))
+ self.assertEqual([0, 1], list(testcase._mods(5, 5)))
+ self.assertEqual([1, 1], list(testcase._mods(6, 5)))
+ self.assertEqual([2, 1], list(testcase._mods(7, 5)))
+ self.assertEqual([0, 2], list(testcase._mods(10, 5)))
+ self.assertEqual([0, 0, 1], list(testcase._mods(25, 5)))
+ self.assertEqual([1, 0, 1], list(testcase._mods(26, 5)))
+ self.assertEqual([1], list(testcase._mods(1, 100)))
+ self.assertEqual([0, 1], list(testcase._mods(100, 100)))
+ self.assertEqual([0, 10], list(testcase._mods(1000, 100)))
+
+ def test_unique_text(self):
+ self.assertEqual(
+ u'\u1e00',
+ testcase._unique_text(base_cp=0x1e00, cp_range=5, index=0))
+ self.assertEqual(
+ u'\u1e01',
+ testcase._unique_text(base_cp=0x1e00, cp_range=5, index=1))
+ self.assertEqual(
+ u'\u1e00\u1e01',
+ testcase._unique_text(base_cp=0x1e00, cp_range=5, index=5))
+ self.assertEqual(
+ u'\u1e03\u1e02\u1e01',
+ testcase._unique_text(base_cp=0x1e00, cp_range=5, index=38))
+
class TestCloneTestWithNewId(TestCase):
"""Tests for clone_test_with_new_id."""