Ability to generate unique fields in factories

This commit is contained in:
2020-05-21 19:34:02 +02:00
parent c6f2bacf0f
commit c17b558d14
4 changed files with 49 additions and 7 deletions

View File

@@ -1,4 +1,5 @@
""" Module generating useful models in 1 place """ """ Module generating useful models in 1 place """
from inspect import signature
from typing import Type, TypeVar from typing import Type, TypeVar
from django.core.files.uploadedfile import SimpleUploadedFile 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: def create(model: Type[T], **kwargs) -> T:
if model is models.Video: 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: if model is models.Transcoding:
def url(): 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. 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. 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 model: django model to create
:param kwargs: keyword arguments to fill the model :param kwargs: keyword arguments to fill the model
:param defaults: default keyword arguments to use when not mentioned in kwargs :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(): for k, v in defaults.items():
if callable(v) and not k in kwargs: 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}) 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

View File

@@ -8,7 +8,7 @@ from tests.videodinges import factories, UploadMixin
class TranscodingTestCase(TestCase): class TranscodingTestCase(TestCase):
def test_factory_returns_model(self): def test_factory_returns_model(self):
transcoding = factories.create(Transcoding) 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.quality, '360p')
self.assertEqual(transcoding.type, 'video/webm') self.assertEqual(transcoding.type, 'video/webm')
self.assertEqual(transcoding.url, 'https://some_url') self.assertEqual(transcoding.url, 'https://some_url')

View File

@@ -6,8 +6,31 @@ from datetime import datetime
class VideoTestCase(TestCase): class VideoTestCase(TestCase):
def test_factory_returns_model(self): def test_factory_returns_model(self):
video = factories.create(Video) video = factories.create(Video)
self.assertEqual(video.slug, 'slug') self.assertEqual(video.slug, 'slug-1')
self.assertEqual(video.title, 'Title') self.assertEqual(video.title, 'Title 1')
self.assertEqual(video.description, 'Description') self.assertEqual(video.description, 'Description 1')
self.assertIsInstance(video.created_at, datetime) self.assertIsInstance(video.created_at, datetime)
self.assertIsInstance(video.updated_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)

View File

@@ -70,7 +70,7 @@ class VideoTestCase(UploadMixin, TestCase):
self.assertInHTML('<h1>Vid 1</h1>', content) self.assertInHTML('<h1>Vid 1</h1>', content)
self.assertInHTML('<p>Description</p>', content) self.assertInHTML('<p>Description 1</p>', content)
self.assertInHTML('<strong>480p versie</strong>', content) self.assertInHTML('<strong>480p versie</strong>', content)