-
Notifications
You must be signed in to change notification settings - Fork 97
Feature/allocation model get information tests #707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,15 +7,21 @@ | |
import datetime | ||
|
||
from django.core.exceptions import ValidationError | ||
from django.test import TestCase | ||
from django.test import TestCase, override_settings | ||
from django.utils import timezone | ||
from django.utils.html import format_html | ||
from django.utils.safestring import SafeString | ||
|
||
from coldfront.core.allocation.models import ( | ||
Allocation, | ||
AllocationAttribute, | ||
AllocationStatusChoice, | ||
) | ||
from coldfront.core.project.models import Project | ||
from coldfront.core.test_helpers.factories import ( | ||
AllocationAttributeFactory, | ||
AllocationAttributeTypeFactory, | ||
AllocationAttributeUsageFactory, | ||
AllocationFactory, | ||
AllocationStatusChoiceFactory, | ||
ProjectFactory, | ||
|
@@ -140,3 +146,284 @@ def test_status_is_active_and_start_date_equals_end_date_no_error(self): | |
status=self.active_status, start_date=start_and_end_date, end_date=start_and_end_date, project=self.project | ||
) | ||
actual_allocation.full_clean() | ||
|
||
|
||
class AllocationModelGetInformationTests(TestCase): | ||
path_to_allocation_models_allocation_attribute_view_list: str = ( | ||
"coldfront.core.allocation.models.ALLOCATION_ATTRIBUTE_VIEW_LIST" | ||
) | ||
|
||
attribute_usage_formatter_template: str = "{}: {}/{} ({} %) <br>" | ||
attribute_view_list_formatter_template: str = "{}: {} <br>" | ||
|
||
name_in_view_list_1 = "Something 1" | ||
name_in_view_list_2 = "Something Else" | ||
name_not_in_view_list_1 = "This is another thing " | ||
name_not_in_view_list_2 = "This Is Not In List" | ||
sample_allocation_attribute_view_list = [name_in_view_list_1, name_in_view_list_2] | ||
|
||
def find_percent(self, numerator, denominator): | ||
return round(float(numerator) / float(denominator) * 10000) / 100 | ||
|
||
def test_no_allocation_attributes_returns_empty_string(self): | ||
"""Test that the get_information method returns an empty string if there are no allocation attributes.""" | ||
allocation: Allocation = AllocationFactory() | ||
self.assertEqual(allocation.get_information, "") | ||
|
||
@override_settings(ALLOCATION_ATTRIBUTE_VIEW_LIST=sample_allocation_attribute_view_list) | ||
def test_attribute_type_not_in_view_list_returns_without_type_substring_included(self): | ||
"""Test that the get_information method returns a string without the attribute type substring when the type name is not in ALLOCATION_ATTRIBUTE_VIEW_LIST.""" | ||
allocation: Allocation = AllocationFactory() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we we move this allocation factory call to a test setup function if every test in this class runs the same setup step |
||
allocation_attribute_type = AllocationAttributeTypeFactory(name="Not a name in the view list") | ||
allocation_attribute = AllocationAttributeFactory( | ||
allocation_attribute_type=allocation_attribute_type, allocation=allocation | ||
) | ||
allocation_attribute_usage = AllocationAttributeUsageFactory(allocation_attribute=allocation_attribute) | ||
|
||
expected_percent = self.find_percent(allocation_attribute_usage.value, allocation_attribute.value) | ||
|
||
expected_information: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
allocation_attribute_type.name, | ||
float(allocation_attribute_usage.value), | ||
allocation_attribute.value, | ||
expected_percent, | ||
) | ||
|
||
self.assertHTMLEqual(allocation.get_information, expected_information) | ||
|
||
@override_settings(ALLOCATION_ATTRIBUTE_VIEW_LIST=sample_allocation_attribute_view_list) | ||
def test_attribute_type_in_view_list_returns_with_type_substring_included(self): | ||
"""Test that the get_information method returns a string with the attribute type substring when the type name is in ALLOCATION_ATTRIBUTE_VIEW_LIST.""" | ||
allocation: Allocation = AllocationFactory() | ||
allocation_attribute_type = AllocationAttributeTypeFactory(name=self.name_in_view_list_1) | ||
allocation_attribute = AllocationAttributeFactory( | ||
allocation_attribute_type=allocation_attribute_type, allocation=allocation | ||
) | ||
allocation_attribute_usage = AllocationAttributeUsageFactory(allocation_attribute=allocation_attribute) | ||
|
||
expected_percent = self.find_percent(allocation_attribute_usage.value, allocation_attribute.value) | ||
|
||
regular_substring: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
allocation_attribute_type.name, | ||
float(allocation_attribute_usage.value), | ||
allocation_attribute.value, | ||
expected_percent, | ||
) | ||
|
||
view_list_substring: SafeString = format_html( | ||
self.attribute_view_list_formatter_template, allocation_attribute_type.name, allocation_attribute.value | ||
) | ||
|
||
expected_information: SafeString = view_list_substring + regular_substring | ||
|
||
self.assertHTMLEqual(allocation.get_information, expected_information) | ||
|
||
def test_attribute_value_is_zero_returns_100_percent_string(self): | ||
allocation: Allocation = AllocationFactory() | ||
allocation_attribute: AllocationAttribute = AllocationAttributeFactory(allocation=allocation, value=0) | ||
allocation_attribute_usage = AllocationAttributeUsageFactory( | ||
allocation_attribute=allocation_attribute, value=10 | ||
) | ||
|
||
allocation_attribute_type_name: str = allocation_attribute.allocation_attribute_type.name | ||
allocation_attribute_usage_value: float = float(allocation_attribute_usage.value) | ||
allocation_attribute_value: str = allocation_attribute.value | ||
expected_percent = 100 | ||
|
||
expected_information: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
allocation_attribute_type_name, | ||
allocation_attribute_usage_value, | ||
allocation_attribute_value, | ||
expected_percent, | ||
) | ||
|
||
self.assertHTMLEqual(allocation.get_information, expected_information) | ||
|
||
def test_multiple_attributes_with_same_type_returns_combined_information(self): | ||
"""Test that the get_information method returns combined information for multiple attributes.""" | ||
allocation: Allocation = AllocationFactory() | ||
allocation_attribute_type = AllocationAttributeTypeFactory() | ||
|
||
allocation_attribute_1: AllocationAttribute = AllocationAttributeFactory( | ||
allocation=allocation, allocation_attribute_type=allocation_attribute_type, value=100 | ||
) | ||
allocation_attribute_2: AllocationAttribute = AllocationAttributeFactory( | ||
allocation=allocation, allocation_attribute_type=allocation_attribute_type, value=1000 | ||
) | ||
allocation_attribute_usage_1 = AllocationAttributeUsageFactory( | ||
allocation_attribute=allocation_attribute_1, value=50 | ||
) | ||
allocation_attribute_usage_2 = AllocationAttributeUsageFactory( | ||
allocation_attribute=allocation_attribute_2, value=500 | ||
) | ||
|
||
percent_1 = self.find_percent(allocation_attribute_usage_1.value, allocation_attribute_1.value) | ||
percent_2 = self.find_percent(allocation_attribute_usage_2.value, allocation_attribute_2.value) | ||
|
||
expected_information: SafeString = format_html( | ||
"{}: {}/{} ({} %) <br>{}: {}/{} ({} %) <br>", | ||
allocation_attribute_type.name, | ||
float(allocation_attribute_usage_1.value), | ||
allocation_attribute_1.value, | ||
percent_1, | ||
allocation_attribute_type.name, | ||
float(allocation_attribute_usage_2.value), | ||
allocation_attribute_2.value, | ||
percent_2, | ||
) | ||
|
||
self.assertHTMLEqual(allocation.get_information, expected_information) | ||
|
||
@override_settings(ALLOCATION_ATTRIBUTE_VIEW_LIST=sample_allocation_attribute_view_list) | ||
def test_attributes_with_names_in_view_list_included_in_information(self): | ||
"""Test that only allocations with AttributeTypes whose names are in ALLOCATION_ATTRIBUTE_VIEW_LIST | ||
have their special snippets also included in the information""" | ||
|
||
# AllocationAttributeTypes whose names are inside of ALLOCATION_ATTRIBUTE_VIEW_LIST | ||
attribute_type_in_view_list_1 = AllocationAttributeTypeFactory(name=self.name_in_view_list_1) | ||
attribute_type_in_view_list_2 = AllocationAttributeTypeFactory(name=self.name_in_view_list_2) | ||
|
||
# AllocationAttributeTypes whose names are NOT inside of ALLOCATION_ATTRIBUTE_VIEW_LIST | ||
attribute_type_not_in_view_list_1 = AllocationAttributeTypeFactory(name=self.name_not_in_view_list_1) | ||
attribute_type_not_in_view_list_2 = AllocationAttributeTypeFactory(name=self.name_not_in_view_list_2) | ||
|
||
# Allocation that we are testing, needed for creating AllocationAttributes | ||
tested_allocation: Allocation = AllocationFactory() | ||
|
||
# AllocationAttribute for each AllocationAttributeType | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have concerns about how maintainable this test will be, I think maybe adding some comments to provide more context for how you're constructing the test example might make it a little easier to parse and understand. |
||
|
||
view_list_allocation_attribute_value_1 = 2000 | ||
view_list_allocation_attribute_1 = AllocationAttributeFactory( | ||
allocation_attribute_type=attribute_type_in_view_list_1, | ||
value=view_list_allocation_attribute_value_1, | ||
allocation=tested_allocation, | ||
) | ||
|
||
view_list_allocation_attribute_value_2 = 5000 | ||
view_list_allocation_attribute_2 = AllocationAttributeFactory( | ||
allocation_attribute_type=attribute_type_in_view_list_2, | ||
value=view_list_allocation_attribute_value_2, | ||
allocation=tested_allocation, | ||
) | ||
|
||
no_view_list_allocation_attribute_value_1 = 20 | ||
no_view_list_allocation_attribute_1 = AllocationAttributeFactory( | ||
allocation_attribute_type=attribute_type_not_in_view_list_1, | ||
value=no_view_list_allocation_attribute_value_1, | ||
allocation=tested_allocation, | ||
) | ||
|
||
no_view_list_allocation_attribute_value_2 = 80000 | ||
no_view_list_allocation_attribute_2 = AllocationAttributeFactory( | ||
allocation_attribute_type=attribute_type_not_in_view_list_2, | ||
value=no_view_list_allocation_attribute_value_2, | ||
allocation=tested_allocation, | ||
) | ||
|
||
# AllocationAttributeUsage for each AllocationAttribute | ||
view_list_allocation_attribute_usage_value_1 = 4 | ||
view_list_allocation_attribute_usage_1 = AllocationAttributeUsageFactory( # noqa: F841 | ||
allocation_attribute=view_list_allocation_attribute_1, | ||
value=view_list_allocation_attribute_usage_value_1, | ||
) | ||
|
||
view_list_allocation_attribute_usage_value_2 = 200 | ||
view_list_allocation_attribute_usage_2 = AllocationAttributeUsageFactory( # noqa: F841 | ||
allocation_attribute=view_list_allocation_attribute_2, | ||
value=view_list_allocation_attribute_usage_value_2, | ||
) | ||
|
||
no_view_list_allocation_attribute_usage_value_1 = 5 | ||
no_view_list_allocation_attribute_usage_1 = AllocationAttributeUsageFactory( # noqa: F841 | ||
allocation_attribute=no_view_list_allocation_attribute_1, | ||
value=no_view_list_allocation_attribute_usage_value_1, | ||
) | ||
|
||
no_view_list_allocation_attribute_usage_value_2 = 5 | ||
no_view_list_allocation_attribute_usage_2 = AllocationAttributeUsageFactory( # noqa: F841 | ||
allocation_attribute=no_view_list_allocation_attribute_2, | ||
value=no_view_list_allocation_attribute_usage_value_2, | ||
) | ||
|
||
view_list_percent_1 = self.find_percent( | ||
view_list_allocation_attribute_usage_value_1, view_list_allocation_attribute_value_1 | ||
) | ||
view_list_percent_2 = self.find_percent( | ||
view_list_allocation_attribute_usage_value_2, view_list_allocation_attribute_value_2 | ||
) | ||
no_view_list_percent_1 = self.find_percent( | ||
no_view_list_allocation_attribute_usage_value_1, no_view_list_allocation_attribute_value_1 | ||
) | ||
no_view_list_percent_2 = self.find_percent( | ||
no_view_list_allocation_attribute_usage_value_2, no_view_list_allocation_attribute_value_2 | ||
) | ||
|
||
# Build up the substrings that make up the expected information string | ||
|
||
usage_string_from_view_1: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
self.name_in_view_list_1, | ||
float(view_list_allocation_attribute_usage_value_1), | ||
view_list_allocation_attribute_value_1, | ||
view_list_percent_1, | ||
) | ||
|
||
usage_string_from_view_2: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
self.name_in_view_list_2, | ||
float(view_list_allocation_attribute_usage_value_2), | ||
view_list_allocation_attribute_value_2, | ||
view_list_percent_2, | ||
) | ||
|
||
usage_string_from_no_view_1: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
self.name_not_in_view_list_1, | ||
float(no_view_list_allocation_attribute_usage_value_1), | ||
no_view_list_allocation_attribute_value_1, | ||
no_view_list_percent_1, | ||
) | ||
|
||
usage_string_from_no_view_2: SafeString = format_html( | ||
self.attribute_usage_formatter_template, | ||
self.name_not_in_view_list_2, | ||
float(no_view_list_allocation_attribute_usage_value_2), | ||
no_view_list_allocation_attribute_value_2, | ||
no_view_list_percent_2, | ||
) | ||
|
||
typename_string_from_view_1: SafeString = format_html( | ||
self.attribute_view_list_formatter_template, | ||
view_list_allocation_attribute_1.allocation_attribute_type.name, | ||
view_list_allocation_attribute_1.value, | ||
) | ||
|
||
typename_string_from_view_2: SafeString = format_html( | ||
self.attribute_view_list_formatter_template, | ||
view_list_allocation_attribute_2.allocation_attribute_type.name, | ||
view_list_allocation_attribute_2.value, | ||
) | ||
|
||
# Finally we can test the values... | ||
|
||
expected_information: SafeString = format_html( | ||
"{}{}{}{}{}{}", | ||
typename_string_from_view_1, | ||
usage_string_from_view_1, | ||
typename_string_from_view_2, | ||
usage_string_from_view_2, | ||
usage_string_from_no_view_1, | ||
usage_string_from_no_view_2, | ||
) | ||
|
||
actual_information: SafeString = tested_allocation.get_information | ||
|
||
# with open('output.txt', 'w') as f: | ||
# print(f'expected: \n\n{expected_information}', file=f) | ||
# print("\n", file=f) | ||
# print(f'actual: \n\n{actual_information}', file=f) | ||
|
||
self.assertHTMLEqual(expected_information, actual_information) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a comment to explain the math here without having to dig into what is happening in models.py, especially the multiplication by 10000