From 017b9f3d83d7b057f9720e1e004213effa85a0ce Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Wed, 8 Nov 2023 10:49:26 -0500
Subject: [PATCH] Rework internal class inheritance to be more pythonically
 standardized

---
 .../mixins/core_mixin.py                      | 104 +++++++++++-------
 .../mixins/live_server_mixin.py               |  26 ++---
 .../mixins/response_mixin.py                  |  11 +-
 .../test_cases/base_test_case.py              |  82 +++++++++++---
 .../channels_live_server_test_case.py         |  79 +++++++++----
 .../test_cases/integration_test_case.py       |  67 ++++++++++-
 .../test_cases/live_server_test_case.py       |  79 +++++++++----
 tests/test_cases/test_integration_case.py     |   5 +-
 8 files changed, 322 insertions(+), 131 deletions(-)

diff --git a/django_expanded_test_cases/mixins/core_mixin.py b/django_expanded_test_cases/mixins/core_mixin.py
index 7c7ad26..3712457 100644
--- a/django_expanded_test_cases/mixins/core_mixin.py
+++ b/django_expanded_test_cases/mixins/core_mixin.py
@@ -64,25 +64,67 @@ class DebugPrintMetaClass(type):
 
 
 class BaseMixin:
+    """Base mixin that all other project classes should inherit from in some way.
+
+    Basically only exists to guarantee certain expected functions exist during inheritance chain, unconditionally.
+    Helps prevent MethodNotFound errors and make inheritance/super() calls easier to handle.
+    """
+
     @classmethod
