Skip to content
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
6 changes: 5 additions & 1 deletion app/api/api_v1/endpoints/test_run_executions.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def read_test_run_executions(
search_query: Optional[str] = None,
skip: int = 0,
limit: int = 100,
sort_order: str = "asc",
) -> list[schemas.TestRunExecutionWithStats]:
"""Retrieve test runs, including statistics.

Expand All @@ -71,7 +72,9 @@ def read_test_run_executions(
archived: Get archived test runs, when true will return archived
test runs only, when false only non-archived test runs are returned.
skip: Pagination offset.
limit: Max number of records to return.
limit: Max number of records to return. Set to 0 to return all results.
sort_order: Sort order for results. Either "asc" or "desc". Defaults to "asc".
Results are sorted by ID.

Returns:
List of test runs with execution statistics.
Expand All @@ -83,6 +86,7 @@ def read_test_run_executions(
search_query=search_query,
skip=skip,
limit=limit,
sort_order=sort_order,
)


Expand Down
15 changes: 13 additions & 2 deletions app/crud/crud_test_run_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def get_multi(
archived: Optional[bool] = False,
search_query: Optional[str] = None,
order_by: Optional[str] = None,
sort_order: Optional[str] = "asc",
skip: Optional[int] = 0,
limit: Optional[int] = 100,
) -> Sequence[TestRunExecution]:
Expand All @@ -85,11 +86,19 @@ def get_multi(
)

if order_by is None:
query = query.order_by(self.model.id)
# Default to ordering by id with specified sort order
if sort_order == "desc":
query = query.order_by(self.model.id.desc())
else:
query = query.order_by(self.model.id.asc())
else:
query = query.order_by(order_by)

query = query.offset(skip).limit(limit)
query = query.offset(skip)

# If limit is 0, return all results without limit
if limit != 0:
query = query.limit(limit)

return db.scalars(query).all()

Expand All @@ -101,6 +110,7 @@ def get_multi_with_stats(
archived: Optional[bool] = False,
search_query: Optional[str] = None,
order_by: Optional[str] = None,
sort_order: Optional[str] = "asc",
skip: Optional[int] = 0,
limit: Optional[int] = 100,
) -> List[TestRunExecutionWithStats]:
Expand All @@ -110,6 +120,7 @@ def get_multi_with_stats(
archived=archived,
search_query=search_query,
order_by=order_by,
sort_order=sort_order,
skip=skip,
limit=limit,
)
Expand Down
35 changes: 35 additions & 0 deletions app/tests/api/api_v1/test_test_run_executions.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,41 @@ def test_read_multiple_test_run_executions_with_search_query(
assert not any(test_run.get("id") == test_run_execution.id for test_run in content)


def test_read_multiple_test_run_executions_with_limit_zero_returns_all(
client: TestClient, db: Session
) -> None:
"""Test that limit=0 returns all test run executions."""

# Create several test executions to ensure we have more than default limit
test_runs = []
for i in range(5):
test_run = create_random_test_run_execution(db)
test_runs.append(test_run)

# Ensure changes are committed
db.commit()

# Test with limit=0 to get all results
response = client.get(f"{settings.API_V1_STR}/test_run_executions?limit=0")
assert response.status_code == HTTPStatus.OK
content = response.json()
assert isinstance(content, list)

# Verify that all our created test runs are in the response
created_ids = {tr.id for tr in test_runs}
response_ids = {tr["id"] for tr in content}

# All created test runs should be present (and potentially more from other tests)
assert created_ids.issubset(
response_ids
), f"Created IDs {created_ids} not found in response IDs"

# Verify we got more than the default limit (should be at least our 5 created runs)
assert (
len(content) >= 5
), f"Expected at least 5 test runs with limit=0, got {len(content)}"


def test_read_test_run_execution(client: TestClient, db: Session) -> None:
# We generate a random test run for this test.
# To validate that all test cases are returned in the response,
Expand Down
80 changes: 80 additions & 0 deletions app/tests/crud/test_test_run_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,3 +809,83 @@ def test_import_execution_success_without_test_config() -> None:
assert imported_test_run.project_id == project_id
assert imported_test_run.title == test_run_execution_dict.get("title")
assert imported_test_run.operator_id == operator_id


def test_get_test_run_executions_sort_order(db: Session) -> None:
"""Test that sort_order parameter correctly orders test run executions by id."""
project = create_random_project(db, config={})

# Create multiple test run executions
test_runs = []
for i in range(3):
test_run = create_random_test_run_execution(db, project_id=project.id)
test_runs.append(test_run)

# Test ascending order (default)
test_run_executions_asc = crud.test_run_execution.get_multi_with_stats(
db, project_id=project.id, sort_order="asc"
)

# Test descending order
test_run_executions_desc = crud.test_run_execution.get_multi_with_stats(
db, project_id=project.id, sort_order="desc"
)

# Verify we have all test runs
assert len(test_run_executions_asc) >= 3
assert len(test_run_executions_desc) >= 3

# Get the IDs of our created test runs
created_ids = [tr.id for tr in test_runs]

# Filter to only our test runs for verification
asc_our_runs = [tre for tre in test_run_executions_asc if tre.id in created_ids]
desc_our_runs = [tre for tre in test_run_executions_desc if tre.id in created_ids]

# Sort by id for verification
asc_our_runs.sort(key=lambda x: x.id)
desc_our_runs.sort(key=lambda x: x.id, reverse=True)

# Verify ascending order - lowest ID first
assert asc_our_runs[0].id <= asc_our_runs[1].id <= asc_our_runs[2].id

# Verify descending order - highest ID first
assert desc_our_runs[0].id >= desc_our_runs[1].id >= desc_our_runs[2].id

# Verify the orders are actually different (reversed)
asc_ids = [tr.id for tr in asc_our_runs]
desc_ids = [tr.id for tr in desc_our_runs]
assert asc_ids == list(reversed(desc_ids))


def test_get_test_run_executions_limit_zero_returns_all(db: Session) -> None:
"""Test that limit=0 returns all test run executions without applying limit."""
project = create_random_project(db, config={})

# Create several test runs to ensure we have multiple records
test_runs = []
for i in range(5):
test_run = create_random_test_run_execution(db, project_id=project.id)
test_runs.append(test_run)

db.commit()

# Test with default limit (should be limited to 2)
limited_results = crud.test_run_execution.get_multi_with_stats(
db, project_id=project.id, limit=2
)

# Test with limit=0 (should return all for this project)
all_results = crud.test_run_execution.get_multi_with_stats(
db, project_id=project.id, limit=0
)

# Verify that limit=0 returns more results than the limited query
assert len(all_results) > len(limited_results)
assert len(limited_results) == 2 # Verify limited query worked
assert len(all_results) >= 5 # Should have at least our 5 test runs

# Verify all our created test runs are in the unlimited results
created_ids = {tr.id for tr in test_runs}
result_ids = {tr.id for tr in all_results}
assert created_ids.issubset(result_ids)
Loading