summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_fuzzy.py238
-rw-r--r--tests/utils.py100
2 files changed, 338 insertions, 0 deletions
diff --git a/tests/test_fuzzy.py b/tests/test_fuzzy.py
index e3b5772..97abece 100644
--- a/tests/test_fuzzy.py
+++ b/tests/test_fuzzy.py
@@ -23,9 +23,11 @@
import datetime
+from factory import compat
from factory import fuzzy
from .compat import mock, unittest
+from . import utils
class FuzzyAttributeTestCase(unittest.TestCase):
@@ -163,3 +165,239 @@ class FuzzyDateTestCase(unittest.TestCase):
res = fuzz.evaluate(2, None, False)
self.assertEqual(datetime.date(2013, 1, 2), res)
+
+
+class FuzzyNaiveDateTimeTestCase(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # Setup useful constants
+ cls.jan1 = datetime.datetime(2013, 1, 1)
+ cls.jan3 = datetime.datetime(2013, 1, 3)
+ cls.jan31 = datetime.datetime(2013, 1, 31)
+
+ def test_accurate_definition(self):
+ """Tests explicit definition of a FuzzyNaiveDateTime."""
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertLessEqual(self.jan1, res)
+ self.assertLessEqual(res, self.jan31)
+
+ def test_partial_definition(self):
+ """Test defining a FuzzyNaiveDateTime without passing an end date."""
+ with utils.mocked_datetime_now(self.jan3, fuzzy):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertLessEqual(self.jan1, res)
+ self.assertLessEqual(res, self.jan3)
+
+ def test_aware_start(self):
+ """Tests that a timezone-aware start datetime is rejected."""
+ self.assertRaises(ValueError, fuzzy.FuzzyNaiveDateTime,
+ self.jan1.replace(tzinfo=compat.UTC), self.jan31)
+
+ def test_aware_end(self):
+ """Tests that a timezone-aware end datetime is rejected."""
+ self.assertRaises(ValueError, fuzzy.FuzzyNaiveDateTime,
+ self.jan1, self.jan31.replace(tzinfo=compat.UTC))
+
+ def test_force_year(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_year=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.year)
+
+ def test_force_month(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_month=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.month)
+
+ def test_force_day(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_day=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.day)
+
+ def test_force_hour(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_hour=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.hour)
+
+ def test_force_minute(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_minute=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.minute)
+
+ def test_force_second(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_second=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.second)
+
+ def test_force_microsecond(self):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31, force_microsecond=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.microsecond)
+
+ def test_invalid_definition(self):
+ self.assertRaises(ValueError, fuzzy.FuzzyNaiveDateTime,
+ self.jan31, self.jan1)
+
+ def test_invalid_partial_definition(self):
+ with utils.mocked_datetime_now(self.jan1, fuzzy):
+ self.assertRaises(ValueError, fuzzy.FuzzyNaiveDateTime,
+ self.jan31)
+
+ def test_biased(self):
+ """Tests a FuzzyDate with a biased random.randint."""
+
+ fake_randint = lambda low, high: (low + high) // 2
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1, self.jan31)
+
+ with mock.patch('random.randint', fake_randint):
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual(datetime.datetime(2013, 1, 16), res)
+
+ def test_biased_partial(self):
+ """Tests a FuzzyDate with a biased random and implicit upper bound."""
+ with utils.mocked_datetime_now(self.jan3, fuzzy):
+ fuzz = fuzzy.FuzzyNaiveDateTime(self.jan1)
+
+ fake_randint = lambda low, high: (low + high) // 2
+ with mock.patch('random.randint', fake_randint):
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual(datetime.datetime(2013, 1, 2), res)
+
+
+class FuzzyDateTimeTestCase(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # Setup useful constants
+ cls.jan1 = datetime.datetime(2013, 1, 1, tzinfo=compat.UTC)
+ cls.jan3 = datetime.datetime(2013, 1, 3, tzinfo=compat.UTC)
+ cls.jan31 = datetime.datetime(2013, 1, 31, tzinfo=compat.UTC)
+
+ def test_accurate_definition(self):
+ """Tests explicit definition of a FuzzyDateTime."""
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertLessEqual(self.jan1, res)
+ self.assertLessEqual(res, self.jan31)
+
+ def test_partial_definition(self):
+ """Test defining a FuzzyDateTime without passing an end date."""
+ with utils.mocked_datetime_now(self.jan3, fuzzy):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertLessEqual(self.jan1, res)
+ self.assertLessEqual(res, self.jan3)
+
+ def test_invalid_definition(self):
+ self.assertRaises(ValueError, fuzzy.FuzzyDateTime,
+ self.jan31, self.jan1)
+
+ def test_invalid_partial_definition(self):
+ with utils.mocked_datetime_now(self.jan1, fuzzy):
+ self.assertRaises(ValueError, fuzzy.FuzzyDateTime,
+ self.jan31)
+
+ def test_naive_start(self):
+ """Tests that a timezone-naive start datetime is rejected."""
+ self.assertRaises(ValueError, fuzzy.FuzzyDateTime,
+ self.jan1.replace(tzinfo=None), self.jan31)
+
+ def test_naive_end(self):
+ """Tests that a timezone-naive end datetime is rejected."""
+ self.assertRaises(ValueError, fuzzy.FuzzyDateTime,
+ self.jan1, self.jan31.replace(tzinfo=None))
+
+ def test_force_year(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_year=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.year)
+
+ def test_force_month(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_month=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.month)
+
+ def test_force_day(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_day=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.day)
+
+ def test_force_hour(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_hour=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.hour)
+
+ def test_force_minute(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_minute=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.minute)
+
+ def test_force_second(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_second=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.second)
+
+ def test_force_microsecond(self):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31, force_microsecond=4)
+
+ for _i in range(20):
+ res = fuzz.evaluate(2, None, False)
+ self.assertEqual(4, res.microsecond)
+
+ def test_biased(self):
+ """Tests a FuzzyDate with a biased random.randint."""
+
+ fake_randint = lambda low, high: (low + high) // 2
+ fuzz = fuzzy.FuzzyDateTime(self.jan1, self.jan31)
+
+ with mock.patch('random.randint', fake_randint):
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual(datetime.datetime(2013, 1, 16, tzinfo=compat.UTC), res)
+
+ def test_biased_partial(self):
+ """Tests a FuzzyDate with a biased random and implicit upper bound."""
+ with utils.mocked_datetime_now(self.jan3, fuzzy):
+ fuzz = fuzzy.FuzzyDateTime(self.jan1)
+
+ fake_randint = lambda low, high: (low + high) // 2
+ with mock.patch('random.randint', fake_randint):
+ res = fuzz.evaluate(2, None, False)
+
+ self.assertEqual(datetime.datetime(2013, 1, 2, tzinfo=compat.UTC), res)
diff --git a/tests/utils.py b/tests/utils.py
new file mode 100644
index 0000000..823e82b
--- /dev/null
+++ b/tests/utils.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2010 Mark Sandstrom
+# Copyright (c) 2011-2013 Raphaƫl Barrois
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import datetime
+
+from .compat import mock
+
+
+class MultiModulePatcher(object):
+ """An abstract context processor for patching multiple modules."""
+
+ replaced_symbol = None
+ replaced_symbol_module = None
+ module_imported_as = ''
+
+ def __init__(self, *target_modules, **kwargs):
+ super(MultiModulePatcher, self).__init__(**kwargs)
+ if not self.module_imported_as:
+ self.module_imported_as = replaced_symbol.__module__.__name__
+ self.patchers = [self._build_patcher(mod) for mod in target_modules]
+
+ def _check_module(self, target_module):
+ if not self.replaced_symbol_module:
+ # No check to perform
+ return
+
+ replaced_import = getattr(target_module, self.module_imported_as)
+ assert replaced_import is self.replaced_symbol_module, (
+ "Cannot patch import %s.%s (%r != %r)" % (
+ target_module.__name__, self.module_imported_as,
+ replaced_import, self.replaced_symbol_module))
+
+ def _build_patcher(self, target_module):
+ """Build a mock patcher for the target module."""
+ self._check_module(target_module)
+
+ return mock.patch.object(
+ getattr(target_module, self.module_imported_as),
+ self.replaced_symbol.__name__,
+ mock.Mock(wraps=self.replaced_symbol),
+ )
+
+ def setup_mocked_symbol(self, mocked_symbol):
+ """Setup a mocked symbol for later use."""
+ pass
+
+ def __enter__(self):
+ for patcher in self.patchers:
+ mocked_symbol = patcher.start()
+ self.setup_mocked_symbol(mocked_symbol)
+
+ def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
+ for patcher in self.patchers:
+ patcher.stop()
+
+
+class mocked_date_today(MultiModulePatcher):
+ """A context processor changing the value of date.today()."""
+ replaced_symbol = datetime.date
+ replaced_symbol_module = datetime
+ module_imported_as = 'datetime'
+
+ def __init__(self, target_date, *target_modules, **kwargs):
+ self.target_date = target_date
+ super(mocked_date_today, self).__init__(*target_modules, **kwargs)
+
+ def setup_mocked_symbol(self, mocked_date):
+ mocked_date.today.return_value = self.target_date
+
+
+class mocked_datetime_now(MultiModulePatcher):
+ replaced_symbol = datetime.datetime
+ replaced_symbol_module = datetime
+ module_imported_as = 'datetime'
+
+ def __init__(self, target_dt, *target_modules, **kwargs):
+ self.target_dt = target_dt
+ super(mocked_datetime_now, self).__init__(*target_modules, **kwargs)
+
+ def setup_mocked_symbol(self, mocked_datetime):
+ mocked_datetime.now.return_value = self.target_dt