From bf2de21d92433ea9b9b68012ff1b230519fcedeb Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 28 Apr 2025 12:50:55 +0200 Subject: [PATCH 1/5] first pass, intialize the method for failure rate: --- api/public/v2/test_results/serializers.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/api/public/v2/test_results/serializers.py b/api/public/v2/test_results/serializers.py index 161368567c..6b128b553d 100644 --- a/api/public/v2/test_results/serializers.py +++ b/api/public/v2/test_results/serializers.py @@ -13,15 +13,23 @@ 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): + test_instances = TestInstance.objects.filter(test=obj.test) + total_runs = test_instances.count() + if total_runs == 0: + return 0.0 + + fail_count = test_instances.filter(outcome=TestInstance.Outcome.FAILURE.value).count() + + return fail_count / total_runs + class Meta: model = TestInstance read_only_fields = ( From 40960225c41c41aa143f42b733bfdf8d3e123a14 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 28 Apr 2025 12:53:08 +0200 Subject: [PATCH 2/5] linting --- api/public/v2/test_results/serializers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/public/v2/test_results/serializers.py b/api/public/v2/test_results/serializers.py index 6b128b553d..f0a28a92ef 100644 --- a/api/public/v2/test_results/serializers.py +++ b/api/public/v2/test_results/serializers.py @@ -25,9 +25,7 @@ def get_failure_rate(self, obj): total_runs = test_instances.count() if total_runs == 0: return 0.0 - fail_count = test_instances.filter(outcome=TestInstance.Outcome.FAILURE.value).count() - return fail_count / total_runs class Meta: From da2bd3e1b21c4e07b6e4904adb15c677863575c8 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 28 Apr 2025 12:56:57 +0200 Subject: [PATCH 3/5] format doc --- api/public/v2/test_results/serializers.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/api/public/v2/test_results/serializers.py b/api/public/v2/test_results/serializers.py index f0a28a92ef..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 @@ -21,12 +22,24 @@ class TestInstanceSerializer(serializers.ModelSerializer): ) def get_failure_rate(self, obj): - test_instances = TestInstance.objects.filter(test=obj.test) - total_runs = test_instances.count() + """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 - fail_count = test_instances.filter(outcome=TestInstance.Outcome.FAILURE.value).count() - return fail_count / total_runs + + return stats["failures"] / total_runs class Meta: model = TestInstance From 4e918304f68af12cd1bcd2a1f2e3fc76aacf9cdb Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 28 Apr 2025 13:28:25 +0200 Subject: [PATCH 4/5] try this --- api/public/v2/tests/test_test_results_view.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/public/v2/tests/test_test_results_view.py b/api/public/v2/tests/test_test_results_view.py index aec5bcc6a7..6ed5df4199 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": 0.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": 0.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": 0.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": 0.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": 0.0, } From de2a6e73ade82ebf792bff6da3ddcde9aaab95c8 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 28 Apr 2025 13:36:14 +0200 Subject: [PATCH 5/5] fix failure rate percentage --- api/public/v2/tests/test_test_results_view.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/public/v2/tests/test_test_results_view.py b/api/public/v2/tests/test_test_results_view.py index 6ed5df4199..b05a173917 100644 --- a/api/public/v2/tests/test_test_results_view.py +++ b/api/public/v2/tests/test_test_results_view.py @@ -53,7 +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": 0.0, + "failure_rate": 1.0, }, { "id": self.test_instances[1].id, @@ -65,7 +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": 0.0, + "failure_rate": 1.0, }, ], "total_pages": 1, @@ -97,7 +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": 0.0, + "failure_rate": 1.0, }, ], "total_pages": 1, @@ -128,7 +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": 0.0, + "failure_rate": 1.0, } @patch("api.shared.permissions.RepositoryArtifactPermissions.has_permission") @@ -230,5 +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": 0.0, + "failure_rate": 1.0, }