Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit acf749e

Browse files
[GQL] Add filters to the testResults field on the Repository (#824)
1 parent b5540ad commit acf749e

File tree

14 files changed

+277
-74
lines changed

14 files changed

+277
-74
lines changed

graphql_api/tests/test_repository.py

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from django.test import TransactionTestCase, override_settings
55
from freezegun import freeze_time
6+
from shared.django_apps.reports.tests.factories import FlakeFactory
67

78
from codecov_auth.tests.factories import OwnerFactory
89
from core.tests.factories import (
@@ -918,6 +919,105 @@ def test_branch_filter_on_test_results(self) -> None:
918919
)
919920
assert res["testResults"] == {"edges": [{"node": {"name": test.name}}]}
920921

922+
def test_flaky_filter_on_test_results(self) -> None:
923+
repo = RepositoryFactory(author=self.owner, active=True, private=True)
924+
test = TestFactory(repository=repo)
925+
test2 = TestFactory(repository=repo)
926+
_ = FlakeFactory(test=test2, repository=repo, end_date=None)
927+
_ = DailyTestRollupFactory(
928+
test=test,
929+
created_at=datetime.datetime.now(),
930+
repoid=repo.repoid,
931+
branch="main",
932+
)
933+
_ = DailyTestRollupFactory(
934+
test=test2,
935+
created_at=datetime.datetime.now(),
936+
repoid=repo.repoid,
937+
branch="feature",
938+
)
939+
res = self.fetch_repository(
940+
repo.name,
941+
"""testResults(filters: { parameter: FLAKY_TESTS }) { edges { node { name } } }""",
942+
)
943+
assert res["testResults"] == {"edges": [{"node": {"name": test2.name}}]}
944+
945+
def test_failed_filter_on_test_results(self) -> None:
946+
repo = RepositoryFactory(author=self.owner, active=True, private=True)
947+
test = TestFactory(repository=repo)
948+
test2 = TestFactory(repository=repo)
949+
_ = DailyTestRollupFactory(
950+
test=test,
951+
created_at=datetime.datetime.now(),
952+
repoid=repo.repoid,
953+
branch="main",
954+
fail_count=0,
955+
)
956+
_ = DailyTestRollupFactory(
957+
test=test2,
958+
created_at=datetime.datetime.now(),
959+
repoid=repo.repoid,
960+
branch="feature",
961+
fail_count=1000,
962+
)
963+
res = self.fetch_repository(
964+
repo.name,
965+
"""testResults(filters: { parameter: FAILED_TESTS }) { edges { node { name } } }""",
966+
)
967+
assert res["testResults"] == {"edges": [{"node": {"name": test2.name}}]}
968+
969+
def test_skipped_filter_on_test_results(self) -> None:
970+
repo = RepositoryFactory(author=self.owner, active=True, private=True)
971+
test = TestFactory(repository=repo)
972+
test2 = TestFactory(repository=repo)
973+
_ = DailyTestRollupFactory(
974+
test=test,
975+
created_at=datetime.datetime.now(),
976+
repoid=repo.repoid,
977+
branch="main",
978+
skip_count=10,
979+
pass_count=10,
980+
fail_count=10,
981+
)
982+
_ = DailyTestRollupFactory(
983+
test=test2,
984+
created_at=datetime.datetime.now(),
985+
repoid=repo.repoid,
986+
branch="feature",
987+
skip_count=1000,
988+
pass_count=0,
989+
fail_count=0,
990+
)
991+
res = self.fetch_repository(
992+
repo.name,
993+
"""testResults(filters: { parameter: SKIPPED_TESTS }) { edges { node { name } } }""",
994+
)
995+
assert res["testResults"] == {"edges": [{"node": {"name": test2.name}}]}
996+
997+
def test_slowest_filter_on_test_results(self) -> None:
998+
repo = RepositoryFactory(author=self.owner, active=True, private=True)
999+
test = TestFactory(repository=repo)
1000+
test2 = TestFactory(repository=repo)
1001+
_ = DailyTestRollupFactory(
1002+
test=test,
1003+
created_at=datetime.datetime.now(),
1004+
repoid=repo.repoid,
1005+
branch="main",
1006+
avg_duration_seconds=0.1,
1007+
)
1008+
_ = DailyTestRollupFactory(
1009+
test=test2,
1010+
created_at=datetime.datetime.now(),
1011+
repoid=repo.repoid,
1012+
branch="main",
1013+
avg_duration_seconds=20.0,
1014+
)
1015+
res = self.fetch_repository(
1016+
repo.name,
1017+
"""testResults(filters: { parameter: SLOWEST_TESTS }) { edges { node { name } } }""",
1018+
)
1019+
assert res["testResults"] == {"edges": [{"node": {"name": test2.name}}]}
1020+
9211021
def test_commits_failed_ordering_on_test_results(self) -> None:
9221022
repo = RepositoryFactory(author=self.owner, active=True, private=True)
9231023
test = TestFactory(repository=repo)
@@ -1294,11 +1394,11 @@ def test_test_results_aggregates(self) -> None:
12941394
)
12951395
res = self.fetch_repository(
12961396
repo.name,
1297-
"""testResultsHeaders { totalRunTime, slowestTestsRunTime, totalFails, totalSkips }""",
1397+
"""testResultsAggregates { totalRunTime, slowestTestsRunTime, totalFails, totalSkips }""",
12981398
)
1299-
assert res["testResultsHeaders"] == {
1300-
"totalRunTime": 5940.0,
1301-
"slowestTestsRunTime": 850.0,
1399+
assert res["testResultsAggregates"] == {
1400+
"totalRunTime": 5900.0,
1401+
"slowestTestsRunTime": 580.0,
13021402
"totalFails": 20,
13031403
"totalSkips": 10,
13041404
}

graphql_api/tests/test_test_results_headers.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def test_fetch_test_result_total_runtime(self) -> None:
3636
owner(username: "%s") {
3737
repository(name: "%s") {
3838
... on Repository {
39-
testResultsHeaders {
39+
testResultsAggregates {
4040
totalRunTime
4141
}
4242
}
@@ -49,7 +49,8 @@ def test_fetch_test_result_total_runtime(self) -> None:
4949

5050
assert "errors" not in result
5151
assert (
52-
result["owner"]["repository"]["testResultsHeaders"]["totalRunTime"] == 435.0
52+
result["owner"]["repository"]["testResultsAggregates"]["totalRunTime"]
53+
== 435.0
5354
)
5455

5556
def test_fetch_test_result_slowest_tests_runtime(self) -> None:
@@ -58,7 +59,7 @@ def test_fetch_test_result_slowest_tests_runtime(self) -> None:
5859
owner(username: "%s") {
5960
repository(name: "%s") {
6061
... on Repository {
61-
testResultsHeaders {
62+
testResultsAggregates {
6263
slowestTestsRunTime
6364
}
6465
}
@@ -71,7 +72,9 @@ def test_fetch_test_result_slowest_tests_runtime(self) -> None:
7172

7273
assert "errors" not in result
7374
assert (
74-
result["owner"]["repository"]["testResultsHeaders"]["slowestTestsRunTime"]
75+
result["owner"]["repository"]["testResultsAggregates"][
76+
"slowestTestsRunTime"
77+
]
7578
== 29.0
7679
)
7780

@@ -81,7 +84,7 @@ def test_fetch_test_result_failed_tests(self) -> None:
8184
owner(username: "%s") {
8285
repository(name: "%s") {
8386
... on Repository {
84-
testResultsHeaders {
87+
testResultsAggregates {
8588
totalFails
8689
}
8790
}
@@ -93,15 +96,17 @@ def test_fetch_test_result_failed_tests(self) -> None:
9396
result = self.gql_request(query, owner=self.owner)
9497

9598
assert "errors" not in result
96-
assert result["owner"]["repository"]["testResultsHeaders"]["totalFails"] == 29
99+
assert (
100+
result["owner"]["repository"]["testResultsAggregates"]["totalFails"] == 29
101+
)
97102

98103
def test_fetch_test_result_skipped_tests(self) -> None:
99104
query = """
100105
query {
101106
owner(username: "%s") {
102107
repository(name: "%s") {
103108
... on Repository {
104-
testResultsHeaders {
109+
testResultsAggregates {
105110
totalSkips
106111
}
107112
}
@@ -113,4 +118,6 @@ def test_fetch_test_result_skipped_tests(self) -> None:
113118
result = self.gql_request(query, owner=self.owner)
114119

115120
assert "errors" not in result
116-
assert result["owner"]["repository"]["testResultsHeaders"]["totalSkips"] == 29
121+
assert (
122+
result["owner"]["repository"]["testResultsAggregates"]["totalSkips"] == 29
123+
)

graphql_api/types/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@
121121
account,
122122
okta_config,
123123
test_results,
124-
test_results_aggregates,
125124
flake_aggregates,
125+
test_results_aggregates,
126126
]
127127

128128
bindables = [

graphql_api/types/enums/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
PullRequestState,
1414
RepositoryOrdering,
1515
SyncProvider,
16+
TestResultsFilterParameter,
1617
TestResultsOrderingParameter,
1718
TypeProjectOnboarding,
1819
UploadErrorEnum,
@@ -35,6 +36,7 @@
3536
"PullRequestState",
3637
"RepositoryOrdering",
3738
"SyncProvider",
39+
"TestResultsFilterParameter",
3840
"TestResultsOrderingParameter",
3941
"TypeProjectOnboarding",
4042
"UploadErrorEnum",

graphql_api/types/enums/enum_types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
PullRequestState,
2323
RepositoryOrdering,
2424
SyncProvider,
25+
TestResultsFilterParameter,
2526
TestResultsOrderingParameter,
2627
TypeProjectOnboarding,
2728
UploadErrorEnum,
@@ -53,5 +54,6 @@
5354
EnumType("YamlStates", YamlStates),
5455
EnumType("BundleLoadTypes", BundleLoadTypes),
5556
EnumType("TestResultsOrderingParameter", TestResultsOrderingParameter),
57+
EnumType("TestResultsFilterParameter", TestResultsFilterParameter),
5658
EnumType("AssetOrdering", AssetOrdering),
5759
]

graphql_api/types/enums/enums.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class OrderingParameter(enum.Enum):
1313
LINES = "lines"
1414

1515

16+
class TestResultsFilterParameter(enum.Enum):
17+
FLAKY_TESTS = "flaky_tests"
18+
FAILED_TESTS = "failed_tests"
19+
SLOWEST_TESTS = "slowest_tests"
20+
SKIPPED_TESTS = "skipped_tests"
21+
22+
1623
class TestResultsOrderingParameter(enum.Enum):
1724
LAST_DURATION = "last_duration"
1825
AVG_DURATION = "avg_duration"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
enum TestResultsFilterParameter {
2+
FLAKY_TESTS,
3+
FAILED_TESTS,
4+
SLOWEST_TESTS,
5+
SKIPPED_TESTS
6+
}
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
from typing import TypedDict
2+
13
from ariadne import ObjectType
4+
from graphql import GraphQLResolveInfo
25

36
flake_aggregates_bindable = ObjectType("FlakeAggregates")
47

58

9+
class FlakeAggregate(TypedDict):
10+
flake_count: int
11+
flake_rate: float
12+
13+
614
@flake_aggregates_bindable.field("flakeCount")
7-
def resolve_name(obj, _) -> int:
15+
def resolve_flake_count(obj: FlakeAggregate, _: GraphQLResolveInfo) -> int:
816
return obj["flake_count"]
917

1018

1119
@flake_aggregates_bindable.field("flakeRate")
12-
def resolve_updated_at(obj, _) -> float:
20+
def resolve_flake_rate(obj: FlakeAggregate, _: GraphQLResolveInfo) -> float:
1321
return obj["flake_rate"]

graphql_api/types/inputs/test_results_filters.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
input TestResultsFilters {
22
branch: String
3+
parameter: TestResultsFilterParameter
34
}
45

56
input TestResultsOrdering {

graphql_api/types/repository/repository.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ type Repository {
8686

8787
"CoverageAnalytics are fields related to Codecov's Coverage product offering"
8888
coverageAnalytics: CoverageAnalytics
89-
testResultsHeaders: TestResultsAggregates
89+
testResultsAggregates: TestResultsAggregates
9090
flakeAggregates: FlakeAggregates
9191
}
9292

0 commit comments

Comments
 (0)