Skip to content

Commit 7ed1d29

Browse files
[PERF-274] Include additional randomness in tests to avoid StaleObjectExceptions (#53)
* Added additional randomness to tests * Added additional randomness and removed primary key updates that result in 409 * Cautionary note for anyone stumbling on these docs * Better type handling * Descriptors need to use instance var instead of class because of inheritance Co-authored-by: Stephen A. Fuqua <[email protected]>
1 parent f843cbe commit 7ed1d29

21 files changed

+77
-50
lines changed

docs/old/how-to-create-tests.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# How to Create Tests
22

3+
| ❗❗❗ These instructions are out of date, applicable to the original version of the performance testing. ❗❗❗ |
4+
| ---------------------------------------------------------------------------------------------------------- |
5+
36
## Resource Tests
47

58
When creating a test for a new resource, you will be creating 5 different classes:
@@ -41,7 +44,7 @@ Perform the following steps to create a factory (let's call our example resource
4144
from .. import APIFactory
4245
from ..descriptors.utils import build_descriptor
4346
from ..utils import RandomSuffixAttribute
44-
47+
4548
class CourseFactory(APIFactory):
4649
courseTitle = 'Algebra I'
4750
educationOrganizationReference = factory.Dict(
@@ -242,7 +245,7 @@ Perform the following steps to create a simple volume test:
242245
* The method name must be decorated with `@task` so locust knows that it's a locust task
243246
* The first two parameters for `run_scenario()` include the name of the attribute to be updated and its corresponding value
244247
* Each additional argument must be formatted as shown above in the second scenario, since those are the values that differ from the first
245-
* Note that if there were no values to update, you wouldn't pass any arguments
248+
* Note that if there were no values to update, you wouldn't pass any arguments
246249
* Normally, your first scenario would just take in the update values since the factory will have all of its attributes
247250
* The second scenario would take in the update values, along with any key-value pairs
248251

@@ -353,4 +356,4 @@ Perform the following steps to create a pipeclean test for a composite:
353356
* The remaining pipeclean tests contain the list of the enrollment composite resources and inherit from `EdFiCompositePipecleanTestBase`, as expected.
354357
* The list of composite resources is located near the top since it is shared by most of the pipeclean tests
355358

356-
3. After adding this, you should be finished with these tests and they should run. Make sure the client and pipeclean test class names follow the same naming convention and are on the correct file path. Remember to replace 'enrollment' with the name of your new composite.
359+
3. After adding this, you should be finished with these tests and they should run. Make sure the client and pipeclean test class names follow the same naming convention and are on the correct file path. Remember to replace 'enrollment' with the name of your new composite.

docs/old/lab-extension-testing.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Lab Exercise - Testing Extensions
22

3+
| ❗❗❗ These instructions are out of date, applicable to the original version of the performance testing. ❗❗❗ |
4+
| ---------------------------------------------------------------------------------------------------------- |
5+
36
This lab exercise, developed for the 2018 bootcamp, walks through the process of
47
adding test cases for extensions to the API.
58

@@ -188,7 +191,7 @@ Some highlights:
188191
* Because Locust runs test clients in parallel, the total requests per second is
189192
not the average of the individual values. In this case we managed
190193
approximately 42 requests per second.
191-
194+
192195
(!) These data are from a small-ish VM installed in single-server mode, which is far
193196
from ideal. In other words, these numbers are not reflective of what a good
194197
production setup can achieve.
@@ -377,4 +380,4 @@ Re-run the performance tests to see what the impact of this index is.
377380

378381
Conclusion: adding this index, at this volume of data, does not have a clear
379382
negative impact, and is therefore the risk of introducing a performance problem
380-
in production is very low.
383+
in production is very low.

src/edfi-performance-test/edfi_performance_test/api/client/calendar_date.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-License-Identifier: Apache-2.0
1+
# SPDX-License-Identifier: Apache-2.0
22
# Licensed to the Ed-Fi Alliance under one or more agreements.
33
# The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
44
# See the LICENSE and NOTICES files in the project root for more information.
@@ -33,6 +33,8 @@ def create_with_dependencies(self, **kwargs):
3333
"calendarCode"
3434
],
3535
calendarReference__schoolId=school_id,
36-
calendarReference__schoolYear=2014,
36+
calendarReference__schoolYear=calendar_reference["attributes"][
37+
"schoolYearTypeReference"
38+
]["schoolYear"],
3739
**kwargs
3840
)

src/edfi-performance-test/edfi_performance_test/api/client/course_offering.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ class CourseOfferingClient(EdFiAPIClient):
1515

1616
def create_with_dependencies(self, **kwargs):
1717
school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id())
18-
18+
school_year = kwargs.get("schoolYear", 2014)
1919
session_reference = self.session_client.create_with_dependencies(
20-
schoolId=school_id
20+
schoolId=school_id, schoolYear=school_year
2121
)
2222

