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

Code before:
            (Count, 4),
            (Sum, 16.5),
        ):
            with self.subTest(aggregate=aggregate.__name__):
                books = Book.objects.aggregate(
                    ratings=aggregate("rating", distinct=True)
                )
                self.assertEqual(books["ratings"], expected_result)

    @skipUnlessDBFeature("supports_aggregate_distinct_multiple_argument")
    def test_distinct_on_stringagg(self):
        books = Book.objects.aggregate(
            ratings=StringAgg(Cast(F("rating"), CharField()), Value(","), distinct=True)
        )
        self.assertCountEqual(books["ratings"].split(","), ["3", "4", "4.5", "5"])

    @skipIfDBFeature("supports_aggregate_distinct_multiple_argument")
    def test_raises_error_on_multiple_argument_distinct(self):
        message = (
            "StringAgg does not support distinct with multiple expressions on this "
            "database backend."
        )
        with self.assertRaisesMessage(NotSupportedError, message):
            Book.objects.aggregate(
                ratings=StringAgg(
                    Cast(F("rating"), CharField()),
                    Value(","),
                    distinct=True,
                )
            )

    def test_non_grouped_annotation_not_in_group_by(self):
        """
        An annotation not included in values() before an aggregate should be
        excluded from the group by clause.
        """
        qs = (
            Book.objects.annotate(xprice=F("price"))
            .filter(rating=4.0)
            .values("rating")
            .annotate(count=Count("publisher_id", distinct=True))
            .values("count", "rating")
            .order_by("count")
        )
        self.assertEqual(list(qs), [{"rating": 4.0, "count": 2}])

    def test_grouped_annotation_in_group_by(self):
        """
        An annotation included in values() before an aggregate should be
        included in the group by clause.
        """

Review comment (suggestion):
Simon's prior feedback for you was to avoid asserting over the exact stringified values, but once I realized that we _don't_ want this test to run on all databases (what about other databases besides SQLite where supports_aggregate_distinct_multiple_argument is also False, but the default delimiter trick may not work), I realized we were only testing a SQLite specific case.

Given that, I shuffled this test location and made it as parallel as possible to the prior one.

Code after:
            (Avg, 4.125),
            (Count, 4),
            (Sum, 16.5),
        ):
            with self.subTest(aggregate=aggregate.__name__):
                books = Book.objects.aggregate(
                    ratings=aggregate("rating", distinct=True)
                )
                self.assertEqual(books["ratings"], expected_result)

    @skipUnlessDBFeature("supports_aggregate_distinct_multiple_argument")
    def test_distinct_on_stringagg(self):
        books = Book.objects.aggregate(
            ratings=StringAgg(Cast(F("rating"), CharField()), Value(","), distinct=True)
        )
        self.assertCountEqual(books["ratings"].split(","), ["3", "4", "4.5", "5"])

    @skipUnless(connection.vendor == "sqlite", "Special default case for SQLite.")
    def test_distinct_on_stringagg_sqlite_special_case(self):
        """
        Value(",") is the only delimiter usable on SQLite with distinct=True.
        """
        books = Book.objects.aggregate(
            ratings=StringAgg(Cast(F("rating"), CharField()), Value(","), distinct=True)
        )
        self.assertCountEqual(books["ratings"].split(","), ["3.0", "4.0", "4.5", "5.0"])

    @skipIfDBFeature("supports_aggregate_distinct_multiple_argument")
    def test_raises_error_on_multiple_argument_distinct(self):
        message = (
            "StringAgg does not support distinct with multiple expressions on this "
            "database backend."
        )
        with self.assertRaisesMessage(NotSupportedError, message):
            Book.objects.aggregate(
                ratings=StringAgg(
                    Cast(F("rating"), CharField()),
                    Value(";"),
                    distinct=True,
                )
            )

    def test_non_grouped_annotation_not_in_group_by(self):
        """
        An annotation not included in values() before an aggregate should be
        excluded from the group by clause.
        """
        qs = (
            Book.objects.annotate(xprice=F("price"))
            .filter(rating=4.0)
            .values("rating")