-    def set_up_class(cls, *args, **kwargs):
+    def setUpClass(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin setUpClass()')
         pass
 
     @classmethod
-    def set_up_test_data(cls, *args, **kwargs):
+    def setUpTestData(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin setUpTestData()')
         pass
 
-    def set_up(self, *args, **kwargs):
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin setUp()')
         pass
 
-    def sub_test(self, *args, **kwargs):
+    def subTest(self, *args, **kwargs):
+        """Test logic setup run every time we enter a subtest.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin subTest()')
         pass
 
     @classmethod
-    def tear_down_class(cls, *args, **kwargs):
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin tearDownClass()')
         pass
 
-    def tear_down(self, *args, **kwargs):
+    def tearDown(self, *args, **kwargs):
+        """Test logic setup run at the end of function/method execution, as part of termination/clean up.
+
+        Function is empty, but provided to prevent MethodNotFound errors
+        in case super() is called from an inheriting child.
+        """
+        print('BaseMixin tearDown()')
         pass
 
 
@@ -100,18 +142,18 @@ class CoreTestCaseMixin(BaseMixin):
     # region Class Functions
 
     @classmethod
-    def set_up_class(cls, *args, debug_print=None, **kwargs):
-        """
-        Acts as the equivalent of the UnitTesting "setUpClass()" function.
-
-        However, since this is not inheriting from a given TestCase, calling the literal function
-        here would override instead.
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation.
 
         :param debug_print: Optional bool that indicates if debug output should print to console.
                             Param overrides setting value if both param and setting are set.
         """
+        print('CoreMixin setUpClass()')
+
         # Call parent logic.
-        super().set_up_class(*args, **kwargs)
+        super().setUpClass(*args, **kwargs)
+
+        print('Setting up debug_print class variable')
 
         # Check user debug_print option.
         if debug_print is not None:
@@ -119,21 +161,20 @@ class CoreTestCaseMixin(BaseMixin):
         else:
             cls._debug_print_bool = ETC_DEBUG_PRINT
 
+        print('setting up site_root_url class variable')
         cls._site_root_url = None
 
     @classmethod
-    def set_up_test_data(cls, *args, extra_usergen_kwargs=None, **kwargs):
-        """
-        Acts as the equivalent of the UnitTesting "setUpTestData()" function.
-
-        However, since this is not inheriting from a given TestCase, calling the literal function
-        here would override instead.
+    def setUpTestData(cls, *args, extra_usergen_kwargs=None, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup.
 
         :param extra_usergen_kwargs: Optional extra kwargs to pass into the get_user_model().objects.create_user()
                                      function.
         """
+        print('CoreMixin setUpTestData()')
+
         # Call parent logic.
-        super().set_up_test_data(*args, **kwargs)
+        super().setUpTestData(*args, **kwargs)
 
         if ETC_AUTO_GENERATE_USERS:
             # Run logic to auto-generate test users. Setting is on by default.
@@ -147,32 +188,17 @@ class CoreTestCaseMixin(BaseMixin):
 
             cls._auto_generate_test_users(extra_usergen_kwargs=extra_usergen_kwargs)
 
-    def set_up(self, *args, **kwargs):
-        # Call parent logic.
-        super().set_up(*args, **kwargs)
-
-    def sub_test(self, *args, **kwargs):
+    def subTest(self, *args, **kwargs):
+        """Test logic setup run every time we enter a subtest.
         """
-        Acts as the equivalent of the UnitTesting "subtTest()" function.
+        print('CoreMixin subTest()')
 
-        However, since this is not inheriting from a given TestCase, calling the literal function
-        here would override instead.
-        """
         # Call parent logic.
-        super().sub_test(*args, **kwargs)
+        super().subTest(*args, **kwargs)
 
         # Reset display error, in case multiple subtests run and fail in a given test.
         self._error_displayed = False
 
-    @classmethod
-    def tear_down_class(cls, *args, **kwargs):
-        # Call parent logic.
-        super().tear_down_class(*args, **kwargs)
-
-    def tear_down(self, *args, **kwargs):
-        # Call parent logic.
-        super().tear_down(*args, **kwargs)
-
     @classmethod
     def _auto_generate_test_users(cls, extra_usergen_kwargs=None):
         """Logic to automatically generate test users.
diff --git a/django_expanded_test_cases/mixins/live_server_mixin.py b/django_expanded_test_cases/mixins/live_server_mixin.py
index 8cf224f..3d69f18 100644
--- a/django_expanded_test_cases/mixins/live_server_mixin.py
+++ b/django_expanded_test_cases/mixins/live_server_mixin.py
@@ -45,18 +45,14 @@ class LiveServerMixin(ResponseTestCaseMixin):
     """Universal logic for all selenium LiveServer test cases."""
 
     @classmethod
-    def set_up_class(cls, debug_print=None):
-        """
-        Acts as the equivalent of the UnitTesting "setUpClass()" function.
-
-        However, since this is not inheriting from a given TestCase, calling the literal function
-        here would override instead.
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation.
 
         :param debug_print: Optional bool that indicates if debug output should print to console.
                             Param overrides setting value if both param and setting are set.
         """
         # Call CoreMixin setup logic.
-        super().set_up_class(debug_print=debug_print)
+        super().setUpClass(*args, debug_print=debug_print, **kwargs)
 
         # Populate some initial values.
         cls._driver_set = []
@@ -152,20 +148,20 @@ class LiveServerMixin(ResponseTestCaseMixin):
         # Create initial testing driver.
         cls.driver = cls.create_driver(cls)
 
-    def set_up(self):
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution."""
+
         # Call parent logic.
-        super().set_up()
+        super().setUp(*args, **kwargs)
 
         self._error_displayed = False
 
-    def sub_test(self, *args, **kwargs):
-        # Call parent logic.
-        super().sub_test(*args, **kwargs)
-
     @classmethod
-    def tear_down_class(cls):
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up."""
+
         # Call parent teardown logic.
-        super().tear_down_class()
+        super().tearDownClass(*args, **kwargs)
 
         # Close all remaining driver instances for class.
         while len(cls._driver_set) > 0:
diff --git a/django_expanded_test_cases/mixins/response_mixin.py b/django_expanded_test_cases/mixins/response_mixin.py
index 2bc86c9..97377f2 100644
--- a/django_expanded_test_cases/mixins/response_mixin.py
+++ b/django_expanded_test_cases/mixins/response_mixin.py
@@ -27,6 +27,7 @@ from django_expanded_test_cases.constants import (
     ETC_RESPONSE_DEBUG_FORM_COLOR,
     ETC_RESPONSE_DEBUG_USER_INFO_COLOR,
     ETC_OUTPUT_EMPHASIS_COLOR,
+    ETC_AUTO_GENERATE_USERS,
 )
 
 
@@ -38,18 +39,14 @@ class ResponseTestCaseMixin(CoreTestCaseMixin):
     """Includes testing logic used in handling Response objects."""
 
     @classmethod
-    def set_up_class(cls, debug_print=None):
-        """
-        Acts as the equivalent of the UnitTesting "setUpClass()" function.
-
-        However, since this is not inheriting from a given TestCase, calling the literal function
-        here would override instead.
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation.
 
         :param debug_print: Optional bool that indicates if debug output should print to console.
                             Param overrides setting value if both param and setting are set.
         """
         # Run parent setup logic.
-        super().set_up_class(debug_print=debug_print)
+        super().setUpClass(*args, debug_print=debug_print, **kwargs)
 
     # region Debug Output Functions
 
diff --git a/django_expanded_test_cases/test_cases/base_test_case.py b/django_expanded_test_cases/test_cases/base_test_case.py
index 49ac925..d04c712 100644
--- a/django_expanded_test_cases/test_cases/base_test_case.py
+++ b/django_expanded_test_cases/test_cases/base_test_case.py
@@ -14,31 +14,81 @@ class BaseTestCase(TestCase, CoreTestCaseMixin):
     """Generalized testing functionality. Builds upon Django's default TestCase class."""
 
     @classmethod
-    def setUpClass(cls, debug_print=None):
-        # Run parent setup logic.
-        super().setUpClass()
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation."""
+        print('BaseTestCase setUpClass()')
 
-        # Also call CoreMixin setup logic.
-        cls.set_up_class(debug_print=debug_print)
+        # Call parent logic.
+        return_val = super().setUpClass()
+        CoreTestCaseMixin.setUpClass(*args, debug_print=debug_print, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     @classmethod
-    def setUpTestData(cls):
-        """"""
-        # Initialize default data models.
-        cls.set_up_test_data()
+    def setUpTestData(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup."""
+        print('BaseTestCase setUpTestData()')
+
+        # Call parent logic.
+        return_val = super().setUpTestData()
+        CoreTestCaseMixin.setUpTestData(*args, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution."""
+        print('BaseTestCase setUp()')
 
-    def setUp(self):
-        # Run parent setup logic.
-        super().setUp()
+        # Call parent logic.
+        return_val = super().setUp()
+        CoreTestCaseMixin.setUp(self, *args, **kwargs)
 
         self._error_displayed = False
 
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
     def subTest(self, *args, **kwargs):
-        # Call CoreMixin logic.
-        self.sub_test()
+        """Test logic setup run every time we enter a subtest."""
+        print('BaseTestCase subTest()')
+
+        # Call parent logic.
+        return_val = super().subTest()
+        CoreTestCaseMixin.subTest(self, *args, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    @classmethod
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up."""
+        print('BaseTestCase tearDownClass()')
+
+        # Call parent logic.
+        return_val = super().tearDownClass()
+        CoreTestCaseMixin.tearDownClass(*args, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def tearDown(self, *args, **kwargs):
+        """Test logic setup run at the end of function/method execution, as part of termination/clean up."""
+        print('BaseTestCase tearDown()')
+
+        # Call parent logic.
+        return_val = super().tearDown()
+        CoreTestCaseMixin.tearDown(self, *args, **kwargs)
 
-        # Run parent logic.
-        return super().subTest(*args, **kwargs)
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     def _handle_test_error(self, err):
         """
diff --git a/django_expanded_test_cases/test_cases/channels_live_server_test_case.py b/django_expanded_test_cases/test_cases/channels_live_server_test_case.py
index 5dba371..fd2ded7 100644
--- a/django_expanded_test_cases/test_cases/channels_live_server_test_case.py
+++ b/django_expanded_test_cases/test_cases/channels_live_server_test_case.py
@@ -18,44 +18,75 @@ class ChannelsLiveServerTestCase(DjangoChannelsLiveServerTestCase, LiveServerMix
     """Uses DjangoChannels package to test functionality through selenium. Simulates web browser navigation."""
 
     @classmethod
-    def setUpClass(cls, debug_print=None):
-        # Run parent setup logic.
-        super().setUpClass()
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation."""
 
-        # Also call Mixin setup logic.
-        cls.set_up_class(debug_print=debug_print)
+        # Call parent logic.
+        return_val = super().setUpClass()
+        LiveServerMixin.setUpClass(*args, debug_print=debug_print, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     @classmethod
-    def setUpTestData(cls):
-        # Run parent setup logic.
-        super().setUpTestData()
+    def setUpTestData(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup."""
+
+        # Call parent logic.
+        return_val = super().setUpTestData()
+        LiveServerMixin.setUpTestData(*args, **kwargs)
 
-        # Initialize default data models.
-        cls.set_up_test_data()
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
-    def setUp(self):
-        # Run parent setup logic.
-        super().setUp()
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution."""
 
-        # Also call Mixin setup logic.
-        self.set_up()
+        # Call parent logic.
+        return_val = super().setUp()
+        LiveServerMixin.setUp(self, *args, **kwargs)
 
         self._error_displayed = False
 
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
     def subTest(self, *args, **kwargs):
-        # Call CoreMixin logic.
-        self.sub_test()
+        """Test logic setup run every time we enter a subtest."""
+
+        # Call parent logic.
+        return_val = super().subTest()
+        LiveServerMixin.subTest(self, *args, **kwargs)
 
-        # Run parent logic.
-        return super().subTest(*args, **kwargs)
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     @classmethod
-    def tearDownClass(cls):
-        # Call Mixin setup logic.
-        cls.tear_down_class()
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDownClass()
+        LiveServerMixin.tearDownClass(*args, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def tearDown(self, *args, **kwargs):
+        """Test logic setup run at the end of function/method execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDown()
+        LiveServerMixin.tearDown(self, *args, **kwargs)
 
-        # Call parent teardown logic.
-        super().tearDownClass()
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
 
 # Define acceptable imports on file.
diff --git a/django_expanded_test_cases/test_cases/integration_test_case.py b/django_expanded_test_cases/test_cases/integration_test_case.py
index b4e8dc4..63fae7b 100644
--- a/django_expanded_test_cases/test_cases/integration_test_case.py
+++ b/django_expanded_test_cases/test_cases/integration_test_case.py
@@ -25,10 +25,9 @@ from django_expanded_test_cases.constants import (
     ETC_INCLUDE_RESPONSE_DEBUG_USER_INFO,
     ETC_ALLOW_TITLE_PARTIALS,
     ETC_ALLOW_MESSAGE_PARTIALS,
+    ETC_AUTO_GENERATE_USERS,
     ETC_REQUEST_USER_STRICTNESS,
     ETC_DEFAULT_STANDARD_USER_IDENTIFIER,
-    ETC_RESPONSE_DEBUG_URL_COLOR,
-    ETC_OUTPUT_EMPHASIS_COLOR,
     ETC_OUTPUT_ERROR_COLOR,
     ETC_OUTPUT_RESET_COLOR,
     ETC_OUTPUT_ACTUALS_MATCH_COLOR,
@@ -43,8 +42,10 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
 
     @classmethod
     def setUpClass(cls, *args, debug_print=None, **kwargs):
-        # Run parent setup logic.
-        super().setUpClass(debug_print=None)
+        """Test logic setup run at the start of class creation."""
+
+        # Call parent logic.
+        return_val = super().setUpClass()
 
         # Initialize url variables.
         try:
@@ -53,6 +54,64 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
             # Login url is not defined.
             cls.login_url = None
 
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    @classmethod
+    def setUpTestData(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup."""
+
+        # Call parent logic.
+        return_val = super().setUpTestData()
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution."""
+
+        # Call parent logic.
+        return_val = super().setUp()
+
+        self._error_displayed = False
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def subTest(self, *args, **kwargs):
+        """Test logic setup run every time we enter a subtest."""
+
+        # Call parent logic.
+        return_val = super().subTest()
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    @classmethod
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDownClass()
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def tearDown(self, *args, **kwargs):
+        """Test logic setup run at the end of function/method execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDown()
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
     # region Custom Assertions
 
     def assertResponse(
diff --git a/django_expanded_test_cases/test_cases/live_server_test_case.py b/django_expanded_test_cases/test_cases/live_server_test_case.py
index 020a82f..d4d2deb 100644
--- a/django_expanded_test_cases/test_cases/live_server_test_case.py
+++ b/django_expanded_test_cases/test_cases/live_server_test_case.py
@@ -19,44 +19,75 @@ class LiveServerTestCase(DjangoLiveServerTestCase, LiveServerMixin):
     """Uses Django package to test functionality through selenium. Simulates web browser navigation."""
 
     @classmethod
-    def setUpClass(cls, debug_print=None):
-        # Run parent setup logic.
-        super().setUpClass()
+    def setUpClass(cls, *args, debug_print=None, **kwargs):
+        """Test logic setup run at the start of class creation."""
 
-        # Also call Mixin setup logic.
-        cls.set_up_class(debug_print=debug_print)
+        # Call parent logic.
+        return_val = super().setUpClass()
+        LiveServerMixin.setUpClass(*args, debug_print=debug_print, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     @classmethod
-    def setUpTestData(cls):
-        # Run parent setup logic.
-        super().setUpTestData()
+    def setUpTestData(cls, *args, **kwargs):
+        """Test logic setup run at the start of class creation, specifically for data setup."""
+
+        # Call parent logic.
+        return_val = super().setUpTestData()
+        LiveServerMixin.setUpTestData(*args, **kwargs)
 
-        # Initialize default data models.
-        cls.set_up_test_data()
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
-    def setUp(self):
-        # Run parent setup logic.
-        super().setUp()
+    def setUp(self, *args, **kwargs):
+        """Test logic setup run at the start of function/method execution."""
 
-        # Also call Mixin setup logic.
-        self.set_up()
+        # Call parent logic.
+        return_val = super().setUp()
+        LiveServerMixin.setUp(self, *args, **kwargs)
 
         self._error_displayed = False
 
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
     def subTest(self, *args, **kwargs):
-        # Call CoreMixin logic.
-        self.sub_test()
+        """Test logic setup run every time we enter a subtest."""
+
+        # Call parent logic.
+        return_val = super().subTest()
+        LiveServerMixin.subTest(self, *args, **kwargs)
 
-        # Run parent logic.
-        return super().subTest(*args, **kwargs)
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
     @classmethod
-    def tearDownClass(cls):
-        # Call Mixin setup logic.
-        cls.tear_down_class()
+    def tearDownClass(cls, *args, **kwargs):
+        """Test logic setup run at the end of class execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDownClass()
+        LiveServerMixin.tearDownClass(*args, **kwargs)
+
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
+
+    def tearDown(self, *args, **kwargs):
+        """Test logic setup run at the end of function/method execution, as part of termination/clean up."""
+
+        # Call parent logic.
+        return_val = super().tearDown()
+        LiveServerMixin.tearDown(self, *args, **kwargs)
 
-        # Call parent teardown logic.
-        super().tearDownClass()
+        # Return original python class value, if any.
+        # ETC setup/teardown functions never contain a return value.
+        return return_val
 
 
 # Define acceptable imports on file.
diff --git a/tests/test_cases/test_integration_case.py b/tests/test_cases/test_integration_case.py
index 8178631..d6972b5 100644
--- a/tests/test_cases/test_integration_case.py
+++ b/tests/test_cases/test_integration_case.py
@@ -12,6 +12,7 @@ from django.contrib.auth.models import AnonymousUser, Group, Permission
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
 from django.http import HttpResponse
+from django.test import override_settings
 from django.urls import reverse
 
 # Internal Imports.
@@ -7043,12 +7044,12 @@ class IntegrationClassTest__NoAutoGeneratedUser(IntegrationTestCase):
     """Tests for IntegrationTestCase class, specifically with no auto-generated users."""
 
     @classmethod
-    @patch('django_expanded_test_cases.mixins.core_mixin.ETC_AUTO_GENERATE_USERS', False)
+    @patch('django_expanded_test_cases.mixins.core_mixin.ETC_AUTO_GENERATE_USERS', 'False')
     def setUpClass(cls):
         # Run parent setup logic.
         super().setUpClass()
 
-    @patch('django_expanded_test_cases.mixins.core_mixin.ETC_AUTO_GENERATE_USERS', False)
+    @patch('django_expanded_test_cases.mixins.core_mixin.ETC_AUTO_GENERATE_USERS', 'False')
     def test__class_users(self):
         # Since no users were auto-generated, all of these class attributes should come back as None.
         self.assertFalse(hasattr(self, 'test_superuser'))
-- 
GitLab