2323
return self.create_using_dependencies(
2424
session_reference,
2525
sessionReference__schoolId=school_id,
26-
sessionReference__schoolYear=2014,
26+
sessionReference__schoolYear=school_year,
2727
sessionReference__sessionName=session_reference["attributes"][
2828
"sessionName"
2929
],

src/edfi-performance-test/edfi_performance_test/api/client/section.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ class SectionClient(EdFiAPIClient):
2323

2424
def create_with_dependencies(self, **kwargs):
2525
school_id = kwargs.get("schoolId", SchoolClient.shared_elementary_school_id())
26+
school_year = kwargs.get("schoolYear", 2014)
2627
custom_course_code = kwargs.pop("courseCode", "ELA-01")
2728

2829
# Create a course offering and its dependencies
2930
course_offering_reference = (
3031
self.course_offering_client.create_with_dependencies(
3132
schoolId=school_id,
33+
schoolYear=school_year,
3234
courseReference__courseCode=custom_course_code,
3335
courseReference__educationOrganizationId=school_id,
3436
schoolReference__schoolId=school_id,
@@ -57,6 +59,7 @@ def create_with_dependencies(self, **kwargs):
5759
"localCourseCode"
5860
],
5961
courseOfferingReference__schoolId=school_id,
62+
courseOfferingReference__schoolYear=school_year,
6063
courseOfferingReference__sessionName=course_offering_attrs[
6164
"sessionReference"
6265
]["sessionName"],
@@ -111,9 +114,10 @@ def create_with_dependencies(self, **kwargs):
111114
schoolId=school_id,
112115
)
113116
calendar_date_attrs = calendar_date_reference["attributes"]
117+
calendarSchoolYear = calendar_date_attrs["calendarReference"]["schoolYear"]
114118

115119
section_reference = self.section_client.create_with_dependencies(
116-
schoolId=school_id,
120+
schoolId=school_id, schoolYear=calendarSchoolYear
117121
)
118122
section_attrs = section_reference["attributes"]
119123

@@ -123,9 +127,11 @@ def create_with_dependencies(self, **kwargs):
123127
{"section_client": section_reference},
124128
],
125129
calendarDateReference__schoolId=school_id,
130+
calendarDateReference__schoolYear=calendarSchoolYear,
126131
calendarDateReference__calendarCode=calendar_date_attrs[
127132
"calendarReference"
128133
]["calendarCode"],
134+
calendarDateReference__date=calendar_date_attrs["date"],
129135
sectionReference__sectionIdentifier=section_attrs["sectionIdentifier"],
130136
sectionReference__localCourseCode=section_attrs["courseOfferingReference"][
131137
"localCourseCode"

src/edfi-performance-test/edfi_performance_test/api/client/session.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ class SessionClient(EdFiAPIClient):
1717

1818
def create_with_dependencies(self, **kwargs):
1919
school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id())
20-
20+
school_year = kwargs.get("schoolYear", 2014)
2121
# Create two grading periods
2222
period_1_reference = self.grading_period_client.create_with_dependencies(
2323
schoolReference__schoolId=school_id,
24+
schoolYearTypeReference__schoolYear=school_year,
2425
)
2526
period_2_reference = self.grading_period_client.create_with_dependencies(
2627
schoolReference__schoolId=school_id,
28+
schoolYearTypeReference__schoolYear=school_year,
2729
beginDate="2014-10-06",
2830
endDate="2014-12-15",
2931
totalInstructionalDays=30,
@@ -39,6 +41,7 @@ def create_with_dependencies(self, **kwargs):
3941
{"period_2_reference": period_2_reference},
4042
],
4143
schoolReference__schoolId=school_id,
44+
schoolYearTypeReference__schoolYear=school_year,
4245
gradingPeriods__0__gradingPeriodReference__periodSequence=period_1_reference[
4346
"attributes"
4447
][

src/edfi-performance-test/edfi_performance_test/factories/resources/calendar.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
from edfi_performance_test.api.client.school import SchoolClient
99
from edfi_performance_test.factories.resources.api_factory import APIFactory
1010
from edfi_performance_test.factories.descriptors.utils import build_descriptor
11-
from edfi_performance_test.factories.utils import RandomSuffixAttribute
11+
from edfi_performance_test.factories.utils import (
12+
RandomSuffixAttribute,
13+
RandomSchoolYearAttribute,
14+
)
1215

1316

1417
class CalendarFactory(APIFactory):
1518
schoolYearTypeReference = factory.Dict(
1619
{
17-
"schoolYear": 2014,
20+
"schoolYear": RandomSchoolYearAttribute(),
1821
}
1922
)
2023
calendarTypeDescriptor = build_descriptor("CalendarType", "IEP")

src/edfi-performance-test/edfi_performance_test/factories/resources/calendar_date.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import factory
77

88
from edfi_performance_test.api.client.school import SchoolClient
9-
from edfi_performance_test.factories.utils import current_year
9+
from edfi_performance_test.factories.utils import (
10+
RandomDateAttribute,
11+
)
1012
from edfi_performance_test.factories.resources.api_factory import APIFactory
1113
from edfi_performance_test.factories.descriptors.utils import build_descriptor_dicts
1214

@@ -16,8 +18,8 @@ class CalendarDateFactory(APIFactory):
1618
dict(
1719
calendarCode="107SS111111",
1820
schoolId=SchoolClient.shared_elementary_school_id(),
19-
schoolYear=current_year(),
21+
schoolYear=2014,
2022
)
2123
)
2224
calendarEvents = build_descriptor_dicts("CalendarEvent", ["Holiday"])
23-
date = "2014-09-16"
25+
date = RandomDateAttribute()

