Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions graphql_api/tests/test_test_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1134,3 +1134,48 @@ def test_flake_aggregates_7_days(self) -> None:
"flakeCountPercentChange": -50.0,
"flakeRatePercentChange": -43.75,
}

def test_test_suites(self) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add 2 more tests where there's no filter? To hit the elses

repo = RepositoryFactory(author=self.owner, active=True, private=True)
test = TestFactory(repository=repo, testsuite="hello_world")
test2 = TestFactory(repository=repo, testsuite="goodbye_world")

repo_flag = RepositoryFlagFactory(repository=repo, flag_name="hello_world")

_ = TestFlagBridgeFactory(flag=repo_flag, test=test)
_ = DailyTestRollupFactory(
test=test,
created_at=datetime.datetime.now(),
repoid=repo.repoid,
branch="main",
avg_duration_seconds=0.1,
)
_ = DailyTestRollupFactory(
test=test2,
created_at=datetime.datetime.now(),
repoid=repo.repoid,
branch="main",
avg_duration_seconds=20.0,
)
res = self.fetch_test_analytics(
repo.name,
"""testSuites(term: "hello")""",
)
assert res["testSuites"] == ["hello_world"]

def test_flags(self) -> None:
repo = RepositoryFactory(author=self.owner, active=True, private=True)
test = TestFactory(repository=repo)
test2 = TestFactory(repository=repo)

repo_flag = RepositoryFlagFactory(repository=repo, flag_name="hello_world")
repo_flag2 = RepositoryFlagFactory(repository=repo, flag_name="goodbye_world")

_ = TestFlagBridgeFactory(flag=repo_flag, test=test)
_ = TestFlagBridgeFactory(flag=repo_flag2, test=test2)

res = self.fetch_test_analytics(
repo.name,
"""flags(term: "hello")""",
)
assert res["flags"] == ["hello_world"]
5 changes: 5 additions & 0 deletions graphql_api/types/test_analytics/test_analytics.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ type TestAnalytics {

"Flake aggregates are flake totals across all tests"
flakeAggregates(interval: MeasurementInterval): FlakeAggregates

testSuites(term: String): [String!]!

"Only flag names relevant to Test Analytics"
flags(term: String): [String!]!
}

type TestResultConnection {
Expand Down
16 changes: 16 additions & 0 deletions graphql_api/types/test_analytics/test_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
generate_flake_aggregates,
generate_test_results,
generate_test_results_aggregates,
get_flags,
get_test_suites,
)

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -88,6 +90,20 @@ async def resolve_flake_aggregates(
)


@test_analytics_bindable.field("testSuites")
async def resolve_test_suites(
repository: Repository, info: GraphQLResolveInfo, term: str | None = None, **_
):
return await sync_to_async(get_test_suites)(repository.repoid, term)


@test_analytics_bindable.field("flags")
async def resolve_flags(
repository: Repository, info: GraphQLResolveInfo, term: str | None = None, **_
):
return await sync_to_async(get_flags)(repository.repoid, term)


def convert_interval_to_timedelta(interval: MeasurementInterval | None) -> timedelta:
if interval is None:
return timedelta(days=30)
Expand Down
35 changes: 35 additions & 0 deletions utils/test_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from shared.django_apps.reports.models import (
DailyTestRollup,
Flake,
Test,
TestFlagBridge,
)

Expand Down Expand Up @@ -623,3 +624,37 @@
curr_numbers,
past_numbers,
)


def get_test_suites(repoid: int, term: str | None = None) -> list[str]:
if term:
return list(
Test.objects.filter(repository_id=repoid, testsuite__icontains=term)
.values_list("testsuite", flat=True)
.distinct()
)
else:
return list(

Check warning on line 637 in utils/test_results.py

View check run for this annotation

Codecov Notifications / codecov/patch

utils/test_results.py#L637

Added line #L637 was not covered by tests
Test.objects.filter(repository_id=repoid)
.values_list("testsuite", flat=True)
.distinct()
)


def get_flags(repoid: int, term: str | None = None) -> list[str]:
if term:
return list(
TestFlagBridge.objects.filter(
test__repository_id=repoid, flag__flag_name__icontains=term
)
.select_related("flag")
.values_list("flag__flag_name", flat=True)
.distinct()
)
else:
return list(

Check warning on line 655 in utils/test_results.py

View check run for this annotation

Codecov Notifications / codecov/patch

utils/test_results.py#L655

Added line #L655 was not covered by tests
TestFlagBridge.objects.filter(test__repository_id=repoid)
.select_related("flag")
.values_list("flag__flag_name", flat=True)
.distinct()
)
Loading