diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_alchemy.py | 32 | ||||
-rw-r--r-- | tests/test_base.py | 22 | ||||
-rw-r--r-- | tests/test_containers.py | 129 | ||||
-rw-r--r-- | tests/test_django.py | 16 | ||||
-rw-r--r-- | tests/test_fuzzy.py | 13 | ||||
-rw-r--r-- | tests/test_using.py | 186 |
6 files changed, 298 insertions, 100 deletions
diff --git a/tests/test_alchemy.py b/tests/test_alchemy.py index 9d7288a..5d8f275 100644 --- a/tests/test_alchemy.py +++ b/tests/test_alchemy.py @@ -23,6 +23,7 @@ import factory from .compat import unittest +import mock try: @@ -55,6 +56,16 @@ class StandardFactory(SQLAlchemyModelFactory): foo = factory.Sequence(lambda n: 'foo%d' % n) +class ForceFlushingStandardFactory(SQLAlchemyModelFactory): + class Meta: + model = models.StandardModel + sqlalchemy_session = mock.MagicMock() + force_flush = True + + id = factory.Sequence(lambda n: n) + foo = factory.Sequence(lambda n: 'foo%d' % n) + + class NonIntegerPkFactory(SQLAlchemyModelFactory): class Meta: model = models.NonIntegerPk @@ -103,6 +114,27 @@ class SQLAlchemyPkSequenceTestCase(unittest.TestCase): @unittest.skipIf(sqlalchemy is None, "SQLalchemy not installed.") +class SQLAlchemyForceFlushTestCase(unittest.TestCase): + def setUp(self): + super(SQLAlchemyForceFlushTestCase, self).setUp() + ForceFlushingStandardFactory.reset_sequence(1) + ForceFlushingStandardFactory._meta.sqlalchemy_session.rollback() + ForceFlushingStandardFactory._meta.sqlalchemy_session.reset_mock() + + def test_force_flush_called(self): + self.assertFalse(ForceFlushingStandardFactory._meta.sqlalchemy_session.flush.called) + ForceFlushingStandardFactory.create() + self.assertTrue(ForceFlushingStandardFactory._meta.sqlalchemy_session.flush.called) + + def test_force_flush_not_called(self): + ForceFlushingStandardFactory._meta.force_flush = False + self.assertFalse(ForceFlushingStandardFactory._meta.sqlalchemy_session.flush.called) + ForceFlushingStandardFactory.create() + self.assertFalse(ForceFlushingStandardFactory._meta.sqlalchemy_session.flush.called) + ForceFlushingStandardFactory._meta.force_flush = True + + +@unittest.skipIf(sqlalchemy is None, "SQLalchemy not installed.") class SQLAlchemyNonIntegerPkTestCase(unittest.TestCase): def setUp(self): super(SQLAlchemyNonIntegerPkTestCase, self).setUp() diff --git a/tests/test_base.py b/tests/test_base.py index 24f64e5..a3b3704 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -24,6 +24,7 @@ import warnings from factory import base from factory import declarations +from factory import errors from .compat import unittest @@ -63,7 +64,7 @@ class TestModel(FakeDjangoModel): class SafetyTestCase(unittest.TestCase): def test_base_factory(self): - self.assertRaises(base.FactoryError, base.BaseFactory) + self.assertRaises(errors.FactoryError, base.BaseFactory) class AbstractFactoryTestCase(unittest.TestCase): @@ -88,8 +89,8 @@ class AbstractFactoryTestCase(unittest.TestCase): class TestObjectFactory(base.Factory): pass - self.assertRaises(base.FactoryError, TestObjectFactory.build) - self.assertRaises(base.FactoryError, TestObjectFactory.create) + self.assertRaises(errors.FactoryError, TestObjectFactory.build) + self.assertRaises(errors.FactoryError, TestObjectFactory.create) def test_abstract_factory_not_inherited(self): """abstract=True isn't propagated to child classes.""" @@ -110,8 +111,8 @@ class AbstractFactoryTestCase(unittest.TestCase): abstract = False model = None - self.assertRaises(base.FactoryError, TestObjectFactory.build) - self.assertRaises(base.FactoryError, TestObjectFactory.create) + self.assertRaises(errors.FactoryError, TestObjectFactory.build) + self.assertRaises(errors.FactoryError, TestObjectFactory.create) class OptionsTests(unittest.TestCase): @@ -134,25 +135,28 @@ class OptionsTests(unittest.TestCase): self.assertEqual(AbstractFactory, AbstractFactory._meta.counter_reference) def test_declaration_collecting(self): - lazy = declarations.LazyAttribute(lambda _o: 1) + lazy = declarations.LazyFunction(int) + lazy2 = declarations.LazyAttribute(lambda _o: 1) postgen = declarations.PostGenerationDeclaration() class AbstractFactory(base.Factory): x = 1 y = lazy + y2 = lazy2 z = postgen # Declarations aren't removed self.assertEqual(1, AbstractFactory.x) self.assertEqual(lazy, AbstractFactory.y) + self.assertEqual(lazy2, AbstractFactory.y2) self.assertEqual(postgen, AbstractFactory.z) # And are available in class Meta - self.assertEqual({'x': 1, 'y': lazy}, AbstractFactory._meta.declarations) + self.assertEqual({'x': 1, 'y': lazy, 'y2': lazy2}, AbstractFactory._meta.declarations) self.assertEqual({'z': postgen}, AbstractFactory._meta.postgen_declarations) def test_inherited_declaration_collecting(self): - lazy = declarations.LazyAttribute(lambda _o: 1) + lazy = declarations.LazyFunction(int) lazy2 = declarations.LazyAttribute(lambda _o: 2) postgen = declarations.PostGenerationDeclaration() postgen2 = declarations.PostGenerationDeclaration() @@ -178,7 +182,7 @@ class OptionsTests(unittest.TestCase): self.assertEqual({'z': postgen, 'b': postgen2}, OtherFactory._meta.postgen_declarations) def test_inherited_declaration_shadowing(self): - lazy = declarations.LazyAttribute(lambda _o: 1) + lazy = declarations.LazyFunction(int) lazy2 = declarations.LazyAttribute(lambda _o: 2) postgen = declarations.PostGenerationDeclaration() postgen2 = declarations.PostGenerationDeclaration() diff --git a/tests/test_containers.py b/tests/test_containers.py index 9107b0d..ea6ddff 100644 --- a/tests/test_containers.py +++ b/tests/test_containers.py @@ -23,6 +23,7 @@ from factory import base from factory import containers from factory import declarations +from factory import errors from .compat import unittest @@ -91,7 +92,7 @@ class LazyStubTestCase(unittest.TestCase): 'two': self.LazyAttr('one'), }) - self.assertRaises(containers.CyclicDefinitionError, getattr, stub, 'one') + self.assertRaises(errors.CyclicDefinitionError, getattr, stub, 'one') def test_cyclic_definition_rescue(self): class LazyAttrDefault(self.LazyAttr): @@ -124,97 +125,56 @@ class LazyStubTestCase(unittest.TestCase): class AttributeBuilderTestCase(unittest.TestCase): - def test_empty(self): - """Tests building attributes from an empty definition.""" + + def make_fake_factory(self, decls): + class Meta: + declarations = decls + parameters = {} + parameters_dependencies = {} class FakeFactory(object): - @classmethod - def declarations(cls, extra): - return extra + _meta = Meta @classmethod def _generate_next_sequence(cls): return 1 + return FakeFactory + + def test_empty(self): + """Tests building attributes from an empty definition.""" + + FakeFactory = self.make_fake_factory({}) ab = containers.AttributeBuilder(FakeFactory) self.assertEqual({}, ab.build(create=False)) def test_factory_defined(self): - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': 1} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 - + FakeFactory = self.make_fake_factory({'one': 1}) ab = containers.AttributeBuilder(FakeFactory) + self.assertEqual({'one': 1}, ab.build(create=False)) def test_extended(self): - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': 1} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 - + FakeFactory = self.make_fake_factory({'one': 1}) ab = containers.AttributeBuilder(FakeFactory, {'two': 2}) self.assertEqual({'one': 1, 'two': 2}, ab.build(create=False)) def test_overridden(self): - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': 1} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 - + FakeFactory = self.make_fake_factory({'one': 1}) ab = containers.AttributeBuilder(FakeFactory, {'one': 2}) self.assertEqual({'one': 2}, ab.build(create=False)) def test_factory_defined_sequence(self): seq = declarations.Sequence(lambda n: 'xx%d' % n) - - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': seq} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 + FakeFactory = self.make_fake_factory({'one': seq}) ab = containers.AttributeBuilder(FakeFactory) self.assertEqual({'one': 'xx1'}, ab.build(create=False)) def test_additionnal_sequence(self): seq = declarations.Sequence(lambda n: 'xx%d' % n) - - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': 1} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 + FakeFactory = self.make_fake_factory({'one': 1}) ab = containers.AttributeBuilder(FakeFactory, extra={'two': seq}) self.assertEqual({'one': 1, 'two': 'xx1'}, ab.build(create=False)) @@ -222,34 +182,27 @@ class AttributeBuilderTestCase(unittest.TestCase): def test_replaced_sequence(self): seq = declarations.Sequence(lambda n: 'xx%d' % n) seq2 = declarations.Sequence(lambda n: 'yy%d' % n) - - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': seq} - d.update(extra) - return d - - @classmethod - def _generate_next_sequence(cls): - return 1 + FakeFactory = self.make_fake_factory({'one': seq}) ab = containers.AttributeBuilder(FakeFactory, extra={'one': seq2}) self.assertEqual({'one': 'yy1'}, ab.build(create=False)) - def test_lazy_attribute(self): - la = declarations.LazyAttribute(lambda a: a.one * 2) + def test_lazy_function(self): + lf = declarations.LazyFunction(int) + FakeFactory = self.make_fake_factory({'one': 1, 'two': lf}) - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': 1, 'two': la} - d.update(extra) - return d + ab = containers.AttributeBuilder(FakeFactory) + self.assertEqual({'one': 1, 'two': 0}, ab.build(create=False)) - @classmethod - def _generate_next_sequence(cls): - return 1 + ab = containers.AttributeBuilder(FakeFactory, {'one': 4}) + self.assertEqual({'one': 4, 'two': 0}, ab.build(create=False)) + + ab = containers.AttributeBuilder(FakeFactory, {'one': 4, 'three': lf}) + self.assertEqual({'one': 4, 'two': 0, 'three': 0}, ab.build(create=False)) + + def test_lazy_attribute(self): + la = declarations.LazyAttribute(lambda a: a.one * 2) + FakeFactory = self.make_fake_factory({'one': 1, 'two': la}) ab = containers.AttributeBuilder(FakeFactory) self.assertEqual({'one': 1, 'two': 2}, ab.build(create=False)) @@ -265,18 +218,12 @@ class AttributeBuilderTestCase(unittest.TestCase): pass sf = declarations.SubFactory(FakeInnerFactory) - - class FakeFactory(object): - @classmethod - def declarations(cls, extra): - d = {'one': sf, 'two': 2} - d.update(extra) - return d + FakeFactory = self.make_fake_factory({'one': sf, 'two': 2}) ab = containers.AttributeBuilder(FakeFactory, {'one__blah': 1, 'two__bar': 2}) self.assertTrue(ab.has_subfields(sf)) self.assertEqual(['one'], list(ab._subfields.keys())) - self.assertEqual(2, ab._attrs['two__bar']) + self.assertEqual(2, ab._declarations['two__bar']) def test_sub_factory(self): pass diff --git a/tests/test_django.py b/tests/test_django.py index 103df91..08349b9 100644 --- a/tests/test_django.py +++ b/tests/test_django.py @@ -362,6 +362,22 @@ class DjangoAbstractBaseSequenceTestCase(django_test.TestCase): obj = ConcreteGrandSonFactory() self.assertEqual(1, obj.pk) + def test_optional_abstract(self): + """Users need not describe the factory for an abstract model as abstract.""" + class AbstractBaseFactory(factory.django.DjangoModelFactory): + class Meta: + model = models.AbstractBase + + foo = factory.Sequence(lambda n: "foo%d" % n) + + class ConcreteSonFactory(AbstractBaseFactory): + class Meta: + model = models.ConcreteSon + + obj = ConcreteSonFactory() + self.assertEqual(1, obj.pk) + self.assertEqual("foo0", obj.foo) + @unittest.skipIf(django is None, "Django not installed.") class DjangoRelatedFieldTestCase(django_test.TestCase): diff --git a/tests/test_fuzzy.py b/tests/test_fuzzy.py index 3f9c434..4c3873a 100644 --- a/tests/test_fuzzy.py +++ b/tests/test_fuzzy.py @@ -189,6 +189,19 @@ class FuzzyDecimalTestCase(unittest.TestCase): self.assertEqual(decimal.Decimal('8.001').quantize(decimal.Decimal(10) ** -3), res) + @unittest.skipIf(compat.PY2, "decimal.FloatOperation was added in Py3") + def test_no_approximation(self): + """We should not go through floats in our fuzzy calls unless actually needed.""" + fuzz = fuzzy.FuzzyDecimal(0, 10) + + decimal_context = decimal.getcontext() + old_traps = decimal_context.traps[decimal.FloatOperation] + try: + decimal_context.traps[decimal.FloatOperation] = True + fuzz.evaluate(2, None, None) + finally: + decimal_context.traps[decimal.FloatOperation] = old_traps + class FuzzyDateTestCase(unittest.TestCase): @classmethod diff --git a/tests/test_using.py b/tests/test_using.py index c7d2b85..0ce29e9 100644 --- a/tests/test_using.py +++ b/tests/test_using.py @@ -27,6 +27,7 @@ import sys import warnings import factory +from factory import errors from .compat import is_python2, unittest from . import tools @@ -40,6 +41,15 @@ class TestObject(object): self.four = four self.five = five + def as_dict(self): + return dict( + one=self.one, + two=self.two, + three=self.three, + four=self.four, + five=self.five, + ) + class FakeModel(object): @classmethod @@ -292,6 +302,19 @@ class SimpleBuildTestCase(unittest.TestCase): self.assertEqual(obj.three, 5) self.assertEqual(obj.four, None) + def test_build_to_dict(self): + # We have a generic factory + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + one = 'one' + two = factory.LazyAttribute(lambda o: o.one * 2) + + # Now, get a dict out of it + obj = factory.build(dict, FACTORY_CLASS=TestObjectFactory) + self.assertEqual({'one': 'one', 'two': 'oneone'}, obj) + class UsingFactoryTestCase(unittest.TestCase): def test_attribute(self): @@ -1092,6 +1115,119 @@ class KwargAdjustTestCase(unittest.TestCase): self.assertEqual(42, obj.attributes) +class TraitTestCase(unittest.TestCase): + def test_traits(self): + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + class Params: + even = factory.Trait(two=True, four=True) + odd = factory.Trait(one=True, three=True, five=True) + + obj1 = TestObjectFactory() + self.assertEqual(obj1.as_dict(), + dict(one=None, two=None, three=None, four=None, five=None)) + + obj2 = TestObjectFactory(even=True) + self.assertEqual(obj2.as_dict(), + dict(one=None, two=True, three=None, four=True, five=None)) + + obj3 = TestObjectFactory(odd=True) + self.assertEqual(obj3.as_dict(), + dict(one=True, two=None, three=True, four=None, five=True)) + + obj4 = TestObjectFactory(even=True, odd=True) + self.assertEqual(obj4.as_dict(), + dict(one=True, two=True, three=True, four=True, five=True)) + + obj5 = TestObjectFactory(odd=True, two=True) + self.assertEqual(obj5.as_dict(), + dict(one=True, two=True, three=True, four=None, five=True)) + + def test_traits_inheritance(self): + """A trait can be set in an inherited class.""" + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + class Params: + even = factory.Trait(two=True, four=True) + odd = factory.Trait(one=True, three=True, five=True) + + class EvenObjectFactory(TestObjectFactory): + even = True + + # Simple call + obj1 = EvenObjectFactory() + self.assertEqual(obj1.as_dict(), + dict(one=None, two=True, three=None, four=True, five=None)) + + # Force-disable it + obj2 = EvenObjectFactory(even=False) + self.assertEqual(obj2.as_dict(), + dict(one=None, two=None, three=None, four=None, five=None)) + + def test_traits_override(self): + """Override a trait in a subclass.""" + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + class Params: + even = factory.Trait(two=True, four=True) + odd = factory.Trait(one=True, three=True, five=True) + + class WeirdMathFactory(TestObjectFactory): + class Params: + # Here, one is even. + even = factory.Trait(two=True, four=True, one=True) + + obj = WeirdMathFactory(even=True) + self.assertEqual(obj.as_dict(), + dict(one=True, two=True, three=None, four=True, five=None)) + + def test_traits_chaining(self): + """Use a trait to enable other traits.""" + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + class Params: + even = factory.Trait(two=True, four=True) + odd = factory.Trait(one=True, three=True, five=True) + full = factory.Trait(even=True, odd=True) + + # Setting "full" should enable all fields. + obj = TestObjectFactory(full=True) + self.assertEqual(obj.as_dict(), + dict(one=True, two=True, three=True, four=True, five=True)) + + # Does it break usual patterns? + obj1 = TestObjectFactory() + self.assertEqual(obj1.as_dict(), + dict(one=None, two=None, three=None, four=None, five=None)) + + obj2 = TestObjectFactory(even=True) + self.assertEqual(obj2.as_dict(), + dict(one=None, two=True, three=None, four=True, five=None)) + + obj3 = TestObjectFactory(odd=True) + self.assertEqual(obj3.as_dict(), + dict(one=True, two=None, three=True, four=None, five=True)) + + def test_prevent_cyclic_traits(self): + + with self.assertRaises(errors.CyclicDefinitionError): + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + + class Params: + a = factory.Trait(b=True, one=True) + b = factory.Trait(a=True, two=True) + + class SubFactoryTestCase(unittest.TestCase): def test_sub_factory(self): class TestModel2(FakeModel): @@ -1132,6 +1268,26 @@ class SubFactoryTestCase(unittest.TestCase): self.assertEqual('x0x', test_model.two.one) self.assertEqual('x0xx0x', test_model.two.two) + def test_sub_factory_with_lazy_fields_access_factory_parent(self): + class TestModel2(FakeModel): + pass + + class TestModelFactory(FakeModelFactory): + class Meta: + model = TestModel + one = 3 + + class TestModel2Factory(FakeModelFactory): + class Meta: + model = TestModel2 + one = 'parent' + child = factory.SubFactory(TestModelFactory, + one=factory.LazyAttribute(lambda o: '%s child' % o.factory_parent.one), + ) + + test_model = TestModel2Factory() + self.assertEqual('parent child', test_model.child.one) + def test_sub_factory_and_sequence(self): class TestObject(object): def __init__(self, **kwargs): @@ -1924,6 +2080,36 @@ class PostGenerationTestCase(unittest.TestCase): self.assertEqual(3, related.one) self.assertEqual(4, related.two) + def test_related_factory_selfattribute(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): + class Meta: + model = TestRelatedObject + one = 1 + two = factory.LazyAttribute(lambda o: o.one + 1) + + class TestObjectFactory(factory.Factory): + class Meta: + model = TestObject + one = 3 + two = 2 + three = factory.RelatedFactory(TestRelatedObjectFactory, 'obj', + two=factory.SelfAttribute('obj.two'), + ) + + obj = TestObjectFactory.build(two=4) + self.assertEqual(3, obj.one) + self.assertEqual(4, obj.two) + self.assertEqual(1, obj.related.one) + self.assertEqual(4, obj.related.two) + + class RelatedFactoryExtractionTestCase(unittest.TestCase): def setUp(self): |