src/edfi-performance-test/edfi_performance_test/factories/resources/cohort.py

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

88
from edfi_performance_test.api.client.school import SchoolClient
99
from edfi_performance_test.factories.resources.api_factory import APIFactory
10-
from edfi_performance_test.factories.utils import RandomSuffixAttribute
10+
from edfi_performance_test.factories.utils import UniqueIdAttribute
1111
from edfi_performance_test.factories.descriptors.utils import build_descriptor
1212

1313

1414
class CohortFactory(APIFactory):
15-
cohortIdentifier = RandomSuffixAttribute("1")
15+
cohortIdentifier = UniqueIdAttribute(num_chars=20)
1616
educationOrganizationReference = factory.Dict(
1717
{"educationOrganizationId": SchoolClient.shared_elementary_school_id()}
1818
)

src/edfi-performance-test/edfi_performance_test/factories/resources/discipline.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
from edfi_performance_test.api.client.school import SchoolClient
99
from edfi_performance_test.factories.resources.api_factory import APIFactory
1010
from edfi_performance_test.factories.descriptors.utils import build_descriptor
11-
from edfi_performance_test.factories.utils import formatted_date, UniqueIdAttribute
11+
from edfi_performance_test.factories.utils import RandomDateAttribute, UniqueIdAttribute
1212

1313

1414
class DisciplineActionFactory(APIFactory):
1515
disciplineActionIdentifier = UniqueIdAttribute(num_chars=20)
16-
disciplineDate = formatted_date(9, 20)
16+
disciplineDate = RandomDateAttribute()
1717
disciplines = factory.List(
1818
[
1919
factory.Dict(
@@ -50,7 +50,7 @@ class DisciplineActionFactory(APIFactory):
5050

5151

5252
class DisciplineIncidentFactory(APIFactory):
53-
incidentDate = formatted_date(9, 25)
53+
incidentDate = RandomDateAttribute()
5454
incidentIdentifier = UniqueIdAttribute(num_chars=20)
5555
schoolReference = factory.Dict(
5656
dict(schoolId=SchoolClient.shared_elementary_school_id())

0 commit comments

Comments
 (0)