From c17b558d142a124e4d3ac18e4136bb92c66c4323 Mon Sep 17 00:00:00 2001 From: Bastiaan Welmers Date: Thu, 21 May 2020 19:34:02 +0200 Subject: [PATCH] Ability to generate unique fields in factories --- tests/videodinges/factories.py | 23 +++++++++++++-- .../test_factories/test_transcoding.py | 2 +- .../videodinges/test_factories/test_video.py | 29 +++++++++++++++++-- tests/videodinges/views/test_video.py | 2 +- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tests/videodinges/factories.py b/tests/videodinges/factories.py index 3f577b2..3196d43 100644 --- a/tests/videodinges/factories.py +++ b/tests/videodinges/factories.py @@ -1,4 +1,5 @@ """ Module generating useful models in 1 place """ +from inspect import signature from typing import Type, TypeVar from django.core.files.uploadedfile import SimpleUploadedFile @@ -11,7 +12,11 @@ T = TypeVar('T', bound=django.db.models.Model) def create(model: Type[T], **kwargs) -> T: if model is models.Video: - return _create_with_defaults(models.Video, kwargs, title='Title', slug='slug', description='Description') + return _create_with_defaults(models.Video, kwargs, + title=lambda x: 'Title {}'.format(x), + slug=lambda x: 'slug-{}'.format(x), + description=lambda x: 'Description {}'.format(x), + ) if model is models.Transcoding: def url(): @@ -38,6 +43,9 @@ def _create_with_defaults(model: Type[T], kwargs: dict, **defaults) -> T: When providing lambda as default item, the result of the lambda will be taken. The lambda will ONLY be executed when not provided in kwargs. + When a lambda requires an argument, the primary key of the to be created object + will be provided to that argument. This is useful for generating unique fields. + :param model: django model to create :param kwargs: keyword arguments to fill the model :param defaults: default keyword arguments to use when not mentioned in kwargs @@ -45,6 +53,17 @@ def _create_with_defaults(model: Type[T], kwargs: dict, **defaults) -> T: for k, v in defaults.items(): if callable(v) and not k in kwargs: - defaults[k] = v() + if len(signature(v).parameters) == 1: + result = v(_next_pk(model)) + else: + result = v() + defaults[k] = result return model.objects.create(**{**defaults, **kwargs}) + + +def _next_pk(model: Type[T]) -> int: + try: + return model.objects.order_by('-pk').first().pk + 1 + except AttributeError: + return 1 diff --git a/tests/videodinges/test_factories/test_transcoding.py b/tests/videodinges/test_factories/test_transcoding.py index 4e43b78..0f86df4 100644 --- a/tests/videodinges/test_factories/test_transcoding.py +++ b/tests/videodinges/test_factories/test_transcoding.py @@ -8,7 +8,7 @@ from tests.videodinges import factories, UploadMixin class TranscodingTestCase(TestCase): def test_factory_returns_model(self): transcoding = factories.create(Transcoding) - self.assertEqual(transcoding.video.slug, 'slug') + self.assertEqual(transcoding.video.slug, 'slug-1') self.assertEqual(transcoding.quality, '360p') self.assertEqual(transcoding.type, 'video/webm') self.assertEqual(transcoding.url, 'https://some_url') diff --git a/tests/videodinges/test_factories/test_video.py b/tests/videodinges/test_factories/test_video.py index 3252a5e..ec4b957 100644 --- a/tests/videodinges/test_factories/test_video.py +++ b/tests/videodinges/test_factories/test_video.py @@ -6,8 +6,31 @@ from datetime import datetime class VideoTestCase(TestCase): def test_factory_returns_model(self): video = factories.create(Video) - self.assertEqual(video.slug, 'slug') - self.assertEqual(video.title, 'Title') - self.assertEqual(video.description, 'Description') + self.assertEqual(video.slug, 'slug-1') + self.assertEqual(video.title, 'Title 1') + self.assertEqual(video.description, 'Description 1') self.assertIsInstance(video.created_at, datetime) self.assertIsInstance(video.updated_at, datetime) + + def test_factory_can_create_multiple_models(self): + video1 = factories.create(Video) + video2 = factories.create(Video) + video3 = factories.create(Video) + + self.assertEqual(video1.slug, 'slug-1') + self.assertEqual(video1.title, 'Title 1') + self.assertEqual(video1.description, 'Description 1') + self.assertIsInstance(video1.created_at, datetime) + self.assertIsInstance(video1.updated_at, datetime) + + self.assertEqual(video2.slug, 'slug-2') + self.assertEqual(video2.title, 'Title 2') + self.assertEqual(video2.description, 'Description 2') + self.assertIsInstance(video2.created_at, datetime) + self.assertIsInstance(video2.updated_at, datetime) + + self.assertEqual(video3.slug, 'slug-3') + self.assertEqual(video3.title, 'Title 3') + self.assertEqual(video3.description, 'Description 3') + self.assertIsInstance(video3.created_at, datetime) + self.assertIsInstance(video3.updated_at, datetime) diff --git a/tests/videodinges/views/test_video.py b/tests/videodinges/views/test_video.py index 684b60a..aef91b8 100644 --- a/tests/videodinges/views/test_video.py +++ b/tests/videodinges/views/test_video.py @@ -70,7 +70,7 @@ class VideoTestCase(UploadMixin, TestCase): self.assertInHTML('

Vid 1

', content) - self.assertInHTML('

Description

', content) + self.assertInHTML('

Description 1

', content) self.assertInHTML('480p versie', content)