diff --git a/api/public/v2/test_results/serializers.py b/api/public/v2/test_results/serializers.py index 161368567c..c9db7996e1 100644 --- a/api/public/v2/test_results/serializers.py +++ b/api/public/v2/test_results/serializers.py @@ -1,3 +1,4 @@ +from django.db.models import Count, Q from rest_framework import serializers from reports.models import TestInstance @@ -13,15 +14,33 @@ class TestInstanceSerializer(serializers.ModelSerializer): outcome = serializers.CharField(label="outcome") branch = serializers.CharField(label="branch name") repoid = serializers.IntegerField(label="repo id") - failure_rate = serializers.FloatField( - source="test.failure_rate", read_only=True, label="failure rate" - ) + failure_rate = serializers.SerializerMethodField(label="failure rate") commits_where_fail = serializers.ListField( source="test.commits_where_fail", read_only=True, label="commits where test failed", ) + def get_failure_rate(self, obj): + """Calculate the failure rate for a test. + The failure rate is calculated as: + number of failed test runs / total number of test runs + Returns: + float: A value between 0.0 and 1.0 representing the failure rate + 0.0 means no failures + 1.0 means all runs failed + """ + stats = TestInstance.objects.filter(test=obj.test).aggregate( + total=Count("id"), + failures=Count("id", filter=Q(outcome=TestInstance.Outcome.FAILURE.value)), + ) + + total_runs = stats["total"] + if total_runs == 0: + return 0.0 + + return stats["failures"] / total_runs + class Meta: model = TestInstance read_only_fields = ( diff --git a/api/public/v2/tests/test_test_results_view.py b/api/public/v2/tests/test_test_results_view.py index aec5bcc6a7..b05a173917 100644 --- a/api/public/v2/tests/test_test_results_view.py +++ b/api/public/v2/tests/test_test_results_view.py @@ -53,6 +53,7 @@ def test_list(self): "outcome": self.test_instances[0].outcome, "branch": self.test_instances[0].branch, "repoid": self.test_instances[0].repoid, + "failure_rate": 1.0, }, { "id": self.test_instances[1].id, @@ -64,6 +65,7 @@ def test_list(self): "outcome": self.test_instances[1].outcome, "branch": self.test_instances[1].branch, "repoid": self.test_instances[1].repoid, + "failure_rate": 1.0, }, ], "total_pages": 1, @@ -95,6 +97,7 @@ def test_list_filters(self): "outcome": self.test_instances[0].outcome, "branch": self.test_instances[0].branch, "repoid": self.test_instances[0].repoid, + "failure_rate": 1.0, }, ], "total_pages": 1, @@ -125,6 +128,7 @@ def test_retrieve(self, get_repo_permissions): "outcome": self.test_instances[0].outcome, "branch": self.test_instances[0].branch, "repoid": self.test_instances[0].repoid, + "failure_rate": 1.0, } @patch("api.shared.permissions.RepositoryArtifactPermissions.has_permission") @@ -226,4 +230,5 @@ def test_result_with_valid_super_token( "outcome": self.test_instances[0].outcome, "branch": self.test_instances[0].branch, "repoid": self.test_instances[0].repoid, + "failure_rate": 1.0, }