Repository: django/django
File: tests/foreign_object/tests.py (Python)

Code before:
        self.assertIn("reverse_path_infos", foreign_object_restored.__dict__)


@isolate_apps("foreign_object")
@skipUnlessDBFeature("supports_table_check_constraints")
class ForeignObjectConstraintTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        class CustomerTab(models.Model):
            customer_id = models.IntegerField()
            customer = models.ForeignObject(
                "Customer",
                from_fields=["customer_id"],
                to_fields=["id"],
                on_delete=models.CASCADE,
            )

            class Meta:
                constraints = [
                    models.CheckConstraint(
                        condition=Q(customer__lt=1000),
                        name="customer_id_limit",
                    ),
                ]

        cls.CustomerTab = CustomerTab

    def test_validate_constraints_with_foreign_object(self):
        customer_tab = self.CustomerTab(customer_id=1500)
        with self.assertRaisesMessage(ValidationError, "customer_id_limit"):
            customer_tab.validate_constraints()

    def test_validate_constraints_success_case_single_query(self):
        customer_tab = self.CustomerTab(customer_id=500)
        with CaptureQueriesContext(connection) as ctx:
            customer_tab.validate_constraints()
        select_queries = [
            query["sql"]
            for query in ctx.captured_queries
            if "select" in query["sql"].lower()
        ]
        self.assertEqual(len(select_queries), 1)

    def test_validate_constraints_excluding_foreign_object(self):
        customer_tab = self.CustomerTab(customer_id=150)
        customer_tab.validate_constraints(exclude={"customer"})

    def test_validate_constraints_excluding_foreign_object_member(self):
        customer_tab = self.CustomerTab(customer_id=150)

Review comment (refactor):
I haven't fully understood why we need to move this class to inside the `setUpClass`  forcing us to do `self.CustomerTab` in the tests. Could you help me understand please?

Code after:
        self.assertIn("reverse_path_infos", foreign_object_restored.__dict__)


class ForeignObjectModelValidationTests(TestCase):
    @skipUnlessDBFeature("supports_table_check_constraints")
    def test_validate_constraints_with_foreign_object(self):
        customer_tab = CustomerTab(customer_id=1500)
        with self.assertRaisesMessage(ValidationError, "customer_id_limit"):
            customer_tab.validate_constraints()

    @skipUnlessDBFeature("supports_table_check_constraints")
    def test_validate_constraints_success_case_single_query(self):
        customer_tab = CustomerTab(customer_id=500)
        with CaptureQueriesContext(connection) as ctx:
            customer_tab.validate_constraints()
        select_queries = [
            query["sql"]
            for query in ctx.captured_queries
            if "select" in query["sql"].lower()
        ]
        self.assertEqual(len(select_queries), 1)

    @skipUnlessDBFeature("supports_table_check_constraints")
    def test_validate_constraints_excluding_foreign_object(self):
        customer_tab = CustomerTab(customer_id=150)
        customer_tab.validate_constraints(exclude={"customer"})

    @skipUnlessDBFeature("supports_table_check_constraints")
    def test_validate_constraints_excluding_foreign_object_member(self):
        customer_tab = CustomerTab(customer_id=150)
        customer_tab.validate_constraints(exclude={"customer_id"})