Skip to content

Commit 6f1b159

Browse files
martin056RadoRado
authored andcommitted
Add test_examples factories
1 parent cd6fb7a commit 6f1b159

File tree

8 files changed

+133
-19
lines changed

8 files changed

+133
-19
lines changed

requirements/local.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ pytest==6.2.5
44
pytest-django==4.5.1
55
flake8==4.0.1
66
ipdb==0.13.9
7+
ipython==7.29.0

styleguide_example/test_examples/admin.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from styleguide_example.test_examples.models import (
44
School,
5-
SchoolClass,
5+
SchoolCourse,
66
Student,
77
Roster
88
)
@@ -15,27 +15,27 @@ class SchoolAdmin(admin.ModelAdmin):
1515

1616
@admin.register(Roster)
1717
class RosterAdmin(admin.ModelAdmin):
18-
list_display = ('student', 'school_class', 'start_date', 'end_date', 'active', )
19-
list_filter = ('student', 'school_class')
18+
list_display = ('student', 'school_course', 'start_date', 'end_date', 'active', )
19+
list_filter = ('student', 'school_course')
2020

2121

2222
class RosterStudentInline(admin.TabularInline):
2323
model = Roster
24-
fields = ('school_class', 'start_date', 'end_date', 'active', 'deactivated_at', )
24+
fields = ('school_course', 'start_date', 'end_date', 'active', 'deactivated_at', )
2525
extra = 1
2626

2727

28-
class RosterSchoolClassInline(admin.TabularInline):
28+
class RosterSchoolCourseInline(admin.TabularInline):
2929
model = Roster
3030
fields = ('student', 'start_date', 'end_date', 'active', 'deactivated_at', )
3131
extra = 1
3232

3333

34-
@admin.register(SchoolClass)
35-
class SchoolClassAdmin(admin.ModelAdmin):
34+
@admin.register(SchoolCourse)
35+
class SchoolCourseAdmin(admin.ModelAdmin):
3636
list_display = ('name', 'short_name', 'slug', 'school', 'start_date', 'end_date', )
3737
list_filter = ('school', )
38-
inlines = (RosterSchoolClassInline, )
38+
inlines = (RosterSchoolCourseInline, )
3939

4040

4141
@admin.register(Student)

styleguide_example/test_examples/migrations/0001_initial.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 3.2.9 on 2021-11-18 10:11
1+
# Generated by Django 3.2.9 on 2021-11-18 12:21
22

