summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py1
-rw-r--r--tests/compat.py27
-rw-r--r--tests/cyclic/__init__.py0
-rw-r--r--tests/cyclic/bar.py37
-rw-r--r--tests/cyclic/foo.py38
-rw-r--r--tests/test_base.py88
-rw-r--r--tests/test_containers.py33
-rw-r--r--tests/test_declarations.py52
-rw-r--r--tests/test_using.py508
-rw-r--r--tests/test_utils.py232
10 files changed, 949 insertions, 67 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
index 7ab3567..80a96a4 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -5,3 +5,4 @@ from .test_base import *
from .test_containers import *
from .test_declarations import *
from .test_using import *
+from .test_utils import *
diff --git a/tests/compat.py b/tests/compat.py
new file mode 100644
index 0000000..15fa3ae
--- /dev/null
+++ b/tests/compat.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2011 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.
+
+"""Compatibility tools for tests"""
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
diff --git a/tests/cyclic/__init__.py b/tests/cyclic/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/cyclic/__init__.py
diff --git a/tests/cyclic/bar.py b/tests/cyclic/bar.py
new file mode 100644
index 0000000..cc90930
--- /dev/null
+++ b/tests/cyclic/bar.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2011-2012 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.
+
+"""Helper to test circular factory dependencies."""
+
+import factory
+
+class Bar(object):
+ def __init__(self, foo, y):
+ self.foo = foo
+ self.y = y
+
+
+class BarFactory(factory.Factory):
+ FACTORY_FOR = Bar
+
+ y = 13
+ foo = factory.CircularSubFactory('cyclic.foo', 'FooFactory')
+
diff --git a/tests/cyclic/foo.py b/tests/cyclic/foo.py
new file mode 100644
index 0000000..e6f8896
--- /dev/null
+++ b/tests/cyclic/foo.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2011-2012 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.
+
+"""Helper to test circular factory dependencies."""
+
+import factory
+
+from cyclic import bar
+
+class Foo(object):
+ def __init__(self, bar, x):
+ self.bar = bar
+ self.x = x
+
+
+class FooFactory(factory.Factory):
+ FACTORY_FOR = Foo
+
+ x = 42
+ bar = factory.SubFactory(bar.BarFactory)
diff --git a/tests/test_base.py b/tests/test_base.py
index 8da655e..7ec3d0e 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -20,12 +20,13 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-import unittest
import warnings
from factory import base
from factory import declarations
+from .compat import unittest
+
class TestObject(object):
def __init__(self, one=None, two=None, three=None, four=None):
self.one = one
@@ -34,19 +35,25 @@ class TestObject(object):
self.four = four
class FakeDjangoModel(object):
- class FakeDjangoManager(object):
- def create(self, **kwargs):
- fake_model = FakeDjangoModel(**kwargs)
- fake_model.id = 1
- return fake_model
-
- objects = FakeDjangoManager()
+ @classmethod
+ def create(cls, **kwargs):
+ instance = cls(**kwargs)
+ instance.id = 1
+ return instance
def __init__(self, **kwargs):
for name, value in kwargs.iteritems():
setattr(self, name, value)
self.id = None
+class FakeModelFactory(base.Factory):
+ ABSTRACT_FACTORY = True
+
+ @classmethod
+ def _create(cls, target_class, *args, **kwargs):
+ return target_class.create(**kwargs)
+
+
class TestModel(FakeDjangoModel):
pass
@@ -66,6 +73,8 @@ class FactoryTestCase(unittest.TestCase):
def testLazyAttributeNonExistentParam(self):
class TestObjectFactory(base.Factory):
+ FACTORY_FOR = TestObject
+
one = declarations.LazyAttribute(lambda a: a.does_not_exist )
self.assertRaises(AttributeError, TestObjectFactory)
@@ -73,9 +82,13 @@ class FactoryTestCase(unittest.TestCase):
def testInheritanceWithSequence(self):
"""Tests that sequence IDs are shared between parent and son."""
class TestObjectFactory(base.Factory):
+ FACTORY_FOR = TestObject
+
one = declarations.Sequence(lambda a: a)
class TestSubFactory(TestObjectFactory):
+ FACTORY_FOR = TestObject
+
pass
parent = TestObjectFactory.build()
@@ -96,6 +109,8 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
base.Factory.default_strategy = base.BUILD_STRATEGY
class TestModelFactory(base.Factory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory()
@@ -105,7 +120,9 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
def testCreateStrategy(self):
# Default default_strategy
- class TestModelFactory(base.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory()
@@ -116,6 +133,8 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
base.Factory.default_strategy = base.STUB_STRATEGY
class TestModelFactory(base.Factory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory()
@@ -126,12 +145,16 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
base.Factory.default_strategy = 'unknown'
class TestModelFactory(base.Factory):
+ FACTORY_FOR = TestModel
+
one = 'one'
self.assertRaises(base.Factory.UnknownStrategy, TestModelFactory)
def testStubWithNonStubStrategy(self):
class TestModelFactory(base.StubFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
TestModelFactory.default_strategy = base.CREATE_STRATEGY
@@ -141,6 +164,16 @@ class FactoryDefaultStrategyTestCase(unittest.TestCase):
TestModelFactory.default_strategy = base.BUILD_STRATEGY
self.assertRaises(base.StubFactory.UnsupportedStrategy, TestModelFactory)
+ def test_change_strategy(self):
+ @base.use_strategy(base.CREATE_STRATEGY)
+ class TestModelFactory(base.StubFactory):
+ FACTORY_FOR = TestModel
+
+ one = 'one'
+
+ self.assertEqual(base.CREATE_STRATEGY, TestModelFactory.default_strategy)
+
+
class FactoryCreationTestCase(unittest.TestCase):
def testFactoryFor(self):
class TestFactory(base.Factory):
@@ -149,8 +182,10 @@ class FactoryCreationTestCase(unittest.TestCase):
self.assertTrue(isinstance(TestFactory.build(), TestObject))
def testAutomaticAssociatedClassDiscovery(self):
- class TestObjectFactory(base.Factory):
- pass
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore')
+ class TestObjectFactory(base.Factory):
+ pass
self.assertTrue(isinstance(TestObjectFactory.build(), TestObject))
@@ -159,8 +194,7 @@ class FactoryCreationTestCase(unittest.TestCase):
with warnings.catch_warnings(record=True) as w:
# Clear the warning registry.
- if hasattr(base, '__warningregistry__'):
- base.__warningregistry__.clear()
+ __warningregistry__.clear()
warnings.simplefilter('always')
class TestObjectFactory(base.Factory):
@@ -177,6 +211,8 @@ class FactoryCreationTestCase(unittest.TestCase):
def testInheritanceWithStub(self):
class TestObjectFactory(base.StubFactory):
+ FACTORY_FOR = TestObject
+
pass
class TestFactory(TestObjectFactory):
@@ -185,7 +221,9 @@ class FactoryCreationTestCase(unittest.TestCase):
self.assertEqual(TestFactory.default_strategy, base.STUB_STRATEGY)
def testCustomCreation(self):
- class TestModelFactory(base.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
@classmethod
def _prepare(cls, create, **kwargs):
kwargs['four'] = 4
@@ -220,5 +258,27 @@ class FactoryCreationTestCase(unittest.TestCase):
self.assertTrue('autodiscovery' not in str(e))
+class PostGenerationParsingTestCase(unittest.TestCase):
+
+ def test_extraction(self):
+ class TestObjectFactory(base.Factory):
+ FACTORY_FOR = TestObject
+
+ foo = declarations.PostGenerationDeclaration()
+
+ self.assertIn('foo', TestObjectFactory._postgen_declarations)
+
+ def test_classlevel_extraction(self):
+ class TestObjectFactory(base.Factory):
+ FACTORY_FOR = TestObject
+
+ foo = declarations.PostGenerationDeclaration()
+ foo__bar = 42
+
+ self.assertIn('foo', TestObjectFactory._postgen_declarations)
+ self.assertIn('foo__bar', TestObjectFactory._declarations)
+
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_containers.py b/tests/test_containers.py
index 6e58573..b1ed6ed 100644
--- a/tests/test_containers.py
+++ b/tests/test_containers.py
@@ -20,12 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-import unittest
-
from factory import base
from factory import containers
from factory import declarations
+from .compat import unittest
+
class LazyStubTestCase(unittest.TestCase):
def test_basic(self):
stub = containers.LazyStub({'one': 1, 'two': 2})
@@ -178,6 +178,17 @@ class DeclarationDictTestCase(unittest.TestCase):
self.assertEqual(set(['one', 'three']), set(d))
self.assertEqual(set([1, 3]), set(d.values()))
+ def test_update_with_public_ignores_factory_attributes(self):
+ """Ensure that a DeclarationDict ignores FACTORY_ keys."""
+ d = containers.DeclarationDict()
+ d.update_with_public({
+ 'one': 1,
+ 'FACTORY_FOR': 2,
+ 'FACTORY_ARG_PARAMETERS': 3,
+ })
+ self.assertEqual(['one'], list(d))
+ self.assertEqual([1], list(d.values()))
+
class AttributeBuilderTestCase(unittest.TestCase):
def test_empty(self):
@@ -316,6 +327,24 @@ class AttributeBuilderTestCase(unittest.TestCase):
ab = containers.AttributeBuilder(FakeFactory, {'one': 4, 'three': la})
self.assertEqual({'one': 4, 'two': 8, 'three': 8}, ab.build(create=False))
+ def test_subfields(self):
+ class FakeInnerFactory(object):
+ pass
+
+ sf = declarations.SubFactory(FakeInnerFactory)
+
+ class FakeFactory(object):
+ @classmethod
+ def declarations(cls, extra):
+ d = {'one': sf, 'two': 2}
+ d.update(extra)
+ return d
+
+ ab = containers.AttributeBuilder(FakeFactory, {'one__blah': 1, 'two__bar': 2})
+ self.assertTrue(ab.has_subfields(sf))
+ self.assertEqual(['one'], ab._subfields.keys())
+ self.assertEqual(2, ab._attrs['two__bar'])
+
def test_sub_factory(self):
pass
diff --git a/tests/test_declarations.py b/tests/test_declarations.py
index 7215a54..c0b3539 100644
--- a/tests/test_declarations.py
+++ b/tests/test_declarations.py
@@ -20,9 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-import unittest
+import datetime
-from factory.declarations import deepgetattr, OrderedDeclaration, Sequence
+from factory.declarations import deepgetattr, CircularSubFactory, OrderedDeclaration, \
+ PostGenerationDeclaration, Sequence
+
+from .compat import unittest
class OrderedDeclarationTestCase(unittest.TestCase):
def test_errors(self):
@@ -54,6 +57,51 @@ class DigTestCase(unittest.TestCase):
self.assertEqual(42, deepgetattr(obj, 'a.b.c.n.x', 42))
+class PostGenerationDeclarationTestCase(unittest.TestCase):
+ def test_extract_no_prefix(self):
+ decl = PostGenerationDeclaration()
+
+ extracted, kwargs = decl.extract('foo', {'foo': 13, 'foo__bar': 42})
+ self.assertEqual(extracted, 13)
+ self.assertEqual(kwargs, {'bar': 42})
+
+ def test_extract_with_prefix(self):
+ decl = PostGenerationDeclaration(extract_prefix='blah')
+
+ extracted, kwargs = decl.extract('foo',
+ {'foo': 13, 'foo__bar': 42, 'blah': 42, 'blah__baz': 1})
+ self.assertEqual(extracted, 42)
+ self.assertEqual(kwargs, {'baz': 1})
+
+
+class CircularSubFactoryTestCase(unittest.TestCase):
+ def test_lazyness(self):
+ f = CircularSubFactory('factory.declarations', 'Sequence', x=3)
+ self.assertEqual(None, f.factory)
+
+ self.assertEqual({'x': 3}, f.defaults)
+
+ factory_class = f.get_factory()
+ self.assertEqual(Sequence, factory_class)
+
+ def test_cache(self):
+ orig_date = datetime.date
+ f = CircularSubFactory('datetime', 'date')
+ self.assertEqual(None, f.factory)
+
+ factory_class = f.get_factory()
+ self.assertEqual(orig_date, factory_class)
+
+ try:
+ # Modify original value
+ datetime.date = None
+ # Repeat import
+ factory_class = f.get_factory()
+ self.assertEqual(orig_date, factory_class)
+
+ finally:
+ # IMPORTANT: restore attribute.
+ datetime.date = orig_date
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_using.py b/tests/test_using.py
index 7f9f09c..7e141eb 100644
--- a/tests/test_using.py
+++ b/tests/test_using.py
@@ -20,10 +20,15 @@
# THE SOFTWARE.
"""Tests using factory."""
-import unittest
+
+import functools
+import os
+import sys
+import warnings
import factory
+from .compat import unittest
class TestObject(object):
@@ -34,24 +39,49 @@ class TestObject(object):
self.four = four
self.five = five
-class FakeDjangoModel(object):
- class FakeDjangoManager(object):
+
+class FakeModel(object):
+ @classmethod
+ def create(cls, **kwargs):
+ instance = cls(**kwargs)
+ instance.id = 1
+ return instance
+
+ class FakeModelManager(object):
def create(self, **kwargs):
- fake_model = FakeDjangoModel(**kwargs)
- fake_model.id = 1
- return fake_model
+ instance = FakeModel.create(**kwargs)
+ instance.id = 2
+ return instance
- objects = FakeDjangoManager()
+ objects = FakeModelManager()
def __init__(self, **kwargs):
for name, value in kwargs.iteritems():
setattr(self, name, value)
self.id = None
-class TestModel(FakeDjangoModel):
+
+class FakeModelFactory(factory.Factory):
+ ABSTRACT_FACTORY = True
+
+ @classmethod
+ def _create(cls, target_class, *args, **kwargs):
+ return target_class.create(**kwargs)
+
+
+class TestModel(FakeModel):
pass
+def disable_warnings(fun):
+ @functools.wraps(fun)
+ def decorated(*args, **kwargs):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore')
+ return fun(*args, **kwargs)
+ return decorated
+
+
class SimpleBuildTestCase(unittest.TestCase):
"""Tests the minimalist 'factory.build/create' functions."""
@@ -82,19 +112,21 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.three, 3)
self.assertEqual(obj.four, None)
+ @disable_warnings
def test_create(self):
- obj = factory.create(FakeDjangoModel, foo='bar')
- self.assertEqual(obj.id, 1)
+ obj = factory.create(FakeModel, foo='bar')
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
+ @disable_warnings
def test_create_batch(self):
- objs = factory.create_batch(FakeDjangoModel, 4, foo='bar')
+ objs = factory.create_batch(FakeModel, 4, foo='bar')
self.assertEqual(4, len(objs))
self.assertEqual(4, len(set(objs)))
for obj in objs:
- self.assertEqual(obj.id, 1)
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
def test_stub(self):
@@ -103,7 +135,7 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertFalse(hasattr(obj, 'two'))
def test_stub_batch(self):
- objs = factory.stub_batch(FakeDjangoModel, 4, foo='bar')
+ objs = factory.stub_batch(FakeModel, 4, foo='bar')
self.assertEqual(4, len(objs))
self.assertEqual(4, len(set(objs)))
@@ -113,22 +145,23 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.foo, 'bar')
def test_generate_build(self):
- obj = factory.generate(FakeDjangoModel, factory.BUILD_STRATEGY, foo='bar')
+ obj = factory.generate(FakeModel, factory.BUILD_STRATEGY, foo='bar')
self.assertEqual(obj.id, None)
self.assertEqual(obj.foo, 'bar')
+ @disable_warnings
def test_generate_create(self):
- obj = factory.generate(FakeDjangoModel, factory.CREATE_STRATEGY, foo='bar')
- self.assertEqual(obj.id, 1)
+ obj = factory.generate(FakeModel, factory.CREATE_STRATEGY, foo='bar')
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
def test_generate_stub(self):
- obj = factory.generate(FakeDjangoModel, factory.STUB_STRATEGY, foo='bar')
+ obj = factory.generate(FakeModel, factory.STUB_STRATEGY, foo='bar')
self.assertFalse(hasattr(obj, 'id'))
self.assertEqual(obj.foo, 'bar')
def test_generate_batch_build(self):
- objs = factory.generate_batch(FakeDjangoModel, factory.BUILD_STRATEGY, 20, foo='bar')
+ objs = factory.generate_batch(FakeModel, factory.BUILD_STRATEGY, 20, foo='bar')
self.assertEqual(20, len(objs))
self.assertEqual(20, len(set(objs)))
@@ -137,18 +170,19 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.id, None)
self.assertEqual(obj.foo, 'bar')
+ @disable_warnings
def test_generate_batch_create(self):
- objs = factory.generate_batch(FakeDjangoModel, factory.CREATE_STRATEGY, 20, foo='bar')
+ objs = factory.generate_batch(FakeModel, factory.CREATE_STRATEGY, 20, foo='bar')
self.assertEqual(20, len(objs))
self.assertEqual(20, len(set(objs)))
for obj in objs:
- self.assertEqual(obj.id, 1)
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
def test_generate_batch_stub(self):
- objs = factory.generate_batch(FakeDjangoModel, factory.STUB_STRATEGY, 20, foo='bar')
+ objs = factory.generate_batch(FakeModel, factory.STUB_STRATEGY, 20, foo='bar')
self.assertEqual(20, len(objs))
self.assertEqual(20, len(set(objs)))
@@ -158,17 +192,18 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.foo, 'bar')
def test_simple_generate_build(self):
- obj = factory.simple_generate(FakeDjangoModel, False, foo='bar')
+ obj = factory.simple_generate(FakeModel, False, foo='bar')
self.assertEqual(obj.id, None)
self.assertEqual(obj.foo, 'bar')
+ @disable_warnings
def test_simple_generate_create(self):
- obj = factory.simple_generate(FakeDjangoModel, True, foo='bar')
- self.assertEqual(obj.id, 1)
+ obj = factory.simple_generate(FakeModel, True, foo='bar')
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
def test_simple_generate_batch_build(self):
- objs = factory.simple_generate_batch(FakeDjangoModel, False, 20, foo='bar')
+ objs = factory.simple_generate_batch(FakeModel, False, 20, foo='bar')
self.assertEqual(20, len(objs))
self.assertEqual(20, len(set(objs)))
@@ -177,14 +212,15 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.id, None)
self.assertEqual(obj.foo, 'bar')
+ @disable_warnings
def test_simple_generate_batch_create(self):
- objs = factory.simple_generate_batch(FakeDjangoModel, True, 20, foo='bar')
+ objs = factory.simple_generate_batch(FakeModel, True, 20, foo='bar')
self.assertEqual(20, len(objs))
self.assertEqual(20, len(set(objs)))
for obj in objs:
- self.assertEqual(obj.id, 1)
+ self.assertEqual(obj.id, 2)
self.assertEqual(obj.foo, 'bar')
def test_make_factory(self):
@@ -203,16 +239,31 @@ class SimpleBuildTestCase(unittest.TestCase):
self.assertEqual(obj.four, None)
-class FactoryTestCase(unittest.TestCase):
+class UsingFactoryTestCase(unittest.TestCase):
def testAttribute(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'one'
test_object = TestObjectFactory.build()
self.assertEqual(test_object.one, 'one')
+ def test_abstract(self):
+ class SomeAbstractFactory(factory.Factory):
+ ABSTRACT_FACTORY = True
+ one = 'one'
+
+ class InheritedFactory(SomeAbstractFactory):
+ FACTORY_FOR = TestObject
+
+ test_object = InheritedFactory.build()
+ self.assertEqual(test_object.one, 'one')
+
def testSequence(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.Sequence(lambda n: 'one' + n)
two = factory.Sequence(lambda n: 'two' + n)
@@ -226,6 +277,8 @@ class FactoryTestCase(unittest.TestCase):
def testSequenceCustomBegin(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@classmethod
def _setup_next_sequence(cls):
return 42
@@ -243,6 +296,8 @@ class FactoryTestCase(unittest.TestCase):
def test_sequence_batch(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.Sequence(lambda n: 'one' + n)
two = factory.Sequence(lambda n: 'two' + n)
@@ -256,6 +311,8 @@ class FactoryTestCase(unittest.TestCase):
def testLazyAttribute(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.LazyAttribute(lambda a: 'abc' )
two = factory.LazyAttribute(lambda a: a.one + ' xyz')
@@ -265,6 +322,8 @@ class FactoryTestCase(unittest.TestCase):
def testLazyAttributeSequence(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.LazyAttributeSequence(lambda a, n: 'abc' + n)
two = factory.LazyAttributeSequence(lambda a, n: a.one + ' xyz' + n)
@@ -278,6 +337,8 @@ class FactoryTestCase(unittest.TestCase):
def testLazyAttributeDecorator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@factory.lazy_attribute
def one(a):
return 'one'
@@ -290,6 +351,8 @@ class FactoryTestCase(unittest.TestCase):
n = 3
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'xx'
two = factory.SelfAttribute('one')
three = TmpObj()
@@ -304,6 +367,8 @@ class FactoryTestCase(unittest.TestCase):
def testSequenceDecorator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@factory.sequence
def one(n):
return 'one' + n
@@ -313,6 +378,8 @@ class FactoryTestCase(unittest.TestCase):
def testLazyAttributeSequenceDecorator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@factory.lazy_attribute_sequence
def one(a, n):
return 'one' + n
@@ -326,6 +393,8 @@ class FactoryTestCase(unittest.TestCase):
def testBuildWithParameters(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.Sequence(lambda n: 'one' + n)
two = factory.Sequence(lambda n: 'two' + n)
@@ -339,7 +408,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertEqual(test_object1.two, 'two1')
def testCreate(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.create()
@@ -347,7 +418,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertTrue(test_model.id)
def test_create_batch(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.create_batch(20, two=factory.Sequence(int))
@@ -361,7 +434,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertTrue(obj.id)
def test_generate_build(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.generate(factory.BUILD_STRATEGY)
@@ -369,7 +444,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(test_model.id)
def test_generate_create(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.generate(factory.CREATE_STRATEGY)
@@ -377,7 +454,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertTrue(test_model.id)
def test_generate_stub(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.generate(factory.STUB_STRATEGY)
@@ -385,7 +464,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(hasattr(test_model, 'id'))
def test_generate_batch_build(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.generate_batch(factory.BUILD_STRATEGY, 20, two='two')
@@ -399,7 +480,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(obj.id)
def test_generate_batch_create(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.generate_batch(factory.CREATE_STRATEGY, 20, two='two')
@@ -413,7 +496,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertTrue(obj.id)
def test_generate_batch_stub(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.generate_batch(factory.STUB_STRATEGY, 20, two='two')
@@ -427,7 +512,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(hasattr(obj, 'id'))
def test_simple_generate_build(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.simple_generate(False)
@@ -435,7 +522,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(test_model.id)
def test_simple_generate_create(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
test_model = TestModelFactory.simple_generate(True)
@@ -443,7 +532,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertTrue(test_model.id)
def test_simple_generate_batch_build(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.simple_generate_batch(False, 20, two='two')
@@ -457,7 +548,9 @@ class FactoryTestCase(unittest.TestCase):
self.assertFalse(obj.id)
def test_simple_generate_batch_create(self):
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+
one = 'one'
objs = TestModelFactory.simple_generate_batch(True, 20, two='two')
@@ -472,6 +565,8 @@ class FactoryTestCase(unittest.TestCase):
def test_stub_batch(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'one'
two = factory.LazyAttribute(lambda a: a.one + ' two')
three = factory.Sequence(lambda n: int(n))
@@ -489,6 +584,8 @@ class FactoryTestCase(unittest.TestCase):
def testInheritance(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'one'
two = factory.LazyAttribute(lambda a: a.one + ' two')
@@ -509,6 +606,8 @@ class FactoryTestCase(unittest.TestCase):
def testInheritanceWithInheritedClass(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'one'
two = factory.LazyAttribute(lambda a: a.one + ' two')
@@ -524,6 +623,8 @@ class FactoryTestCase(unittest.TestCase):
def testDualInheritance(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = 'one'
class TestOtherFactory(factory.Factory):
@@ -540,12 +641,13 @@ class FactoryTestCase(unittest.TestCase):
self.assertEqual('three', obj.three)
self.assertEqual('four', obj.four)
+ @disable_warnings
def testSetCreationFunction(self):
def creation_function(class_to_create, **kwargs):
return "This doesn't even return an instance of {0}".format(class_to_create.__name__)
- class TestModelFactory(factory.Factory):
- pass
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
TestModelFactory.set_creation_function(creation_function)
@@ -554,6 +656,8 @@ class FactoryTestCase(unittest.TestCase):
def testClassMethodAccessible(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@classmethod
def alt_create(cls, **kwargs):
return kwargs
@@ -562,6 +666,8 @@ class FactoryTestCase(unittest.TestCase):
def testStaticMethodAccessible(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@staticmethod
def alt_create(**kwargs):
return kwargs
@@ -569,16 +675,65 @@ class FactoryTestCase(unittest.TestCase):
self.assertEqual(TestObjectFactory.alt_create(foo=1), {"foo": 1})
+class NonKwargParametersTestCase(unittest.TestCase):
+ def test_build(self):
+ class TestObject(object):
+ def __init__(self, *args, **kwargs):
+ self.args = args
+ self.kwargs = kwargs
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+ FACTORY_ARG_PARAMETERS = ('one', 'two',)
+
+ one = 1
+ two = 2
+ three = 3
+
+ obj = TestObjectFactory.build()
+ self.assertEqual((1, 2), obj.args)
+ self.assertEqual({'three': 3}, obj.kwargs)
+
+ def test_create(self):
+ class TestObject(object):
+ def __init__(self, *args, **kwargs):
+ self.args = None
+ self.kwargs = None
+
+ @classmethod
+ def create(cls, *args, **kwargs):
+ inst = cls()
+ inst.args = args
+ inst.kwargs = kwargs
+ return inst
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+ FACTORY_ARG_PARAMETERS = ('one', 'two')
+
+ one = 1
+ two = 2
+ three = 3
+
+ @classmethod
+ def _create(cls, target_class, *args, **kwargs):
+ return target_class.create(*args, **kwargs)
+
+ obj = TestObjectFactory.create()
+ self.assertEqual((1, 2), obj.args)
+ self.assertEqual({'three': 3}, obj.kwargs)
+
+
class SubFactoryTestCase(unittest.TestCase):
def testSubFactory(self):
- class TestModel2(FakeDjangoModel):
+ class TestModel2(FakeModel):
pass
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
FACTORY_FOR = TestModel
one = 3
- class TestModel2Factory(factory.Factory):
+ class TestModel2Factory(FakeModelFactory):
FACTORY_FOR = TestModel2
two = factory.SubFactory(TestModelFactory, one=1)
@@ -588,13 +743,13 @@ class SubFactoryTestCase(unittest.TestCase):
self.assertEqual(1, test_model.two.id)
def testSubFactoryWithLazyFields(self):
- class TestModel2(FakeDjangoModel):
+ class TestModel2(FakeModel):
pass
- class TestModelFactory(factory.Factory):
+ class TestModelFactory(FakeModelFactory):
FACTORY_FOR = TestModel
- class TestModel2Factory(factory.Factory):
+ class TestModel2Factory(FakeModelFactory):
FACTORY_FOR = TestModel2
two = factory.SubFactory(TestModelFactory,
one=factory.Sequence(lambda n: 'x%sx' % n),
@@ -605,7 +760,7 @@ class SubFactoryTestCase(unittest.TestCase):
self.assertEqual('x0x', test_model.two.one)
self.assertEqual('x0xx0x', test_model.two.two)
- def testSubFactoryOverriding(self):
+ def testSubFactoryAndSequence(self):
class TestObject(object):
def __init__(self, **kwargs):
for k, v in kwargs.iteritems():
@@ -614,9 +769,36 @@ class SubFactoryTestCase(unittest.TestCase):
class TestObjectFactory(factory.Factory):
FACTORY_FOR = TestObject
+ one = factory.Sequence(lambda n: int(n))
+
class WrappingTestObjectFactory(factory.Factory):
FACTORY_FOR = TestObject
+ wrapped = factory.SubFactory(TestObjectFactory)
+
+ wrapping = WrappingTestObjectFactory.build()
+ self.assertEqual(0, wrapping.wrapped.one)
+ wrapping = WrappingTestObjectFactory.build()
+ self.assertEqual(1, wrapping.wrapped.one)
+
+ def testSubFactoryOverriding(self):
+ class TestObject(object):
+ def __init__(self, **kwargs):
+ for k, v in kwargs.iteritems():
+ setattr(self, k, v)
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
+
+ class OtherTestObject(object):
+ def __init__(self, **kwargs):
+ for k, v in kwargs.iteritems():
+ setattr(self, k, v)
+
+ class WrappingTestObjectFactory(factory.Factory):
+ FACTORY_FOR = OtherTestObject
+
wrapped = factory.SubFactory(TestObjectFactory, two=2, four=4)
wrapped__two = 4
wrapped__three = 3
@@ -759,11 +941,85 @@ class SubFactoryTestCase(unittest.TestCase):
self.assertEqual(outer.side_a.inner_from_a.a, outer.foo * 2)
self.assertEqual(outer.side_a.inner_from_a.b, 4)
+ def test_nonstrict_container_attribute(self):
+ class TestModel2(FakeModel):
+ pass
+
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+ one = 3
+ two = factory.ContainerAttribute(lambda obj, containers: len(containers or []), strict=False)
+
+ class TestModel2Factory(FakeModelFactory):
+ FACTORY_FOR = TestModel2
+ one = 1
+ two = factory.SubFactory(TestModelFactory, one=1)
+
+ obj = TestModel2Factory.build()
+ self.assertEqual(1, obj.one)
+ self.assertEqual(1, obj.two.one)
+ self.assertEqual(1, obj.two.two)
+
+ obj = TestModelFactory()
+ self.assertEqual(3, obj.one)
+ self.assertEqual(0, obj.two)
+
+ def test_strict_container_attribute(self):
+ class TestModel2(FakeModel):
+ pass
+
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+ one = 3
+ two = factory.ContainerAttribute(lambda obj, containers: len(containers or []), strict=True)
+
+ class TestModel2Factory(FakeModelFactory):
+ FACTORY_FOR = TestModel2
+ one = 1
+ two = factory.SubFactory(TestModelFactory, one=1)
+
+ obj = TestModel2Factory.build()
+ self.assertEqual(1, obj.one)
+ self.assertEqual(1, obj.two.one)
+ self.assertEqual(1, obj.two.two)
+
+ self.assertRaises(TypeError, TestModelFactory.build)
+
+ def test_function_container_attribute(self):
+ class TestModel2(FakeModel):
+ pass
+
+ class TestModelFactory(FakeModelFactory):
+ FACTORY_FOR = TestModel
+ one = 3
+
+ @factory.container_attribute
+ def two(self, containers):
+ if containers:
+ return len(containers)
+ return 42
+
+ class TestModel2Factory(FakeModelFactory):
+ FACTORY_FOR = TestModel2
+ one = 1
+ two = factory.SubFactory(TestModelFactory, one=1)
+
+ obj = TestModel2Factory.build()
+ self.assertEqual(1, obj.one)
+ self.assertEqual(1, obj.two.one)
+ self.assertEqual(1, obj.two.two)
+
+ obj = TestModelFactory()
+ self.assertEqual(3, obj.one)
+ self.assertEqual(42, obj.two)
+
class IteratorTestCase(unittest.TestCase):
def test_iterator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.Iterator(xrange(10, 30))
objs = TestObjectFactory.build_batch(20)
@@ -773,6 +1029,8 @@ class IteratorTestCase(unittest.TestCase):
def test_infinite_iterator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.InfiniteIterator(xrange(5))
objs = TestObjectFactory.build_batch(20)
@@ -782,6 +1040,8 @@ class IteratorTestCase(unittest.TestCase):
def test_infinite_iterator_list_comprehension(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.InfiniteIterator([j * 3 for j in xrange(5)])
# Scope bleeding: j will end up in TestObjectFactory's scope.
@@ -790,6 +1050,8 @@ class IteratorTestCase(unittest.TestCase):
def test_infinite_iterator_list_comprehension_protected(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
one = factory.InfiniteIterator([_j * 3 for _j in xrange(5)])
# Scope bleeding : _j will end up in TestObjectFactory's scope.
@@ -801,6 +1063,8 @@ class IteratorTestCase(unittest.TestCase):
def test_iterator_decorator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@factory.iterator
def one():
for i in xrange(10, 50):
@@ -813,6 +1077,8 @@ class IteratorTestCase(unittest.TestCase):
def test_infinite_iterator_decorator(self):
class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
@factory.infinite_iterator
def one():
for i in xrange(5):
@@ -824,6 +1090,150 @@ class IteratorTestCase(unittest.TestCase):
self.assertEqual(i % 5, obj.one)
+class PostGenerationTestCase(unittest.TestCase):
+ def test_post_generation(self):
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
+ one = 1
+
+ @factory.post_generation()
+ def incr_one(self, _create, _increment):
+ self.one += 1
+
+ obj = TestObjectFactory.build()
+ self.assertEqual(2, obj.one)
+ self.assertFalse(hasattr(obj, 'incr_one'))
+
+ obj = TestObjectFactory.build(one=2)
+ self.assertEqual(3, obj.one)
+ self.assertFalse(hasattr(obj, 'incr_one'))
+
+ def test_post_generation_extraction(self):
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
+ one = 1
+
+ @factory.post_generation()
+ def incr_one(self, _create, increment=1):
+ self.one += increment
+
+ obj = TestObjectFactory.build(incr_one=2)
+ self.assertEqual(3, obj.one)
+ self.assertFalse(hasattr(obj, 'incr_one'))
+
+ obj = TestObjectFactory.build(one=2, incr_one=2)
+ self.assertEqual(4, obj.one)
+ self.assertFalse(hasattr(obj, 'incr_one'))
+
+ def test_post_generation_extraction_lambda(self):
+
+ def my_lambda(obj, create, extracted, **kwargs):
+ self.assertTrue(isinstance(obj, TestObject))
+ self.assertFalse(create)
+ self.assertEqual(extracted, 42)
+ self.assertEqual(kwargs, {'foo': 13})
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
+ bar = factory.PostGeneration(my_lambda)
+
+ obj = TestObjectFactory.build(bar=42, bar__foo=13)
+
+ def test_post_generation_method_call(self):
+ calls = []
+
+ class TestObject(object):
+ def __init__(self, one=None, two=None):
+ self.one = one
+ self.two = two
+ self.extra = None
+
+ def call(self, *args, **kwargs):
+ self.extra = (args, kwargs)
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+ one = 3
+ two = 2
+ post_call = factory.PostGenerationMethodCall('call', one=1)
+
+ obj = TestObjectFactory.build()
+ self.assertEqual(3, obj.one)
+ self.assertEqual(2, obj.two)
+ self.assertEqual(((), {'one': 1}), obj.extra)
+
+ obj = TestObjectFactory.build(post_call__one=2, post_call__two=3)
+ self.assertEqual(3, obj.one)
+ self.assertEqual(2, obj.two)
+ self.assertEqual(((), {'one': 2, 'two': 3}), obj.extra)
+
+ def test_related_factory(self):
+ class TestRelatedObject(object):
+ def __init__(self, obj=None, one=None, two=None):
+ obj.related = self
+ self.one = one
+ self.two = two
+ self.three = obj
+
+ class TestRelatedObjectFactory(factory.Factory):
+ FACTORY_FOR = TestRelatedObject
+ one = 1
+ two = factory.LazyAttribute(lambda o: o.one + 1)
+
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+ one = 3
+ two = 2
+ three = factory.RelatedFactory(TestRelatedObjectFactory, name='obj')
+
+ obj = TestObjectFactory.build()
+ # Normal fields
+ self.assertEqual(3, obj.one)
+ self.assertEqual(2, obj.two)
+ # RelatedFactory was built
+ self.assertIsNone(obj.three)
+ self.assertIsNotNone(obj.related)
+ self.assertEqual(1, obj.related.one)
+ self.assertEqual(2, obj.related.two)
+ # RelatedFactory was passed "parent" object
+ self.assertEqual(obj, obj.related.three)
+
+ obj = TestObjectFactory.build(three__one=3)
+ # Normal fields
+ self.assertEqual(3, obj.one)
+ self.assertEqual(2, obj.two)
+ # RelatedFactory was build
+ self.assertIsNone(obj.three)
+ self.assertIsNotNone(obj.related)
+ # three__one was correctly parse
+ self.assertEqual(3, obj.related.one)
+ self.assertEqual(4, obj.related.two)
+ # RelatedFactory received "parent" object
+ self.assertEqual(obj, obj.related.three)
+
+
+class CircularTestCase(unittest.TestCase):
+ def test_example(self):
+ sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+
+ from cyclic import foo
+ f = foo.FooFactory.build(bar__foo=None)
+ self.assertEqual(42, f.x)
+ self.assertEqual(13, f.bar.y)
+ self.assertIsNone(f.bar.foo)
+
+ from cyclic import bar
+ b = bar.BarFactory.build(foo__bar__foo__bar=None)
+ self.assertEqual(13, b.y)
+ self.assertEqual(42, b.foo.x)
+ self.assertEqual(13, b.foo.bar.y)
+ self.assertEqual(42, b.foo.bar.foo.x)
+ self.assertIsNone(b.foo.bar.foo.bar)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_utils.py b/tests/test_utils.py
new file mode 100644
index 0000000..9aaafc1
--- /dev/null
+++ b/tests/test_utils.py
@@ -0,0 +1,232 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2010 Mark Sandstrom
+# Copyright (c) 2011 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.
+
+
+from factory import utils
+
+from .compat import unittest
+
+
+class ExtractDictTestCase(unittest.TestCase):
+ def test_empty_dict(self):
+ self.assertEqual({}, utils.extract_dict('foo', {}))
+
+ def test_unused_key(self):
+ self.assertEqual({}, utils.extract_dict('foo', {'bar__baz': 42}))
+
+ def test_empty_key(self):
+ self.assertEqual({}, utils.extract_dict('', {'foo': 13, 'bar__baz': 42}))
+ d = {'foo': 13, 'bar__baz': 42, '__foo': 1}
+ self.assertEqual({'foo': 1}, utils.extract_dict('', d))
+ self.assertNotIn('__foo', d)
+
+ def test_one_key(self):
+ d = {'foo': 13, 'foo__baz': 42, '__foo': 1}
+ self.assertEqual({'baz': 42}, utils.extract_dict('foo', d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+
+ self.assertEqual({'baz': 42}, utils.extract_dict('foo', d, pop=True))
+ self.assertNotIn('foo__baz', d)
+
+ def test_one_key_excluded(self):
+ d = {'foo': 13, 'foo__baz': 42, '__foo': 1}
+ self.assertEqual({},
+ utils.extract_dict('foo', d, pop=False, exclude=('foo__baz',)))
+ self.assertEqual(42, d['foo__baz'])
+
+ self.assertEqual({},
+ utils.extract_dict('foo', d, pop=True, exclude=('foo__baz',)))
+ self.assertIn('foo__baz', d)
+
+ def test_many_keys(self):
+ d = {'foo': 13, 'foo__baz': 42, 'foo__foo__bar': 2, 'foo__bar': 3, '__foo': 1}
+ self.assertEqual({'foo__bar': 2, 'bar': 3, 'baz': 42},
+ utils.extract_dict('foo', d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+ self.assertEqual(3, d['foo__bar'])
+ self.assertEqual(2, d['foo__foo__bar'])
+
+ self.assertEqual({'foo__bar': 2, 'bar': 3, 'baz': 42},
+ utils.extract_dict('foo', d, pop=True))
+ self.assertNotIn('foo__baz', d)
+ self.assertNotIn('foo__bar', d)
+ self.assertNotIn('foo__foo__bar', d)
+
+ def test_many_keys_excluded(self):
+ d = {'foo': 13, 'foo__baz': 42, 'foo__foo__bar': 2, 'foo__bar': 3, '__foo': 1}
+ self.assertEqual({'foo__bar': 2, 'baz': 42},
+ utils.extract_dict('foo', d, pop=False, exclude=('foo__bar', 'bar')))
+ self.assertEqual(42, d['foo__baz'])
+ self.assertEqual(3, d['foo__bar'])
+ self.assertEqual(2, d['foo__foo__bar'])
+
+ self.assertEqual({'foo__bar': 2, 'baz': 42},
+ utils.extract_dict('foo', d, pop=True, exclude=('foo__bar', 'bar')))
+ self.assertNotIn('foo__baz', d)
+ self.assertIn('foo__bar', d)
+ self.assertNotIn('foo__foo__bar', d)
+
+
+class MultiExtractDictTestCase(unittest.TestCase):
+ def test_empty_dict(self):
+ self.assertEqual({'foo': {}}, utils.multi_extract_dict(['foo'], {}))
+
+ def test_unused_key(self):
+ self.assertEqual({'foo': {}},
+ utils.multi_extract_dict(['foo'], {'bar__baz': 42}))
+ self.assertEqual({'foo': {}, 'baz': {}},
+ utils.multi_extract_dict(['foo', 'baz'], {'bar__baz': 42}))
+
+ def test_no_key(self):
+ self.assertEqual({}, utils.multi_extract_dict([], {'bar__baz': 42}))
+
+ def test_empty_key(self):
+ self.assertEqual({'': {}},
+ utils.multi_extract_dict([''], {'foo': 13, 'bar__baz': 42}))
+
+ d = {'foo': 13, 'bar__baz': 42, '__foo': 1}
+ self.assertEqual({'': {'foo': 1}},
+ utils.multi_extract_dict([''], d))
+ self.assertNotIn('__foo', d)
+
+ def test_one_extracted(self):
+ d = {'foo': 13, 'foo__baz': 42, '__foo': 1}
+ self.assertEqual({'foo': {'baz': 42}},
+ utils.multi_extract_dict(['foo'], d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+
+ self.assertEqual({'foo': {'baz': 42}},
+ utils.multi_extract_dict(['foo'], d, pop=True))
+ self.assertNotIn('foo__baz', d)
+
+ def test_many_extracted(self):
+ d = {'foo': 13, 'foo__baz': 42, 'foo__foo__bar': 2, 'foo__bar': 3, '__foo': 1}
+ self.assertEqual({'foo': {'foo__bar': 2, 'bar': 3, 'baz': 42}},
+ utils.multi_extract_dict(['foo'], d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+ self.assertEqual(3, d['foo__bar'])
+ self.assertEqual(2, d['foo__foo__bar'])
+
+ self.assertEqual({'foo': {'foo__bar': 2, 'bar': 3, 'baz': 42}},
+ utils.multi_extract_dict(['foo'], d, pop=True))
+ self.assertNotIn('foo__baz', d)
+ self.assertNotIn('foo__bar', d)
+ self.assertNotIn('foo__foo__bar', d)
+
+ def test_many_keys_one_extracted(self):
+ d = {'foo': 13, 'foo__baz': 42, '__foo': 1}
+ self.assertEqual({'foo': {'baz': 42}, 'baz': {}},
+ utils.multi_extract_dict(['foo', 'baz'], d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+
+ self.assertEqual({'foo': {'baz': 42}, 'baz': {}},
+ utils.multi_extract_dict(['foo', 'baz'], d, pop=True))
+ self.assertNotIn('foo__baz', d)
+
+ def test_many_keys_many_extracted(self):
+ d = {
+ 'foo': 13,
+ 'foo__baz': 42, 'foo__foo__bar': 2, 'foo__bar': 3,
+ 'bar__foo': 1, 'bar__bar__baz': 4,
+ }
+
+ self.assertEqual(
+ {
+ 'foo': {'foo__bar': 2, 'bar': 3, 'baz': 42},
+ 'bar': {'foo': 1, 'bar__baz': 4},
+ 'baz': {}
+ },
+ utils.multi_extract_dict(['foo', 'bar', 'baz'], d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+ self.assertEqual(3, d['foo__bar'])
+ self.assertEqual(2, d['foo__foo__bar'])
+ self.assertEqual(1, d['bar__foo'])
+ self.assertEqual(4, d['bar__bar__baz'])
+
+ self.assertEqual(
+ {
+ 'foo': {'foo__bar': 2, 'bar': 3, 'baz': 42},
+ 'bar': {'foo': 1, 'bar__baz': 4},
+ 'baz': {}
+ },
+ utils.multi_extract_dict(['foo', 'bar', 'baz'], d, pop=True))
+ self.assertNotIn('foo__baz', d)
+ self.assertNotIn('foo__bar', d)
+ self.assertNotIn('foo__foo__bar', d)
+ self.assertNotIn('bar__foo', d)
+ self.assertNotIn('bar__bar__baz', d)
+
+ def test_son_in_list(self):
+ """Make sure that prefixes are used in decreasing match length order."""
+ d = {
+ 'foo': 13,
+ 'foo__baz': 42, 'foo__foo__bar': 2, 'foo__bar': 3,
+ 'bar__foo': 1, 'bar__bar__baz': 4,
+ }
+
+ self.assertEqual(
+ {
+ 'foo__foo': {'bar': 2},
+ 'foo': {'bar': 3, 'baz': 42},
+ 'bar__bar': {'baz': 4},
+ 'bar': {'foo': 1},
+ 'baz': {}
+ },
+ utils.multi_extract_dict(
+ ['foo', 'bar', 'baz', 'foo__foo', 'bar__bar'], d, pop=False))
+ self.assertEqual(42, d['foo__baz'])
+ self.assertEqual(3, d['foo__bar'])
+ self.assertEqual(2, d['foo__foo__bar'])
+ self.assertEqual(1, d['bar__foo'])
+ self.assertEqual(4, d['bar__bar__baz'])
+
+ self.assertEqual(
+ {
+ 'foo__foo': {'bar': 2},
+ 'foo': {'bar': 3, 'baz': 42},
+ 'bar__bar': {'baz': 4},
+ 'bar': {'foo': 1},
+ 'baz': {}
+ },
+ utils.multi_extract_dict(
+ ['foo', 'bar', 'baz', 'foo__foo', 'bar__bar'], d, pop=True))
+ self.assertNotIn('foo__baz', d)
+ self.assertNotIn('foo__bar', d)
+ self.assertNotIn('foo__foo__bar', d)
+ self.assertNotIn('bar__foo', d)
+ self.assertNotIn('bar__bar__baz', d)
+
+
+class ImportObjectTestCase(unittest.TestCase):
+ def test_datetime(self):
+ imported = utils.import_object('datetime', 'date')
+ import datetime
+ d = datetime.date
+ self.assertEqual(d, imported)
+
+ def test_unknown_attribute(self):
+ self.assertRaises(AttributeError, utils.import_object,
+ 'datetime', 'foo')
+
+ def test_invalid_module(self):
+ self.assertRaises(ImportError, utils.import_object,
+ 'this-is-an-invalid-module', '__name__')