diff --git a/HISTORY.rst b/HISTORY.rst index 6645e10ed4..3098b6f852 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -224,6 +224,7 @@ of the permission proxy support which is now redundant. - Remove the permissions to grant or revoke a permission to a role. The instead the role edit permission is used. +- Add a test mixin to generate random model primary keys. 3.1.9 (2018-11-01) ================== diff --git a/mayan/apps/common/tests/base.py b/mayan/apps/common/tests/base.py index 82f9f19b21..2fc36e4599 100644 --- a/mayan/apps/common/tests/base.py +++ b/mayan/apps/common/tests/base.py @@ -1,7 +1,6 @@ from __future__ import absolute_import, unicode_literals from django.test import TestCase -from django.urls import reverse from django_downloadview import assert_download_response from mayan.apps.acls.tests.mixins import ACLTestCaseMixin @@ -10,12 +9,12 @@ from mayan.apps.smart_settings.classes import Namespace from .mixins import ( ClientMethodsTestCaseMixin, ContentTypeCheckMixin, DatabaseConversionMixin, - OpenFileCheckTestCaseMixin, TempfileCheckTestCaseMixin, - TestViewTestCaseMixin + OpenFileCheckTestCaseMixin, RandomPrimaryKeyModelMonkeyPatchMixin, + TempfileCheckTestCaseMixin, TestViewTestCaseMixin ) -class BaseTestCase(DatabaseConversionMixin, ACLTestCaseMixin, ContentTypeCheckMixin, OpenFileCheckTestCaseMixin, TempfileCheckTestCaseMixin, TestCase): +class BaseTestCase(RandomPrimaryKeyModelMonkeyPatchMixin, DatabaseConversionMixin, ACLTestCaseMixin, ContentTypeCheckMixin, OpenFileCheckTestCaseMixin, TempfileCheckTestCaseMixin, TestCase): """ This is the most basic test case class any test in the project should use. """ diff --git a/mayan/apps/common/tests/mixins.py b/mayan/apps/common/tests/mixins.py index 621353bd68..9f3fa318f7 100644 --- a/mayan/apps/common/tests/mixins.py +++ b/mayan/apps/common/tests/mixins.py @@ -2,10 +2,12 @@ from __future__ import unicode_literals import glob import os +import random from django.conf import settings from django.conf.urls import url from django.core import management +from django.db import models from django.http import HttpResponse from django.template import Context, Template from django.test.utils import ContextList @@ -138,6 +140,53 @@ class OpenFileCheckTestCaseMixin(object): super(OpenFileCheckTestCaseMixin, self).tearDown() +class RandomPrimaryKeyModelMonkeyPatchMixin(object): + random_primary_key_random_floor = 100 + random_primary_key_random_ceiling = 10000 + random_primary_key_maximum_attempts = 100 + + @staticmethod + def get_unique_primary_key(model): + pk_list = model._meta.default_manager.values_list('pk', flat=True) + + attempts = 0 + while True: + primary_key = random.randint( + RandomPrimaryKeyModelMonkeyPatchMixin.random_primary_key_random_floor, + RandomPrimaryKeyModelMonkeyPatchMixin.random_primary_key_random_ceiling + ) + + if primary_key not in pk_list: + break + + attempts = attempts + 1 + + if attempts > RandomPrimaryKeyModelMonkeyPatchMixin.random_primary_key_maximum_attempts: + raise Exception( + 'Maximum number of retries for an unique random primary ' + 'key reached.' + ) + + return primary_key + + def setUp(self): + original_save = models.Model.save + + def new_save(self, *args, **kwargs): + if self.pk: + return original_save(self, *args, **kwargs) + else: + self.pk = RandomPrimaryKeyModelMonkeyPatchMixin.get_unique_primary_key( + model=self._meta.model + ) + self.id = self.pk + + return self.save_base(force_insert=True) + + setattr(models.Model, 'save', new_save) + super(RandomPrimaryKeyModelMonkeyPatchMixin, self).setUp() + + class TempfileCheckTestCaseMixin(object): # Ignore the jvmstat instrumentation and GitLab's CI .config files # Ignore LibreOffice fontconfig cache dir