33
from django.db import migrations, models
44
import django.db.models.deletion
@@ -31,19 +31,19 @@ class Migration(migrations.Migration):
3131
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='students', to='test_examples.school')),
3232
],
3333
options={
34-
'unique_together': {('identifier', 'school'), ('email', 'school')},
34+
'unique_together': {('email', 'school'), ('identifier', 'school')},
3535
},
3636
),
3737
migrations.CreateModel(
38-
name='SchoolClass',
38+
name='SchoolCourse',
3939
fields=[
4040
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
4141
('name', models.CharField(max_length=255)),
4242
('short_name', models.CharField(max_length=50)),
4343
('slug', models.SlugField(max_length=255)),
4444
('start_date', models.DateField()),
4545
('end_date', models.DateField()),
46-
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='school_classes', to='test_examples.school')),
46+
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='school_courses', to='test_examples.school')),
4747
],
4848
),
4949
migrations.CreateModel(
@@ -54,13 +54,17 @@ class Migration(migrations.Migration):
5454
('end_date', models.DateField()),
5555
('active', models.BooleanField(default=True)),
5656
('deactivated_at', models.DateField(blank=True, null=True)),
57-
('school_class', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rosters', to='test_examples.schoolclass')),
57+
('school_course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rosters', to='test_examples.schoolcourse')),
5858
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rosters', to='test_examples.student')),
5959
],
6060
),
6161
migrations.AddConstraint(
62-
model_name='schoolclass',
63-
constraint=models.CheckConstraint(check=models.Q(('start_date__lt', django.db.models.expressions.F('end_date'))), name='school_class_start_before_end'),
62+
model_name='schoolcourse',
63+
constraint=models.CheckConstraint(check=models.Q(('start_date__lt', django.db.models.expressions.F('end_date'))), name='school_course_start_before_end'),
64+
),
65+
migrations.AlterUniqueTogether(
66+
name='schoolcourse',
67+
unique_together={('name', 'slug', 'start_date', 'end_date')},
6468
),
6569
migrations.AddConstraint(
6670
model_name='roster',

styleguide_example/test_examples/models.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,34 @@ def __str__(self):
2727
return f'Student {self.email} ({self.identifier})'
2828

2929

30-
class SchoolClass(models.Model):
30+
class SchoolCourse(models.Model):
3131
name = models.CharField(max_length=255)
3232
short_name = models.CharField(max_length=50)
3333
slug = models.SlugField(max_length=255)
34-
school = models.ForeignKey(School, related_name='school_classes', on_delete=models.CASCADE)
34+
school = models.ForeignKey(School, related_name='school_courses', on_delete=models.CASCADE)
3535

3636
start_date = models.DateField()
3737
end_date = models.DateField()
3838

3939
class Meta:
4040
constraints = [
4141
models.CheckConstraint(
42-
name="school_class_start_before_end",
42+
name="school_course_start_before_end",
4343
check=Q(start_date__lt=F("end_date"))
4444
)
4545
]
4646

47+
unique_together = (
48+
('name', 'slug', 'start_date', 'end_date', ),
49+
)
50+
4751
def __str__(self):
4852
return f'{self.name} in {self.school}'
4953

5054

5155
class Roster(models.Model):
5256
student = models.ForeignKey(Student, related_name='rosters', on_delete=models.CASCADE)
53-
school_class = models.ForeignKey(SchoolClass, related_name='rosters', on_delete=models.CASCADE)
57+
school_course = models.ForeignKey(SchoolCourse, related_name='rosters', on_delete=models.CASCADE)
5458

5559
start_date = models.DateField()
5660
end_date = models.DateField()

styleguide_example/test_examples/tests/__init__.py

Whitespace-only changes.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from datetime import timedelta
2+
3+
import factory
4+
5+
from django.utils.text import slugify
6+
7+
from styleguide_example.utils.tests import faker
8+
from styleguide_example.test_examples.models import (
9+
School,
10+
Student,
11+
Roster,
12+
SchoolCourse
13+
)
14+
15+
16+
class SchoolFactory(factory.django.DjangoModelFactory):
17+
class Meta:
18+
model = School
19+
20+
name = factory.LazyAttribute(lambda _: f'{faker.unique.company()} School')
21+
slug = factory.LazyAttribute(lambda self: slugify(self.name))
22+
23+
24+
class StudentFactory(factory.django.DjangoModelFactory):
25+
class Meta:
26+
model = Student
27+
28+
email = factory.LazyAttribute(lambda _: faker.unique.email())
29+
identifier = factory.LazyAttribute(lambda _: faker.unique.uuid4())
30+
school = factory.SubFactory(SchoolFactory)
31+
32+
33+
class SchoolWithStudentsFactory(SchoolFactory):
34+
@factory.post_generation
35+
def students(obj, created, extracted, **kwargs):
36+
if created and extracted is None:
37+
students = StudentFactory.create_batch(kwargs.get('count', 5))
38+
obj.students.set(students)
39+
40+
return students
41+
42+
43+
class SchoolCourseFactory(factory.django.DjangoModelFactory):
44+
class Meta:
45+
model = SchoolCourse
46+
47+
name = factory.LazyAttribute(lambda _: faker.unique.sentence(nb_words=3)[:-1]) # remove the end punctuation
48+
short_name = factory.LazyAttribute(lambda self: self.name.split(' ')[0])
49+
slug = factory.LazyAttribute(lambda self: slugify(self.name))
50+
school = factory.SubFactory(SchoolFactory)
51+
52+
start_date = factory.LazyAttribute(lambda _: faker.past_date())
53+
# The code below might cause bugs if you only pass start_date to you factory
54+
# end_date = factory.LazyAttribute(lambda _: faker.future_date())
55+
end_date = factory.LazyAttribute(lambda self: self.start_date + timedelta(days=365))
56+
57+
58+
class RosterFactory(factory.django.DjangoModelFactory):
59+
class Meta:
60+
model = Roster
61+
62+
student = factory.SubFactory(StudentFactory)
63+
# Make sure the student and the school_course are from the same school
64+
school_course = factory.SubFactory(SchoolCourseFactory, school=factory.SelfAttribute('..student.school'))
65+
66+
# The code below might cause bugs because of the school_course period
67+
# start_date = factory.LazyAttribute(lambda _: faker.past_date())
68+
# end_date = factory.LazyAttribute(lambda _: faker.future_date())
69+
start_date = factory.LazyAttribute(lambda self: faker.date_between_dates(
70+
date_start=self.school_course.start_date,
71+
date_end=self.school_course.end_date - timedelta(days=1)
72+
))
73+
end_date = factory.LazyAttribute(lambda self: faker.date_between_dates(
74+
date_start=self.start_date,
75+
date_end=self.school_course.end_date
76+
))
77+
78+
active = True
79+
deactivated_at = factory.Maybe(
80+
'active',
81+
no_declaration=factory.LazyAttribute(lambda self: faker.date_between_dates(
82+
date_start=self.start_date,
83+
date_end=self.end_date
84+
)),
85+
yes_declaration=None
86+
)
87+
88+
89+
class SchoolCourseWithRostersFactory(SchoolCourseFactory):
90+
@factory.post_generation
91+
def rosters(obj, created, extracted, **kwargs):
92+
if created and extracted is None:
93+
rosters = RosterFactory.create_batch(
94+
kwargs.get('count', 5),
95+
student__school=obj.school # NOTE!
96+
)
97+
obj.rosters.set(rosters)
98+
99+
return rosters
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# flake8: noqa
2+
3+
from .base import faker
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from faker import Faker
2+
3+
faker = Faker()

0 commit comments

Comments
 (0)