diff --git a/.gitattributes b/.gitattributes index 4a2dfcc8..41bf0cce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,5 @@ +* text eol=lf + *.md text *.txt text *.py text diff --git a/src/edfi-paging-test/edfi_paging_test/performance_tester.py b/src/edfi-paging-test/edfi_paging_test/performance_tester.py index e894bb2d..c1965002 100644 --- a/src/edfi-paging-test/edfi_paging_test/performance_tester.py +++ b/src/edfi-paging-test/edfi_paging_test/performance_tester.py @@ -48,12 +48,14 @@ def _generate_output_reports(args: MainArguments) -> None: def fetch_resource(request_client: RequestClient, target_resource: str) -> None: resources = request_client.get_all(target_resource) - total_count = request_client.get_total(target_resource) - if len(resources) != total_count: - logger.warn( - f"{target_resource}: expected {total_count} results, got: {len(resources)}" - ) + if('error' not in resources): + total_count = request_client.get_total(target_resource) + + if len(resources) != total_count: + logger.warn( + f"{target_resource}: expected {total_count} results, got: {len(resources)}" + ) def invalid_resources( diff --git a/src/edfi-performance-test/README.md b/src/edfi-performance-test/README.md index ab53299c..3ef0c1fd 100644 --- a/src/edfi-performance-test/README.md +++ b/src/edfi-performance-test/README.md @@ -1,8 +1,8 @@ # Performance Tests -Provides performance metrics for the ODS / API SIS Certification endpoints aimed at analysis of -bottlenecks, and providing recommendations for server sizing for representative -agency simulation sizes. +Provides performance metrics for the ODS / API SIS Certification endpoints +aimed at analysis of bottlenecks, and providing recommendations for server +sizing for representative agency simulation sizes. ## Getting Started @@ -24,8 +24,8 @@ directory: poetry run python edfi_performance_test -b "https://localhost:54746" -k "testkey" -s "testsecret" -t "volume" ``` -Test failure ratio is monitored throughout and run is stopped if more than 50% of the -tests experience failures. +Test failure ratio is monitored throughout and run is stopped if more than 50% +of the tests experience failures. ### Supported arguments @@ -35,7 +35,7 @@ tests experience failures. | `-k` or `--key` | yes (no default) | The web API OAuth key | | `-s` or `--secret` | yes (no default) | The web API OAuth secret | | `-i` or `--ignoreCertificateErrors` | no (default: false) | Ignore certificate errors | -| `-t` or `--testType` | no (default: PIPECLEAN) | Type of the performance tests to run: VOLUME, PIPECLEAN, CHANGE_QUERY | +| `-t` or `--testType` | no (default: pipeclean) | Type of the performance tests to run: volume, pipeclean, change_query | | `-tl` or `--testList` | no (no default) | (Optional) List of test files to run - if not provided, all tests will be run | | `-d` or `--deleteResources` | no (default: true) | Delete resources during test run | | `-f` or `--failDeliberately` | no (default: true) | Deliberately introduce requests that result in failure | @@ -48,8 +48,8 @@ tests experience failures. | `-e` or `--localEducationOrganizationId` | no (default: 255901) | Override the default LEA education organization ID | Each argument can also be set by environment variable, or by using as `.env` -file. See [.env.example](edfi_performance_test/.env.example). Arguments provided at -the command line override any arguments provided by environment variable. +file. See [.env.example](edfi_performance_test/.env.example). Arguments provided +at the command line override any arguments provided by environment variable. ### Dev Operations diff --git a/src/edfi-performance-test/edfi_performance_test/.env.example b/src/edfi-performance-test/edfi_performance_test/.env.example index e9736d60..4d4bd80d 100644 --- a/src/edfi-performance-test/edfi_performance_test/.env.example +++ b/src/edfi-performance-test/edfi_performance_test/.env.example @@ -21,7 +21,12 @@ PERF_API_OAUTH_ENDPOINT="/oauth/token" # Meadowlark # PERF_API_PREFIX="/local/v3.3b/ed-fi" -# PERF_API_OAUTH_ENDPOINT="/local/api/oauth/token" +# PERF_API_OAUTH_ENDPOINT="/local/oauth/token" # Set to true when using HTTP instead of HTTPS or when using self-signed certificates IGNORE_TLS_CERTIFICATE=true + +# PERF_TEST_LIST=[""] + +# Meadowlark requires the ID in the body +INCLUDE_ID_IN_BODY=True diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/account.py b/src/edfi-performance-test/edfi_performance_test/api/client/account.py index 3463d807..43ab865c 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/account.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/account.py @@ -19,9 +19,8 @@ class AccountClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - # TODO: this is the only reference to account_code_client anywhere in - # the code base, so the next line should fail if it is ever called. - account_code_reference = self.account_code_client.create_with_dependencies() + # The constructor for ed_fi_api_client dynamically creates the `xyz_client` property using `setattr` + account_code_reference = self.account_code_client.create_with_dependencies() # type: ignore account_code_attrs = account_code_reference["attributes"] edorg_id = account_code_attrs["educationOrganizationReference"][ @@ -56,10 +55,10 @@ class _AccountDependentMixin(object): } def create_with_dependencies(self, **kwargs): - account_reference = self.account_client.create_with_dependencies() + account_reference = self.account_client.create_with_dependencies() # type: ignore account_identifier = account_reference["attributes"]["accountIdentifier"] - return self.create_using_dependencies( + return self.create_using_dependencies( # type: ignore account_reference, accountReference__accountIdentifier=account_identifier, **kwargs diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/assessment.py b/src/edfi-performance-test/edfi_performance_test/api/client/assessment.py index 41d58fd3..e7ff2d72 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/assessment.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/assessment.py @@ -18,7 +18,7 @@ class AssessmentItemClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create new assessment - assessment_reference = self.assessment_client.create_with_dependencies() + assessment_reference = self.assessment_client.create_with_dependencies() # type: ignore # Create assessment item return self.create_using_dependencies( @@ -45,7 +45,7 @@ class ObjectiveAssessmentClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create new assessment - assessment_reference = self.assessment_client.create_with_dependencies() + assessment_reference = self.assessment_client.create_with_dependencies() # type: ignore # Create objective assessment return self.create_using_dependencies( diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/bell_schedule.py b/src/edfi-performance-test/edfi_performance_test/api/client/bell_schedule.py index a30afd93..d961ed35 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/bell_schedule.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/bell_schedule.py @@ -15,7 +15,7 @@ class BellScheduleClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create new class period - class_period_reference = self.class_period_client.create_with_dependencies() + class_period_reference = self.class_period_client.create_with_dependencies() # type: ignore # Create bell schedule return self.create_using_dependencies( diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/calendar_date.py b/src/edfi-performance-test/edfi_performance_test/api/client/calendar_date.py index ef6e4da6..e0c8086d 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/calendar_date.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/calendar_date.py @@ -22,7 +22,7 @@ def create_with_dependencies(self, **kwargs): "calendarCode", RandomSuffixAttribute("107SS111111") ) # Create a calendar - calendar_reference = self.calendar_client.create_with_dependencies( + calendar_reference = self.calendar_client.create_with_dependencies( # type: ignore schoolReference__schoolId=school_id, calendarCode=custom_calendar_code ) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/community.py b/src/edfi-performance-test/edfi_performance_test/api/client/community.py index 21f81c3f..00316139 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/community.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/community.py @@ -20,7 +20,7 @@ class CommunityProviderClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - org_reference = self.org_client.create_with_dependencies() + org_reference = self.org_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( org_reference, @@ -41,7 +41,7 @@ class CommunityProviderLicenseClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - provider_reference = self.provider_client.create_with_dependencies() + provider_reference = self.provider_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( provider_reference, diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/composite.py b/src/edfi-performance-test/edfi_performance_test/api/client/composite.py index f8a99e67..16757a30 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/composite.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/composite.py @@ -44,5 +44,9 @@ def _get_all(self, resource): response = self._get_response( "get", list_endpoint, headers=self.get_headers(), name=list_endpoint ) + + if not response.ok: + raise RuntimeError(f"Composite resource '{resource}' does not exist (404)") + self.log_response(response) return json.loads(response.text) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/course.py b/src/edfi-performance-test/edfi_performance_test/api/client/course.py index f1ce16ef..209e6f39 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/course.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/course.py @@ -24,7 +24,7 @@ class CourseTranscriptClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) - record_reference = self.record_client.create_with_dependencies( + record_reference = self.record_client.create_with_dependencies( # type: ignore schoolId=school_id ) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/course_offering.py b/src/edfi-performance-test/edfi_performance_test/api/client/course_offering.py index 22bcf4bb..5282598e 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/course_offering.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/course_offering.py @@ -15,8 +15,9 @@ class CourseOfferingClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) - school_year = kwargs.get("schoolYear", 2014) - session_reference = self.session_client.create_with_dependencies( + school_year = kwargs.pop("schoolYear", 2014) + + session_reference = self.session_client.create_with_dependencies( # type: ignore schoolId=school_id, schoolYear=school_year ) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/discipline.py b/src/edfi-performance-test/edfi_performance_test/api/client/discipline.py index bc0240c0..d1c0ae87 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/discipline.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/discipline.py @@ -21,7 +21,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create staff - staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) + staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) # type: ignore # Create discipline incident return self.create_using_dependencies( @@ -47,7 +47,7 @@ def create_with_dependencies(self, **kwargs): # Create incident and association first school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) - assoc_reference = self.assoc_client.create_with_dependencies(schoolId=school_id) + assoc_reference = self.assoc_client.create_with_dependencies(schoolId=school_id) # type: ignore # Create discipline action return self.create_using_dependencies( diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/ed_fi_api_client.py b/src/edfi-performance-test/edfi_performance_test/api/client/ed_fi_api_client.py index 794dca46..96609540 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/ed_fi_api_client.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/ed_fi_api_client.py @@ -7,7 +7,7 @@ import json import logging import re -from typing import Any, Dict +from typing import Any, Dict, Optional import urllib3 @@ -118,6 +118,17 @@ def get_item(self, resource_id): self.log_response(response) return json.loads(response.text) + def _get_resource_id_from_location(self, headers: dict) -> Optional[str]: + header = "" + if "Location" in headers: + header = "Location" + elif "location" in headers: + header = "location" + else: + return None + + return headers[header].split("/")[-1].strip() + def create(self, unique_id_field=None, name=None, **factory_kwargs): # Pass in a `unique_id_field` name (e.g. 'schoolId') to have that # attribute returned alongside the resource_id. Useful if you need @@ -146,7 +157,8 @@ def create(self, unique_id_field=None, name=None, **factory_kwargs): return None, None return None self.log_response(response) - resource_id = response.headers["Location"].split("/")[-1].strip() + + resource_id = self._get_resource_id_from_location(response.headers) if unique_id is not None: return resource_id, unique_id return resource_id @@ -164,8 +176,14 @@ def update(self, resource_id, **update_kwargs): if self.is_not_expected_result(response, [200, 204]): return self.log_response(response) - new_id = response.headers["Location"].split("/")[-1].strip() - assert new_id == resource_id + + new_id = self._get_resource_id_from_location(response.headers) + + # The ODS/API returns a Location header on PUT requests, but this is not a required feature + # of an Ed-Fi API. Therefore only apply this test if the location header was found + if new_id is not None: + assert new_id == resource_id + return resource_id def delete_item(self, resource_id): @@ -246,7 +264,7 @@ def create_using_dependencies(self, dependency_reference=None, **kwargs): "attributes": resource_attrs, } - def delete_with_dependencies(self, reference, **kwargs): + def delete_with_dependencies(self, reference): """ Atomically delete an instance of this resource along with all dependencies. The `reference` parameter will contain the necessary diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/education.py b/src/edfi-performance-test/edfi_performance_test/api/client/education.py index aed7aa97..9797646e 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/education.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/education.py @@ -28,7 +28,7 @@ class EducationOrganizationInterventionPrescriptionAssociationClient(EdFiAPIClie } def create_with_dependencies(self, **kwargs): - rx_reference = self.prescription_client.create_with_dependencies() + rx_reference = self.prescription_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( rx_reference, @@ -54,7 +54,7 @@ class EducationOrganizationNetworkAssociationClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - network_reference = self.network_client.create_with_dependencies() + network_reference = self.network_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( network_reference, @@ -75,7 +75,7 @@ class EducationOrganizationPeerAssociationClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - school_reference = self.school_client.create_with_dependencies() + school_reference = self.school_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( school_reference, @@ -105,7 +105,7 @@ class LocalEducationAgencyClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - service_center_reference = self.service_center_client.create_with_dependencies() + service_center_reference = self.service_center_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( service_center_reference, @@ -144,7 +144,7 @@ class FeederSchoolAssociationClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - feeder_school_reference = self.school_client.create_with_dependencies() + feeder_school_reference = self.school_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( feeder_school_reference, diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/grade.py b/src/edfi-performance-test/edfi_performance_test/api/client/grade.py index 503e50c6..1a477a72 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/grade.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/grade.py @@ -23,7 +23,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) course_code = kwargs.pop("courseCode", "ELA-01") - assoc_reference = self.section_assoc_client.create_with_dependencies( + assoc_reference = self.section_assoc_client.create_with_dependencies( # type: ignore schoolId=school_id, courseCode=course_code ) grade_period = assoc_reference["dependency_ids"]["section_client"][ diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/gradebook_entries.py b/src/edfi-performance-test/edfi_performance_test/api/client/gradebook_entries.py index b6d06a66..bcdf8d03 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/gradebook_entries.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/gradebook_entries.py @@ -16,7 +16,7 @@ class GradebookEntryClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - section_reference = self.section_client.create_with_dependencies() + section_reference = self.section_client.create_with_dependencies() # type: ignore section_attrs = section_reference["attributes"] return self.create_using_dependencies( diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/graduation_plan.py b/src/edfi-performance-test/edfi_performance_test/api/client/graduation_plan.py index 32c88991..91cfe013 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/graduation_plan.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/graduation_plan.py @@ -16,7 +16,7 @@ class GraduationPlanClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - school_reference = self.school_client.create_with_dependencies() + school_reference = self.school_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( school_reference, diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/intervention.py b/src/edfi-performance-test/edfi_performance_test/api/client/intervention.py index f0a86f47..225a312f 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/intervention.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/intervention.py @@ -21,7 +21,7 @@ class InterventionClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create intervention prescription - rx_reference = self.prescription_client.create_with_dependencies() + rx_reference = self.prescription_client.create_with_dependencies() # type: ignore # Create intervention return self.create_using_dependencies( @@ -45,7 +45,7 @@ class InterventionStudyClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create intervention prescription - rx_reference = self.prescription_client.create_with_dependencies() + rx_reference = self.prescription_client.create_with_dependencies() # type: ignore # Create intervention return self.create_using_dependencies( diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/parent.py b/src/edfi-performance-test/edfi_performance_test/api/client/parent.py index 01ad8b40..25a9b064 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/parent.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/parent.py @@ -28,12 +28,12 @@ def create_with_dependencies(self, **kwargs): parent_id = self.create(**parent_attrs) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) # Associate parent with student to allow updates - assoc_id = self.parent_assoc_client.create( + assoc_id = self.parent_assoc_client.create( # type: ignore parentReference__parentUniqueId=parent_unique_id, studentReference__studentUniqueId=student_reference["attributes"][ "studentUniqueId" @@ -50,8 +50,8 @@ def create_with_dependencies(self, **kwargs): } def delete_with_dependencies(self, reference, **kwargs): - self.parent_assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) - self.student_client.delete_with_dependencies( + self.parent_assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) # type: ignore + self.student_client.delete_with_dependencies( # type: ignore reference["dependency_ids"]["student_reference"] ) self.delete_item(reference["resource_id"]) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/post_secondary.py b/src/edfi-performance-test/edfi_performance_test/api/client/post_secondary.py index 7a175c82..059a930b 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/post_secondary.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/post_secondary.py @@ -23,7 +23,7 @@ def create_with_dependencies(self, **kwargs): studentUniqueId = kwargs.pop("studentUniqueId", StudentClient.shared_student_id()) # Create new student for association - institution_reference = self.institution_client.create_with_dependencies() + institution_reference = self.institution_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( institution_reference, diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/section.py b/src/edfi-performance-test/edfi_performance_test/api/client/section.py index 57abbade..7ad59bf3 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/section.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/section.py @@ -22,13 +22,13 @@ class SectionClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - school_id = kwargs.get("schoolId", SchoolClient.shared_elementary_school_id()) - school_year = kwargs.get("schoolYear", 2014) + school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) + school_year = kwargs.pop("schoolYear", 2014) custom_course_code = kwargs.pop("courseCode", "ELA-01") # Create a course offering and its dependencies course_offering_reference = ( - self.course_offering_client.create_with_dependencies( + self.course_offering_client.create_with_dependencies( # type: ignore schoolId=school_id, schoolYear=school_year, courseReference__courseCode=custom_course_code, @@ -39,12 +39,12 @@ def create_with_dependencies(self, **kwargs): course_offering_attrs = course_offering_reference["attributes"] # Create a class period - class_period_reference = self.class_period_client.create_with_dependencies( + class_period_reference = self.class_period_client.create_with_dependencies( # type: ignore schoolReference__schoolId=school_id, ) # Create a location - location_reference = self.location_client.create_with_dependencies( + location_reference = self.location_client.create_with_dependencies( # type: ignore schoolReference__schoolId=school_id, ) @@ -55,6 +55,7 @@ def create_with_dependencies(self, **kwargs): ][ "classPeriodName" ], + classPeriods__0__classPeriodReference__schoolId=school_id, courseOfferingReference__localCourseCode=course_offering_attrs[ "localCourseCode" ], @@ -91,11 +92,11 @@ def create_with_dependencies(self, **kwargs): def delete_with_dependencies(self, reference, **kwargs): self.delete_item(reference["resource_id"]) depend = reference["dependency_ids"] - self.location_client.delete_with_dependencies(depend["location_reference"]) - self.class_period_client.delete_with_dependencies( + self.location_client.delete_with_dependencies(depend["location_reference"]) # type: ignore + self.class_period_client.delete_with_dependencies( # type: ignore depend["class_period_reference"] ) - self.course_offering_client.delete_with_dependencies( + self.course_offering_client.delete_with_dependencies( # type: ignore depend["course_offering_reference"] ) @@ -110,13 +111,13 @@ class SectionAttendanceTakenEventClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) - calendar_date_reference = self.calendar_date_client.create_with_dependencies( + calendar_date_reference = self.calendar_date_client.create_with_dependencies( # type: ignore schoolId=school_id, ) calendar_date_attrs = calendar_date_reference["attributes"] calendarSchoolYear = calendar_date_attrs["calendarReference"]["schoolYear"] - section_reference = self.section_client.create_with_dependencies( + section_reference = self.section_client.create_with_dependencies( # type: ignore schoolId=school_id, schoolYear=calendarSchoolYear ) section_attrs = section_reference["attributes"] diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/session.py b/src/edfi-performance-test/edfi_performance_test/api/client/session.py index c78b53a8..e1663585 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/session.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/session.py @@ -16,14 +16,17 @@ class SessionClient(EdFiAPIClient): dependencies: Dict = {GradingPeriodClient: {}} def create_with_dependencies(self, **kwargs): + # is schoolyear a kwarg? + school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) - school_year = kwargs.get("schoolYear", 2014) + school_year = kwargs.pop("schoolYear", 2014) + # Create two grading periods - period_1_reference = self.grading_period_client.create_with_dependencies( + period_1_reference = self.grading_period_client.create_with_dependencies( # type: ignore schoolReference__schoolId=school_id, schoolYearTypeReference__schoolYear=school_year, ) - period_2_reference = self.grading_period_client.create_with_dependencies( + period_2_reference = self.grading_period_client.create_with_dependencies( # type: ignore schoolReference__schoolId=school_id, schoolYearTypeReference__schoolYear=school_year, beginDate="2014-10-06", @@ -57,9 +60,9 @@ def create_with_dependencies(self, **kwargs): def delete_with_dependencies(self, reference, **kwargs): self.delete_item(reference["resource_id"]) - self.grading_period_client.delete_with_dependencies( + self.grading_period_client.delete_with_dependencies( # type: ignore reference["dependency_ids"]["period_1_reference"] ) - self.grading_period_client.delete_with_dependencies( + self.grading_period_client.delete_with_dependencies( # type: ignore reference["dependency_ids"]["period_2_reference"] ) diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/staff.py b/src/edfi-performance-test/edfi_performance_test/api/client/staff.py index d004e6c6..41d0aa1a 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/staff.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/staff.py @@ -35,10 +35,9 @@ def create_with_dependencies(self, **kwargs): staff_id = self.create(**staff_attrs) # Associate staff with existing school to allow updates - assoc_id = self.assoc_client.create( + assoc_id = self.assoc_client.create( # type: ignore staffReference__staffUniqueId=staff_unique_id, educationOrganizationReference__educationOrganizationId=school_id, - staffUniqueId=staff_unique_id, ) return { @@ -50,7 +49,7 @@ def create_with_dependencies(self, **kwargs): } def delete_with_dependencies(self, reference, **kwargs): - self.assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) + self.assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) # type: ignore self.delete_item(reference["resource_id"]) @classmethod @@ -65,16 +64,13 @@ class StaffEducationOrganizationAssignmentAssociationClient(EdFiAPIClient): endpoint = "staffEducationOrganizationAssignmentAssociations" def create_with_dependencies(self, **kwargs): - # Create new staff for association - staff_unique_id = kwargs.pop("staffUniqueId", StaffClient.shared_staff_id()) - - # Create association from staff to ed org - edorg_id = kwargs.pop( - "educationOrganizationId", SchoolClient.shared_elementary_school_id() - ) assoc_overrides = dict( - staffReference__staffUniqueId=staff_unique_id, - educationOrganizationReference__educationOrganizationId=edorg_id, + staffReference__staffUniqueId=kwargs.pop( + "staffUniqueId", StaffClient.shared_staff_id() + ), + educationOrganizationReference__educationOrganizationId=kwargs.pop( + "educationOrganizationId", SchoolClient.shared_elementary_school_id() + ), ) assoc_overrides.update(kwargs) return self.create_using_dependencies(**assoc_overrides) @@ -93,12 +89,12 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create cohort - cohort_reference = self.cohort_client.create_with_dependencies( + cohort_reference = self.cohort_client.create_with_dependencies( # type: ignore educationOrganizationReference__educationOrganizationId=school_id, ) # Create staff - staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) + staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) # type: ignore # Create association between new staff and new cohort return self.create_using_dependencies( @@ -139,7 +135,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create staff record - staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) + staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) # type: ignore return self.create_using_dependencies( staff_reference, @@ -164,12 +160,12 @@ def create_with_dependencies(self, **kwargs): course_code = kwargs.pop("courseCode", "ELA-01") # Create section and staff - section_reference = self.section_client.create_with_dependencies( + section_reference = self.section_client.create_with_dependencies( # type: ignore schoolId=school_id, courseCode=course_code, sectionIdentifier=RandomSuffixAttribute(course_code + "2017RM555"), ) - staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) + staff_reference = self.staff_client.create_with_dependencies(schoolId=school_id) # type: ignore # Create association between staff and section sec_attrs = section_reference["attributes"] diff --git a/src/edfi-performance-test/edfi_performance_test/api/client/student.py b/src/edfi-performance-test/edfi_performance_test/api/client/student.py index 5198f2d9..c183bd34 100644 --- a/src/edfi-performance-test/edfi_performance_test/api/client/student.py +++ b/src/edfi-performance-test/edfi_performance_test/api/client/student.py @@ -29,7 +29,7 @@ class StudentParentAssociationClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create enrolled student - student_reference = self.student_client.create_with_dependencies() + student_reference = self.student_client.create_with_dependencies() # type: ignore # Create parent parent_unique_id = kwargs.pop("parentUniqueId", ParentClient.shared_parent_id()) @@ -65,10 +65,9 @@ def create_with_dependencies(self, **kwargs): student_id = self.create(**student_attrs) # Associate student with existing school to allow updates - assoc_id = self.assoc_client.create( + assoc_id = self.assoc_client.create( # type: ignore studentReference__studentUniqueId=student_unique_id, - schoolReference__schoolId=school_id, - studentUniqueId=student_unique_id, + schoolReference__schoolId=school_id ) return { @@ -80,7 +79,7 @@ def create_with_dependencies(self, **kwargs): } def delete_with_dependencies(self, reference, **kwargs): - self.assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) + self.assoc_client.delete_item(reference["dependency_ids"]["assoc_id"]) # type: ignore self.delete_item(reference["resource_id"]) @classmethod @@ -95,13 +94,11 @@ class StudentSchoolAssociationClient(EdFiAPIClient): endpoint = "studentSchoolAssociations" def create_with_dependencies(self, **kwargs): - # Create new student for association - student_unique_id = kwargs.pop( - "studentUniqueId", StudentClient.shared_student_id() - ) - # Create association from student to school school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) + # This is coming back with a function, and we need to call that function + student_unique_id = kwargs.pop("student_unique_id", StudentClient.shared_student_id()) + assoc_overrides = dict( studentReference__studentUniqueId=student_unique_id, schoolReference__schoolId=school_id, @@ -121,7 +118,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -147,12 +144,12 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) # Create a cohort - cohort_reference = self.cohort_client.create_with_dependencies( + cohort_reference = self.cohort_client.create_with_dependencies( # type: ignore educationOrganizationReference__educationOrganizationId=school_id ) @@ -184,7 +181,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -209,7 +206,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -232,7 +229,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -260,12 +257,12 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) # Create discipline incident - incident_reference = self.incident_client.create_with_dependencies( + incident_reference = self.incident_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -295,15 +292,15 @@ class StudentSectionAssociationClient(EdFiAPIClient): } def create_with_dependencies(self, **kwargs): - school_id = kwargs.get("schoolId", SchoolClient.shared_elementary_school_id()) + school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) course_code = kwargs.pop("courseCode", "ELA-01") # Create section and student - section_reference = self.section_client.create_with_dependencies( + section_reference = self.section_client.create_with_dependencies( # type: ignore schoolId=school_id, courseCode=course_code, sectionIdentifier=RandomSuffixAttribute(course_code + "2017RM555"), ) - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) student_unique_id = student_reference["attributes"]["studentUniqueId"] @@ -345,12 +342,12 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) # Create session - session_reference = self.session_client.create_with_dependencies( + session_reference = self.session_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -385,12 +382,12 @@ def create_with_dependencies(self, **kwargs): course_code = kwargs.pop("courseCode", "ELA-01") # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) # Create section - section_reference = self.section_client.create_with_dependencies( + section_reference = self.section_client.create_with_dependencies( # type: ignore schoolId=school_id, courseCode=course_code, sectionIdentifier=RandomSuffixAttribute(course_code + "2017RM555"), @@ -434,7 +431,7 @@ def create_with_dependencies(self, **kwargs): school_id = kwargs.pop("schoolId", SchoolClient.shared_elementary_school_id()) # Create enrolled student - student_reference = self.student_client.create_with_dependencies( + student_reference = self.student_client.create_with_dependencies( # type: ignore schoolId=school_id ) @@ -462,11 +459,11 @@ def create_with_dependencies(self, **kwargs): studentUniqueId = kwargs.pop("studentUniqueId", StudentClient.shared_student_id()) # Create grading period - period_reference = self.grading_period_client.create_with_dependencies() + period_reference = self.grading_period_client.create_with_dependencies() # type: ignore # Create competency objective objective_reference = ( - self.competency_objective_client.create_with_dependencies() + self.competency_objective_client.create_with_dependencies() # type: ignore ) # Create student competency objective @@ -478,7 +475,7 @@ def create_with_dependencies(self, **kwargs): gradingPeriodReference__periodSequence=period_reference["attributes"][ "periodSequence" ], - objectiveCompetencyObjectiveReference__objective=objective_reference[ + competencyObjectiveReference__objective=objective_reference[ "attributes" ]["objective"], studentReference__studentUniqueId=studentUniqueId, @@ -529,7 +526,7 @@ class StudentGradebookEntryClient(EdFiAPIClient): def create_with_dependencies(self, **kwargs): # Create a student and section - student_section_reference = self.assoc_client.create_with_dependencies() + student_section_reference = self.assoc_client.create_with_dependencies() # type: ignore section_kwargs = { "sectionIdentifier": student_section_reference["attributes"][ "sectionReference" @@ -549,7 +546,7 @@ def create_with_dependencies(self, **kwargs): } # Create gradebook entry - entry_id, gradebook_entry_title = self.entry_client.create( + entry_id, gradebook_entry_title = self.entry_client.create( # type: ignore unique_id_field="gradebookEntryTitle", sectionReference=section_kwargs ) @@ -577,8 +574,8 @@ def create_with_dependencies(self, **kwargs): def delete_with_dependencies(self, reference, **kwargs): self.delete_item(reference["resource_id"]) dependencies = reference["dependency_ids"] - self.entry_client.delete_item(dependencies["entry_client"]) - self.assoc_client.delete_with_dependencies(dependencies["assoc_client"]) + self.entry_client.delete_item(dependencies["entry_client"]) # type: ignore + self.assoc_client.delete_with_dependencies(dependencies["assoc_client"]) # type: ignore class StudentHomelessProgramAssociationClient(EdFiAPIClient): @@ -683,7 +680,7 @@ def create_with_dependencies(self, **kwargs): objective_reference = self.objective_client.create_with_dependencies() - period_reference = self.grading_period_client.create_with_dependencies() + period_reference = self.grading_period_client.create_with_dependencies() # type: ignore return self.create_using_dependencies( [ diff --git a/src/edfi-performance-test/edfi_performance_test/factories/descriptors/utils.py b/src/edfi-performance-test/edfi_performance_test/factories/descriptors/utils.py index 5e0b9c5a..b403c4bb 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/descriptors/utils.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/descriptors/utils.py @@ -3,6 +3,7 @@ # The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. # See the LICENSE and NOTICES files in the project root for more information. +from typing import Any, Dict, List, Tuple, Union import factory @@ -24,14 +25,13 @@ def _descriptor_type_to_dict_key(descriptor_type): return "{}{}".format(dt[0].lower(), dt[1:]) -def _descriptor_type_to_endpoint(descriptor_type): - return "{}s".format(_descriptor_type_to_dict_key(descriptor_type)) - - def build_descriptor(descriptor_type, value): - _namespace = "uri://ed-fi.org/" descriptor_type = _normalize_descriptor_type(descriptor_type) - return "{}{}#{}".format(_namespace, descriptor_type, value) + + # force first letter to be capitalized + descriptor_type = descriptor_type[:1].capitalize() + descriptor_type[1:] + + return f"{'uri://ed-fi.org/'}{descriptor_type}#{value}" def _build_descriptor_dicts(descriptor_type, values): @@ -48,7 +48,7 @@ def _build_descriptor_dicts(descriptor_type, values): yield defaults -def build_descriptor_dicts(descriptor_type, values): +def build_descriptor_dicts(descriptor_type: str, values: List[Union[str, Tuple[str, Dict[str, Union[str, Any]]]]]) -> List[Dict[str, str]]: """ A common pattern in Ed-Fi resources is to have a list of dicts of descriptors, something like diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/assessment.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/assessment.py index 34ab624f..39fe063d 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/assessment.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/assessment.py @@ -86,7 +86,9 @@ class AssessmentFactory(APIFactory): assessmentReportingMethodDescriptor=build_descriptor( "AssessmentReportingMethod", "Scale score" ), - resultDatatypeType="Integer", + resultDatatypeTypeDescriptor=build_descriptor( + "ResultDatatypeType", "Integer" + ), maximumScore="25", minimumScore="0", ) @@ -117,8 +119,7 @@ class LearningObjectiveFactory(APIFactory): dict( academicSubjectDescriptor=build_descriptor( "AcademicSubject", "Mathematics" - ), - namespace="uri://ed-fi.org/", + ) ) ) ] diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/bell_schedule.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/bell_schedule.py index 3d78bd6f..1a742a54 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/bell_schedule.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/bell_schedule.py @@ -19,7 +19,7 @@ class BellScheduleFactory(APIFactory): [ factory.Dict( dict( - classPeriodReference=factory.Dict(dict(classPeriodName=None)), + classPeriodReference=factory.Dict(dict(classPeriodName=None, schoolId=SchoolClient.shared_elementary_school_id())), ) ), ] diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/community.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/community.py index cb3ed889..88199a46 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/community.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/community.py @@ -28,7 +28,7 @@ class CommunityOrganizationFactory(APIFactory): ] ) categories = ListOfDescriptors("EducationOrganizationCategory", ["School"]) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("Other", {"identificationCode": o.communityOrganizationId})], @@ -53,7 +53,7 @@ class CommunityProviderFactory(APIFactory): ] ) categories = ListOfDescriptors("EducationOrganizationCategory", ["School"]) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("Other", {"identificationCode": o.communityProviderId})], diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/course.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/course.py index 616a8cac..92717988 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/course.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/course.py @@ -62,3 +62,4 @@ class CourseTranscriptFactory(APIFactory): courseAttemptResultDescriptor = build_descriptor("CourseAttemptResult", "Pass") finalLetterGradeEarned = "B" finalNumericGradeEarned = 83 + earnedCredits = 3 diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/discipline.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/discipline.py index 699e0bf3..6c1e8dba 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/discipline.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/discipline.py @@ -65,6 +65,6 @@ class DisciplineIncidentFactory(APIFactory): ) ] ) - incidentLocationDescriptor = build_descriptor("IncidentLocation", "School Bus") + incidentLocationDescriptor = build_descriptor("IncidentLocation", "School bus") reporterDescriptionDescriptor = build_descriptor("ReporterDescription", "Staff") reporterName = "Villa, Mike" diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/education.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/education.py index f2a52813..e336739b 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/education.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/education.py @@ -31,7 +31,7 @@ class EducationServiceCenterFactory(APIFactory): categories = ListOfDescriptors( "EducationOrganizationCategory", ["Education Service Center"] ) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": o.educationServiceCenterId})], @@ -53,7 +53,7 @@ class LocalEducationAgencyFactory(APIFactory): localEducationAgencyCategoryDescriptor = build_descriptor( "LocalEducationAgencyCategory", "Independent" ) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": o.localEducationAgencyId})], @@ -66,8 +66,10 @@ class LocalEducationAgencyFactory(APIFactory): class EducationContentFactory(APIFactory): contentIdentifier = UniqueIdAttribute(num_chars=60) - description = "A learning resource for all grade levels" + shortDescription = "A learning resource for all grade levels" namespace = "uri://ed-fi.org" + learningResourceMetadataURI = "uri://ed-fi.org/whatever" + contentClassDescriptor = "uri://ed-fi.org/ContentClassDescriptor#Presentation" class EducationOrganizationInterventionPrescriptionAssociationFactory(APIFactory): @@ -95,7 +97,7 @@ class EducationOrganizationNetworkFactory(APIFactory): ] ) categories = ListOfDescriptors("EducationOrganizationCategory", ["School"]) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": o.educationOrganizationNetworkId})], @@ -142,7 +144,7 @@ class StateEducationAgencyFactory(APIFactory): categories = ListOfDescriptors( "EducationOrganizationCategory", ["Local Education Agency"] ) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": o.stateEducationAgencyId})], diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/grading_period.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/grading_period.py index b012c13d..ec3b74bd 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/grading_period.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/grading_period.py @@ -8,11 +8,10 @@ from edfi_performance_test.api.client.school import SchoolClient from edfi_performance_test.factories.resources.api_factory import APIFactory from edfi_performance_test.factories.descriptors.utils import build_descriptor -from edfi_performance_test.factories.utils import UniquePrimaryKeyAttribute class GradingPeriodFactory(APIFactory): - periodSequence = UniquePrimaryKeyAttribute() + periodSequence = 1 beginDate = "2014-08-23" endDate = "2014-10-04" totalInstructionalDays = 29 diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/school.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/school.py index 3feb80ea..53f40927 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/school.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/school.py @@ -32,7 +32,7 @@ class SchoolFactory(APIFactory): educationOrganizationCategories = ListOfDescriptors( "EducationOrganizationCategory", ["School"] ) - educationOrganizationCodes = factory.LazyAttribute( + identificationCodes = factory.LazyAttribute( lambda o: build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": str(o.schoolId)})], diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/session.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/session.py index 0beab5bc..652196ba 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/session.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/session.py @@ -27,6 +27,8 @@ class SessionFactory(APIFactory): "GradingPeriod", "First Six Weeks" ), periodSequence=None, # Must be entered by client + schoolYear=2014, + schoolId=SchoolClient.shared_elementary_school_id(), ) ), ), @@ -39,6 +41,8 @@ class SessionFactory(APIFactory): "GradingPeriod", "Second Six Weeks" ), periodSequence=None, # Must be entered by client + schoolYear=2014, + schoolId=SchoolClient.shared_elementary_school_id(), ) ), ), diff --git a/src/edfi-performance-test/edfi_performance_test/factories/resources/student.py b/src/edfi-performance-test/edfi_performance_test/factories/resources/student.py index 0fce580d..f9e7f7dc 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/resources/student.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/resources/student.py @@ -7,6 +7,7 @@ from edfi_performance_test.api.client.education import LocalEducationAgencyClient from edfi_performance_test.api.client.school import SchoolClient +from edfi_performance_test.api.client.program import ProgramClient from edfi_performance_test.factories.resources.api_factory import APIFactory from edfi_performance_test.factories.descriptors.utils import build_descriptor from edfi_performance_test.factories.resources.address import AddressFactory @@ -17,6 +18,8 @@ RandomDateAttribute, ) +SESSION_NAME = "2016-2017 Fall Semester" + class StudentFactory(APIFactory): studentUniqueId = UniqueIdAttribute() @@ -26,73 +29,9 @@ class StudentFactory(APIFactory): lastSurname = "Jones" generationCodeSuffix = "JR" personalTitlePrefix = "Mr" - hispanicLatinoEthnicity = False birthCity = "Grand Bend" birthCountryDescriptor = build_descriptor("Country", "AG") birthStateAbbreviationDescriptor = build_descriptor("StateAbbreviation", "TX") - addresses = factory.List( - [ - factory.SubFactory( - AddressFactory, - addressTypeDescriptor=build_descriptor("AddressType", "Temporary"), - city="Grand Bend", - postalCode="78834", - streetNumberName="654 Mission Hills", - apartmentRoomSuiteNumber="100", - nameOfCounty="Williston", - ) - ] - ) - electronicMails = factory.List( - [ - dict( - electronicMailAddress="Austin@edficert.org", - electronicMailTypeDescriptor=build_descriptor( - "ElectronicMailType", "Other" - ), - ), - ] - ) - identificationCodes = factory.List( - [ - dict( - identificationCode=704, - assigningOrganizationIdentificationCode="State", - studentIdentificationSystemDescriptor=build_descriptor( - "StudentIdentificationSystem", "State" - ), - ), - ] - ) - studentLanguages = factory.List( - [ - dict( - languageDescriptor=build_descriptor("Language", "Spanish"), - ), - ] - ) - studentLanguageUses = factory.List( - [ - dict( - languageUseDescriptor=build_descriptor("LanguageUse", "Home language"), - ), - ] - ) - studentRaces = factory.List( - [ - dict(raceDescriptor=build_descriptor("Race", "Black - African American")), - ] - ) - telephones = factory.List( - [ - dict( - telephoneNumber="111-222-3333", - telephoneNumberTypeDescriptor=build_descriptor( - "TelephoneNumberType", "Home" - ), - ), - ] - ) class StudentCohortAssociationFactory(APIFactory): @@ -153,6 +92,63 @@ class StudentEducationOrganizationAssociationFactory(APIFactory): ] ) sexDescriptor = build_descriptor("Sex", "Male") + hispanicLatinoEthnicity = True + addresses = factory.List( + [ + factory.SubFactory( + AddressFactory, + addressTypeDescriptor=build_descriptor("AddressType", "Temporary"), + city="Grand Bend", + postalCode="78834", + streetNumberName="654 Mission Hills", + apartmentRoomSuiteNumber="100", + nameOfCounty="Williston", + ) + ] + ) + electronicMails = factory.List( + [ + dict( + electronicMailAddress="Austin@edficert.org", + electronicMailTypeDescriptor=build_descriptor( + "ElectronicMailType", "Other" + ), + ), + ] + ) + studentIdentificationCodes = factory.List( + [ + dict( + identificationCode=704, + assigningOrganizationIdentificationCode="State", + studentIdentificationSystemDescriptor=build_descriptor( + "StudentIdentificationSystem", "State" + ), + ), + ] + ) + languages = factory.List( + [ + dict( + languageDescriptor=build_descriptor("Language", "Spanish"), + ), + ] + ) + races = factory.List( + [ + dict(raceDescriptor=build_descriptor("Race", "Black - African American")), + ] + ) + telephones = factory.List( + [ + dict( + telephoneNumber="111-222-3333", + telephoneNumberTypeDescriptor=build_descriptor( + "TelephoneNumberType", "Home" + ), + ), + ] + ) class StudentParentAssociationFactory(APIFactory): @@ -176,10 +172,8 @@ class StudentProgramAssociationFactory(APIFactory): ) # Prepopulated ed organization programReference = factory.Dict( dict( - programTypeDescriptor=build_descriptor( - "ProgramType", "Gifted and Talented" - ), - programName="Gifted and Talented", + programTypeDescriptor=build_descriptor("ProgramType", ProgramClient.shared_program_name()), + programName=ProgramClient.shared_program_name(), educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), # Prepopulated ed organization ) ) @@ -196,7 +190,7 @@ class StudentSchoolAssociationFactory(APIFactory): entryDate = RandomDateAttribute() entryGradeLevelDescriptor = build_descriptor("GradeLevel", "First Grade") classOfSchoolYearTypeReference = factory.Dict(dict(schoolYear=2027)) - schoolYear = current_year() + schoolYearTypeReference = factory.Dict(dict(schoolYear=current_year())) entryTypeDescriptor = build_descriptor("EntryType", "Next year school") repeatGradeIndicator = False residencyStatusDescriptor = build_descriptor( @@ -216,8 +210,8 @@ class StudentTitleIPartAProgramAssociationFactory(APIFactory): ) # Prepopulated ed organization programReference = factory.Dict( dict( - programTypeDescriptor=build_descriptor("ProgramType", "Title I Part A"), - programName="Title I Part A", + programTypeDescriptor=build_descriptor("ProgramType", ProgramClient.shared_program_name()), + programName=ProgramClient.shared_program_name(), educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), # Prepopulated ed organization ) ) @@ -238,8 +232,8 @@ class StudentSpecialEducationProgramAssociationFactory(APIFactory): ) # Prepopulated ed organization programReference = factory.Dict( dict( - programTypeDescriptor=build_descriptor("ProgramType", "Special Education"), - programName="Special Education", + programTypeDescriptor=build_descriptor("ProgramType", ProgramClient.shared_program_name()), + programName=ProgramClient.shared_program_name(), educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), # Prepopulated ed organization ) ) @@ -257,7 +251,7 @@ class StudentSectionAssociationFactory(APIFactory): schoolId=SchoolClient.shared_elementary_school_id(), schoolYear=current_year(), sectionIdentifier="ELA012017RM555", - sessionName="2016-2017 Fall Semester", + sessionName=SESSION_NAME, ) ) studentReference = factory.Dict( @@ -276,7 +270,7 @@ class StudentSchoolAttendanceEventFactory(APIFactory): dict( schoolId=SchoolClient.shared_elementary_school_id(), # Prepopulated school schoolYear=2014, # Prepopulated schoolYear - sessionName="2016-2017 Fall Semester", # Default value for scenarios, but not in the DB + sessionName=SESSION_NAME, # Default value for scenarios, but not in the DB ) ) studentReference = factory.Dict( @@ -295,7 +289,7 @@ class StudentSectionAttendanceEventFactory(APIFactory): schoolId=SchoolClient.shared_elementary_school_id(), schoolYear=current_year(), sectionIdentifier="ELA012017RM555", - sessionName="2016-2017 Fall Semester", + sessionName=SESSION_NAME, ) ) studentReference = factory.Dict( @@ -335,7 +329,7 @@ class StudentCompetencyObjectiveFactory(APIFactory): ), ) ) - objectiveCompetencyObjectiveReference = factory.Dict( + competencyObjectiveReference = factory.Dict( dict( educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), # Prepopulated ed org objective=None, # Must be entered by the user @@ -346,6 +340,7 @@ class StudentCompetencyObjectiveFactory(APIFactory): class StudentCTEProgramAssociationFactory(APIFactory): + educationOrganizationReference = factory.Dict( dict( educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id() @@ -355,10 +350,11 @@ class StudentCTEProgramAssociationFactory(APIFactory): dict(studentUniqueId=None) ) programReference = factory.Dict( + dict( educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), - programTypeDescriptor=None, - programName=None, + programTypeDescriptor=build_descriptor("ProgramType", ProgramClient.shared_program_name()), + programName=ProgramClient.shared_program_name(), ) ) # Prepopulated program beginDate = RandomDateAttribute() @@ -385,7 +381,7 @@ class StudentGradebookEntryFactory(APIFactory): schoolId=SchoolClient.shared_elementary_school_id(), schoolYear=current_year(), sectionIdentifier="ELA012017RM555", - sessionName="2016-2017 Fall Semester", + sessionName=SESSION_NAME, gradebookEntryTitle="ALG-1 - First Six Weeks - Homework - 20170821", dateAssigned=formatted_date(2, 2), ) @@ -396,7 +392,7 @@ class StudentGradebookEntryFactory(APIFactory): schoolId=SchoolClient.shared_elementary_school_id(), schoolYear=current_year(), sectionIdentifier="ELA012017RM555", - sessionName="2016-2017 Fall Semester", + sessionName=SESSION_NAME, studentUniqueId=111111, beginDate=formatted_date(5, 5), ) @@ -413,8 +409,8 @@ class StudentHomelessProgramAssociationFactory(APIFactory): programReference = factory.Dict( dict( educationOrganizationId=LocalEducationAgencyClient.shared_education_organization_id(), - programTypeDescriptor=None, - programName=None, + programTypeDescriptor=build_descriptor("ProgramType", ProgramClient.shared_program_name()), + programName=ProgramClient.shared_program_name(), ) ) # Prepopulated program studentReference = factory.Dict( diff --git a/src/edfi-performance-test/edfi_performance_test/factories/utils.py b/src/edfi-performance-test/edfi_performance_test/factories/utils.py index e21c768e..5ec9317a 100644 --- a/src/edfi-performance-test/edfi_performance_test/factories/utils.py +++ b/src/edfi-performance-test/edfi_performance_test/factories/utils.py @@ -82,6 +82,15 @@ def evaluate(self, instance, step, extra): ) +def random_date_time() -> str: + """ + Returns a random date time between 1/1/1901 and 12/28/2050. Ignores days + of the month past the 28th. + """ + + return f"{random.randint(1901, 2050)}-{str(random.randint(1, 12)).zfill(2)}-{str(random.randint(1, 28)).zfill(2)}T15:00:00Z" + + class RandomSchoolYearAttribute(declarations.BaseDeclaration): """ Returns a random date between 1991 & 2050. diff --git a/src/edfi-performance-test/edfi_performance_test/helpers/argparser.py b/src/edfi-performance-test/edfi_performance_test/helpers/argparser.py index 8f053605..d52bfe8e 100644 --- a/src/edfi-performance-test/edfi_performance_test/helpers/argparser.py +++ b/src/edfi-performance-test/edfi_performance_test/helpers/argparser.py @@ -172,6 +172,14 @@ def parse_main_arguments() -> MainArguments: env_var="PERF_DISABLE_COMPOSITES", default=False ) + parser.add( # type: ignore + "-id", + "--includeID", + help="Include ID in body of PUT requests", + type=str, + env_var="INCLUDE_ID_IN_BODY", + default=False + ) args_parsed = parser.parse_args() arguments = MainArguments( @@ -192,7 +200,8 @@ def parse_main_arguments() -> MainArguments: args_parsed.oauthEndpoint, args_parsed.localEducationOrganizationId, args_parsed.logLevel, - args_parsed.disableComposites + args_parsed.disableComposites, + args_parsed.includeID ) return arguments diff --git a/src/edfi-performance-test/edfi_performance_test/helpers/config.py b/src/edfi-performance-test/edfi_performance_test/helpers/config.py index d9b80c75..4e544da5 100644 --- a/src/edfi-performance-test/edfi_performance_test/helpers/config.py +++ b/src/edfi-performance-test/edfi_performance_test/helpers/config.py @@ -46,6 +46,7 @@ def set_config_values(args: MainArguments): os.environ["PERF_API_OAUTH_PREFIX"] = args.oauth_endpoint os.environ["PERF_LOCAL_EDUCATION_ORGANIZATION_ID"] = str(args.localEducationOrganizationId) os.environ["PERF_DISABLE_COMPOSITES"] = str(args.disableComposites) + os.environ["INCLUDE_ID_IN_BODY"] = str(args.includeID) def _get_change_version_file_path(): diff --git a/src/edfi-performance-test/edfi_performance_test/helpers/main_arguments.py b/src/edfi-performance-test/edfi_performance_test/helpers/main_arguments.py index 721a426d..36c6be89 100644 --- a/src/edfi-performance-test/edfi_performance_test/helpers/main_arguments.py +++ b/src/edfi-performance-test/edfi_performance_test/helpers/main_arguments.py @@ -34,6 +34,7 @@ class MainArguments: localEducationOrganizationId: int log_level: LogLevel = LogLevel.INFO disableComposites: bool = False + includeID: bool = False def __str__(self) -> str: def _masked(key: str) -> str: diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/account.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/account.py index d5e4bf8a..4ccf61ba 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/account.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/account.py @@ -3,7 +3,6 @@ # The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. # See the LICENSE and NOTICES files in the project root for more information. -from edfi_performance_test.factories.descriptors.utils import build_descriptor from edfi_performance_test.tasks.pipeclean.ed_fi_pipeclean_test_base import ( EdFiPipecleanTestBase, ) @@ -16,8 +15,8 @@ class AccountPipecleanTest(EdFiPipecleanTestBase): class AccountCodePipecleanTest(EdFiPipecleanTestBase): - update_attribute_name = "accountClassificationDescriptor" - update_attribute_value = build_descriptor("AccountClassification", "Fund") + update_attribute_name = "accountCodeDescription" + update_attribute_value = "another description" class ActualPipecleanTest(EdFiPipecleanTestBase): diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/assessment.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/assessment.py index 2a69bc78..f4c171d9 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/assessment.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/assessment.py @@ -9,7 +9,7 @@ class AssessmentPipecleanTest(EdFiPipecleanTestBase): - update_attribute_name = "title" + update_attribute_name = "assessmentTitle" update_attribute_value = "AP English 3" diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/class_period.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/class_period.py index 541fc91a..7a1af4fe 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/class_period.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/class_period.py @@ -10,5 +10,6 @@ class ClassPeriodPipecleanTest(EdFiPipecleanTestBase): + # This is an allowed natural key update, which should automatically cascade through the API without error update_attribute_name = "classPeriodName" update_attribute_value = RandomSuffixAttribute("Class Period 01", suffix_length=10) diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/gradebook_entries.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/gradebook_entries.py index 1e572829..74e7dc76 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/gradebook_entries.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/gradebook_entries.py @@ -10,5 +10,6 @@ class GradebookEntryPipecleanTest(EdFiPipecleanTestBase): + # This is an allowed natural key update update_attribute_name = "dateAssigned" update_attribute_value = formatted_date(3, 3) diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/parent.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/parent.py index 000f26c0..e1001861 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/parent.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/parent.py @@ -10,7 +10,7 @@ class ParentPipecleanTest(EdFiPipecleanTestBase): - update_attribute_name = "parentOtherNames" + update_attribute_name = "otherNames" update_attribute_value = [ { "firstName": "Lexi", diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/student.py b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/student.py index 28579e11..531a1746 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/student.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/pipeclean/student.py @@ -23,7 +23,8 @@ class StudentSchoolAssociationPipecleanTest(EdFiPipecleanTestBase): class StudentPipecleanTest(EdFiPipecleanTestBase): def _touch_put_endpoint(self, resource_id, attrs): - attrs["telephones"][0]["telephoneNumber"] = "111-222-4444" + if "telepphones" in attrs and len(attrs["telephones"]) > 0: + attrs["telephones"][0]["telephoneNumber"] = "111-222-4444" self.update(resource_id, **attrs) diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/volume/ed_fi_volume_test_base.py b/src/edfi-performance-test/edfi_performance_test/tasks/volume/ed_fi_volume_test_base.py index 74f86481..0a8e708c 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/volume/ed_fi_volume_test_base.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/volume/ed_fi_volume_test_base.py @@ -46,6 +46,8 @@ def _update_attribute( update_attribute_value, **kwargs ): + if get_config_value("INCLUDE_ID_IN_BODY").lower() == "true": + resource_attrs["id"] = resource_id resource_attrs[update_attribute_name] = update_attribute_value self.update(resource_id, **resource_attrs) diff --git a/src/edfi-performance-test/edfi_performance_test/tasks/volume/school.py b/src/edfi-performance-test/edfi_performance_test/tasks/volume/school.py index 07c60c48..640b2120 100644 --- a/src/edfi-performance-test/edfi_performance_test/tasks/volume/school.py +++ b/src/edfi-performance-test/edfi_performance_test/tasks/volume/school.py @@ -8,6 +8,7 @@ from edfi_performance_test.factories.descriptors.utils import build_descriptor_dicts from edfi_performance_test.factories.utils import random_chars from edfi_performance_test.tasks.volume.ed_fi_volume_test_base import EdFiVolumeTestBase +from edfi_performance_test.helpers.config import get_config_value class SchoolVolumeTest(EdFiVolumeTestBase): @@ -28,7 +29,7 @@ def run_school_scenarios(self): "InstitutionTelephoneNumberType", [("Main", {"telephoneNumber": "(950) 325-9465"})], ), - educationOrganizationCodes=build_descriptor_dicts( + identificationCodes=build_descriptor_dicts( "EducationOrganizationIdentificationSystem", [("SEA", {"identificationCode": "255901444"})], ), @@ -42,6 +43,10 @@ def _update_attribute( update_attribute_value, **kwargs ): + + if get_config_value("INCLUDE_ID_IN_BODY").lower() == "true": + resource_attrs["id"] = resource_id + if update_attribute_name == "telephoneNumber": # Update first institutionTelephones record resource_attrs["institutionTelephones"][0][ diff --git a/src/edfi-performance-test/pyproject.toml b/src/edfi-performance-test/pyproject.toml index 814faa18..af02fa6c 100644 --- a/src/edfi-performance-test/pyproject.toml +++ b/src/edfi-performance-test/pyproject.toml @@ -31,6 +31,9 @@ types-urllib3 = "^1.26.15" types-requests = "^2.28.0" +[tool.poetry.group.dev.dependencies] +pytest-describe = "^2.0.1" + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" diff --git a/src/edfi-performance-test/tests/factories/__init__.py b/src/edfi-performance-test/tests/factories/__init__.py new file mode 100644 index 00000000..794c49e6 --- /dev/null +++ b/src/edfi-performance-test/tests/factories/__init__.py @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +# Licensed to the Ed-Fi Alliance under one or more agreements. +# The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +# See the LICENSE and NOTICES files in the project root for more information. diff --git a/src/edfi-performance-test/tests/factories/descriptors/__init__.py b/src/edfi-performance-test/tests/factories/descriptors/__init__.py new file mode 100644 index 00000000..794c49e6 --- /dev/null +++ b/src/edfi-performance-test/tests/factories/descriptors/__init__.py @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +# Licensed to the Ed-Fi Alliance under one or more agreements. +# The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +# See the LICENSE and NOTICES files in the project root for more information. diff --git a/src/edfi-performance-test/tests/factories/descriptors/test_utils.py b/src/edfi-performance-test/tests/factories/descriptors/test_utils.py new file mode 100644 index 00000000..8590cb16 --- /dev/null +++ b/src/edfi-performance-test/tests/factories/descriptors/test_utils.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: Apache-2.0 +# Licensed to the Ed-Fi Alliance under one or more agreements. +# The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +# See the LICENSE and NOTICES files in the project root for more information. + +from typing import Dict, List +import pytest + +from edfi_performance_test.factories.descriptors.utils import build_descriptor_dicts, build_descriptor + + +def describe_when_building_a_descriptor() -> None: + @pytest.mark.parametrize("input, expected", [ + ("Title", "uri://ed-fi.org/TitleDescriptor#value"), + ("title", "uri://ed-fi.org/TitleDescriptor#value"), + ("titledescriptor", "uri://ed-fi.org/TitledescriptorDescriptor#value"), + ("title_descriptor", "uri://ed-fi.org/TitleDescriptor#value"), + ]) + def it_formats_the_descriptor_string_correctly(input: str, expected: str) -> None: + actual = build_descriptor(input, "value") + + assert actual == expected + + +def describe_when_building_a_descriptor_dictionary() -> None: + def describe_given_two_grade_levels() -> None: + @pytest.fixture + def result() -> List[str]: + result = build_descriptor_dicts( + "GradeLevel", ["Ninth grade", "Tenth grade"] + ) + + descriptors = [i['gradeLevelDescriptor'] for i in result] + assert len(descriptors) == 2 + + return descriptors + + @pytest.mark.parametrize("expected", [("uri://ed-fi.org/GradeLevelDescriptor#Ninth grade"), ("uri://ed-fi.org/GradeLevelDescriptor#Tenth grade")]) + def it_includes_all_grades(result, expected) -> None: + assert expected in result + + def describe_given_a_telephone_number() -> None: + @pytest.fixture + def result() -> Dict[str, str]: + result = build_descriptor_dicts( + "InstitutionTelephoneNumberType", [("Main", {"telephoneNumber": "(950) 325-9465"})] + ) + + assert len(result) == 1 + + return result[0] + + def it_references_the_descriptor_properly(result) -> None: + assert result["institutionTelephoneNumberTypeDescriptor"] == "uri://ed-fi.org/InstitutionTelephoneNumberTypeDescriptor#Main" + + def it_includes_the_telephone_number(result) -> None: + assert result["telephoneNumber"] == "(950) 325-9465" diff --git a/src/edfi-performance-test/tests/factories/test_utils.py b/src/edfi-performance-test/tests/factories/test_utils.py index 8e386ce7..de2b4d32 100644 --- a/src/edfi-performance-test/tests/factories/test_utils.py +++ b/src/edfi-performance-test/tests/factories/test_utils.py @@ -8,24 +8,24 @@ from edfi_performance_test.factories.utils import formatted_date -class Test_utils(object): - def test_given_no_year_when_formatting_date_then_use_current_year(self): +def describe_when_formatting_a_date() -> None: + def describe_given_no_year_provided() -> None: + def it_formats_using_current_year() -> None: + month = 12 + day = 1 + expected = str(date.today().year) + "-12-01" - month = 12 - day = 1 - expected = str(date.today().year) + "-12-01" + actual = formatted_date(month, day) - actual = formatted_date(month, day) + assert actual == expected - assert actual == expected + def describe_given_year_is_provided() -> None: + def it_formats_using_the_given_year() -> None: + year = 1999 + month = 12 + day = 1 + expected = "1999-12-01" - def test_given_year_is_supplied_when_formatting_date_then_use_supplied_year(self): + actual = formatted_date(month, day, year) - year = 1999 - month = 12 - day = 1 - expected = "1999-12-01" - - actual = formatted_date(month, day, year) - - assert actual == expected + assert actual == expected diff --git a/src/edfi-performance-test/tests/test_argparser.py b/src/edfi-performance-test/tests/test_argparser.py index 9dfc188b..f8571590 100644 --- a/src/edfi-performance-test/tests/test_argparser.py +++ b/src/edfi-performance-test/tests/test_argparser.py @@ -143,6 +143,7 @@ def main_arguments() -> MainArguments: os.environ["PERF_TEST_LIST"] = '["a", "b"]' os.environ["PERF_FAIL_DELIBERATELY"] = "True" os.environ["PERF_DISABLE_COMPOSITES"] = "True" + os.environ["INCLUDE_ID_IN_BODY"] = "False" sys.argv = ["pytest"] return parse_main_arguments()