diff options
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | factory/django.py | 4 | ||||
-rw-r--r-- | tests/__init__.py | 1 | ||||
-rw-r--r-- | tests/djapp/__init__.py | 0 | ||||
-rw-r--r-- | tests/djapp/models.py | 36 | ||||
-rw-r--r-- | tests/djapp/settings.py | 35 | ||||
-rw-r--r-- | tests/test_django.py | 165 |
7 files changed, 242 insertions, 2 deletions
diff --git a/.travis.yml b/.travis.yml index d0735d8..3c784ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,8 @@ script: - python setup.py test install: - - "if [[ $TRAVIS_PYTHON_VERSION = 2.6 ]]; then pip install unittest2 --use-mirrors; fi" + - if [[ $TRAVIS_PYTHON_VERSION = 2.6 ]]; then pip install unittest2 --use-mirrors; fi + - pip install Django --use-mirrors notifications: email: false diff --git a/factory/django.py b/factory/django.py index 351cb76..3eabca1 100644 --- a/factory/django.py +++ b/factory/django.py @@ -59,7 +59,9 @@ class DjangoModelFactory(base.Factory): try: return 1 + manager.values_list('pk', flat=True ).order_by('-pk')[0] - except IndexError: + except (IndexError, TypeError): + # IndexError: No instance exist yet + # TypeError: pk isn't an integer type return 1 @classmethod diff --git a/tests/__init__.py b/tests/__init__.py index 3c620d6..1529e21 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,6 +4,7 @@ from .test_base import * from .test_containers import * from .test_declarations import * +from .test_django import * from .test_fuzzy import * from .test_using import * from .test_utils import * diff --git a/tests/djapp/__init__.py b/tests/djapp/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/djapp/__init__.py diff --git a/tests/djapp/models.py b/tests/djapp/models.py new file mode 100644 index 0000000..c107add --- /dev/null +++ b/tests/djapp/models.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# 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. + + +"""Helpers for testing django apps.""" + + +from django.db import models + +class StandardModel(models.Model): + foo = models.CharField(max_length=20) + + +class NonIntegerPk(models.Model): + foo = models.CharField(max_length=20, primary_key=True) + bar = models.CharField(max_length=20, blank=True) + + diff --git a/tests/djapp/settings.py b/tests/djapp/settings.py new file mode 100644 index 0000000..787d3f3 --- /dev/null +++ b/tests/djapp/settings.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# 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. +"""Settings for factory_boy/Django tests.""" + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + }, +} + + +INSTALLED_APPS = [ + 'tests.djapp' +] + + +SECRET_KEY = 'testing.' diff --git a/tests/test_django.py b/tests/test_django.py new file mode 100644 index 0000000..aacde76 --- /dev/null +++ b/tests/test_django.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# 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. +"""Tests for factory_boy/Django interactions.""" + +import os + +import factory +import factory.django + + +try: + import django +except ImportError: + django = None + + +from .compat import is_python2, unittest +from . import tools + + +if django is not None: + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tests.djapp.settings') + + from django import test as django_test + from django.test import simple as django_test_simple + from django.test import utils as django_test_utils + from .djapp import models +else: + django_test = unittest + + class Fake(object): + pass + + models = Fake() + models.StandardModel = Fake + models.NonIntegerPk = Fake + + +test_state = {} + + +def setUpModule(): + if django is None: + return + django_test_utils.setup_test_environment() + runner = django_test_simple.DjangoTestSuiteRunner() + runner_state = runner.setup_databases() + test_state.update({ + 'runner': runner, + 'runner_state': runner_state, + }) + + +def tearDownModule(): + if django is None: + return + runner = test_state['runner'] + runner_state = test_state['runner_state'] + runner.teardown_databases(runner_state) + django_test_utils.teardown_test_environment() + + +class StandardFactory(factory.django.DjangoModelFactory): + FACTORY_FOR = models.StandardModel + + foo = factory.Sequence(lambda n: "foo%d" % n) + + +class NonIntegerPkFactory(factory.django.DjangoModelFactory): + FACTORY_FOR = models.NonIntegerPk + + foo = factory.Sequence(lambda n: "foo%d" % n) + bar = '' + + +@unittest.skipIf(django is None, "Django not installed.") +class DjangoPkSequenceTestCase(django_test.TestCase): + def setUp(self): + super(DjangoPkSequenceTestCase, self).setUp() + StandardFactory.reset_sequence() + + def test_pk_first(self): + std = StandardFactory.build() + self.assertEqual('foo1', std.foo) + + def test_pk_many(self): + std1 = StandardFactory.build() + std2 = StandardFactory.build() + self.assertEqual('foo1', std1.foo) + self.assertEqual('foo2', std2.foo) + + def test_pk_creation(self): + std1 = StandardFactory.create() + self.assertEqual('foo1', std1.foo) + self.assertEqual(1, std1.pk) + + StandardFactory.reset_sequence() + std2 = StandardFactory.create() + self.assertEqual('foo2', std2.foo) + self.assertEqual(2, std2.pk) + + def test_pk_force_value(self): + std1 = StandardFactory.create(pk=10) + self.assertEqual('foo1', std1.foo) # sequence was set before pk + self.assertEqual(10, std1.pk) + + StandardFactory.reset_sequence() + std2 = StandardFactory.create() + self.assertEqual('foo11', std2.foo) + self.assertEqual(11, std2.pk) + + +@unittest.skipIf(django is None, "Django not installed.") +class DjangoNonIntegerPkTestCase(django_test.TestCase): + def setUp(self): + super(DjangoNonIntegerPkTestCase, self).setUp() + NonIntegerPkFactory.reset_sequence() + + def test_first(self): + nonint = NonIntegerPkFactory.build() + self.assertEqual('foo1', nonint.foo) + + def test_many(self): + nonint1 = NonIntegerPkFactory.build() + nonint2 = NonIntegerPkFactory.build() + + self.assertEqual('foo1', nonint1.foo) + self.assertEqual('foo2', nonint2.foo) + + def test_creation(self): + nonint1 = NonIntegerPkFactory.create() + self.assertEqual('foo1', nonint1.foo) + self.assertEqual('foo1', nonint1.pk) + + NonIntegerPkFactory.reset_sequence() + nonint2 = NonIntegerPkFactory.build() + self.assertEqual('foo1', nonint2.foo) + + def test_force_pk(self): + nonint1 = NonIntegerPkFactory.create(pk='foo10') + self.assertEqual('foo10', nonint1.foo) + self.assertEqual('foo10', nonint1.pk) + + NonIntegerPkFactory.reset_sequence() + nonint2 = NonIntegerPkFactory.create() + self.assertEqual('foo1', nonint2.foo) + self.assertEqual('foo1', nonint2.pk) |