aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2013-10-04 10:52:26 -0700
committerRaphaƫl Barrois <raphael.barrois@polytechnique.org>2013-10-29 00:19:46 +0100
commit990bfaf44ce39aaa01a2107aadc1933947bcf550 (patch)
tree65ed6af3a74f781ab02b088752dccf313514fae7
parent6834fd72331f186a1f1fe793e193b3cfba36d5b7 (diff)
downloadfactory-boy-990bfaf44ce39aaa01a2107aadc1933947bcf550.tar
factory-boy-990bfaf44ce39aaa01a2107aadc1933947bcf550.tar.gz
Added FuzzyText attribute.
Useful for unique model attributes where the specific value can be fuzzy.
-rw-r--r--docs/fuzzy.rst29
-rw-r--r--factory/fuzzy.py33
-rw-r--r--tests/test_fuzzy.py41
3 files changed, 102 insertions, 1 deletions
diff --git a/docs/fuzzy.rst b/docs/fuzzy.rst
index d88cb5a..582a654 100644
--- a/docs/fuzzy.rst
+++ b/docs/fuzzy.rst
@@ -24,6 +24,35 @@ FuzzyAttribute
The callable that generates random values
+FuzzyText
+---------
+
+
+.. class:: FuzzyText(length=12, chars=string.ascii_letters, prefix='')
+
+ The :class:`FuzzyText` fuzzer yields random strings beginning with
+ the given :attr:`prefix`, followed by :attr:`length` charactes chosen
+ from the :attr:`chars` character set,
+ and ending with the given :attr:`suffix`.
+
+ .. attribute:: length
+
+ int, the length of the random part
+
+ .. attribute:: prefix
+
+ text, an optional prefix to prepend to the random part
+
+ .. attribute:: suffix
+
+ text, an optional suffix to append to the random part
+
+ .. attribute:: chars
+
+ char iterable, the chars to choose from; defaults to the list of ascii
+ letters and numbers.
+
+
FuzzyChoice
-----------
diff --git a/factory/fuzzy.py b/factory/fuzzy.py
index d3b130b..f3e6a31 100644
--- a/factory/fuzzy.py
+++ b/factory/fuzzy.py
@@ -23,8 +23,11 @@
"""Additional declarations for "fuzzy" attribute definitions."""
+from __future__ import unicode_literals
+
import random
+import string
import datetime
from . import compat
@@ -60,6 +63,36 @@ class FuzzyAttribute(BaseFuzzyAttribute):
return self.fuzzer()
+class FuzzyText(BaseFuzzyAttribute):
+ """Random string with a given prefix.
+
+ Generates a random string of the given length from chosen chars.
+ If a prefix or a suffix are supplied, they will be prepended / appended
+ to the generated string.
+
+ Args:
+ prefix (text): An optional prefix to prepend to the random string
+ length (int): the length of the random part
+ suffix (text): An optional suffix to append to the random string
+ chars (str list): the chars to choose from
+
+ Useful for generating unique attributes where the exact value is
+ not important.
+ """
+
+ def __init__(self, prefix='', length=12, suffix='',
+ chars=string.ascii_letters, **kwargs):
+ super(FuzzyText, self).__init__(**kwargs)
+ self.prefix = prefix
+ self.suffix = suffix
+ self.length = length
+ self.chars = tuple(chars) # Unroll iterators
+
+ def fuzz(self):
+ chars = [random.choice(self.chars) for _i in range(self.length)]
+ return self.prefix + ''.join(chars) + self.suffix
+
+
class FuzzyChoice(BaseFuzzyAttribute):
"""Handles fuzzy choice of an attribute."""
diff --git a/tests/test_fuzzy.py b/tests/test_fuzzy.py
index 97abece..a521ee2 100644
--- a/tests/test_fuzzy.py
+++ b/tests/test_fuzzy.py
@@ -63,7 +63,7 @@ class FuzzyChoiceTestCase(unittest.TestCase):
def options():
for i in range(3):
yield i
-
+
d = fuzzy.FuzzyChoice(options())
res = d.evaluate(2, None, False)
@@ -401,3 +401,42 @@ class FuzzyDateTimeTestCase(unittest.TestCase):
res = fuzz.evaluate(2, None, False)
self.assertEqual(datetime.datetime(2013, 1, 2, tzinfo=compat.UTC), res)
+
+
+class FuzzyTextTestCase(unittest.TestCase):
+
+ def test_unbiased(self):
+ chars = ['a', 'b', 'c']
+ fuzz = fuzzy.FuzzyText(prefix='pre', suffix='post', chars=chars, length=12)
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual('pre', res[:3])
+ self.assertEqual('post', res[-4:])
+ self.assertEqual(3 + 12 + 4, len(res))
+
+ for char in res[3:-4]:
+ self.assertIn(char, chars)
+
+ def test_mock(self):
+ fake_choice = lambda chars: chars[0]
+
+ chars = ['a', 'b', 'c']
+ fuzz = fuzzy.FuzzyText(prefix='pre', suffix='post', chars=chars, length=4)
+ with mock.patch('random.choice', fake_choice):
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual('preaaaapost', res)
+
+ def test_generator(self):
+ def options():
+ yield 'a'
+ yield 'b'
+ yield 'c'
+
+ fuzz = fuzzy.FuzzyText(chars=options(), length=12)
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual(12, len(res))
+
+ for char in res:
+ self.assertIn(char, ['a', 'b', 'c'])