Skip to content

Commit fa1e090

Browse files
authored
Merge pull request #30 from jerry-git/cli-command-for-listing-slowest-durations
Introduce slowest-tests cli command
2 parents ca4f4c2 + 6748bbf commit fa1e090

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ However, when there are major changes in the suite compared to what's stored in
4242

4343
The splitting algorithm can be controlled with the `--splitting-algorithm` CLI option and defaults to `duration_based_chunks`. For more information about the different algorithms and their tradeoffs, please see the section below.
4444

45+
### CLI commands
46+
#### slowest-tests
47+
Lists the slowest tests based on the information stored in the test durations file. See `slowest-tests help` for more
48+
information.
49+
4550
## Interactions with other pytest plugins
4651
* [`pytest-random-order`](https://github.com/jbasko/pytest-random-order): ⚠️ The **default settings** of that plugin (setting only `--random-order` to activate it) are **incompatible** with `pytest-split`. Test selection in the groups happens after randomization, potentially causing some tests to be selected in several groups and others not at all. Instead, a global random seed needs to be computed before running the tests (for example using `$RANDOM` from the shell) and that single seed then needs to be used for all groups by setting the `--random-order-seed` option.
4752

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ pre-commit = "^2.13.0"
3636
requires = ["poetry-core>=1.0.0"]
3737
build-backend = "poetry.core.masonry.api"
3838

39+
[tool.poetry.scripts]
40+
slowest-tests = "pytest_split.cli:list_slowest_tests"
41+
3942
[tool.poetry.plugins.pytest11]
4043
pytest-split = "pytest_split.plugin"
4144

src/pytest_split/cli.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import argparse
2+
import json
3+
from typing import TYPE_CHECKING
4+
5+
if TYPE_CHECKING:
6+
from typing import Dict
7+
8+
9+
def list_slowest_tests():
10+
parser = argparse.ArgumentParser()
11+
parser.add_argument(
12+
"--durations-path",
13+
help=(
14+
"Path to the file in which durations are stored, "
15+
"default is .test_durations in the current working directory"
16+
),
17+
default=".test_durations",
18+
type=argparse.FileType(),
19+
)
20+
parser.add_argument(
21+
"-c",
22+
"--count",
23+
help="How many slowest to list",
24+
default=10,
25+
type=int,
26+
)
27+
args = parser.parse_args()
28+
return _list_slowest_tests(json.load(args.durations_path), args.count)
29+
30+
31+
def _list_slowest_tests(durations: "Dict[str, float]", count: int) -> None:
32+
slowest_tests = tuple(sorted(durations.items(), key=lambda item: item[1], reverse=True))[:count]
33+
for test, duration in slowest_tests:
34+
print(f"{duration:.2f} {test}") # noqa: T001

tests/test_cli.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import argparse
2+
import json
3+
import sys
4+
from io import StringIO
5+
from unittest.mock import patch
6+
7+
import pytest
8+
9+
from pytest_split import cli
10+
11+
12+
@pytest.fixture
13+
def durations_file(tmpdir):
14+
durations_path = str(tmpdir.join(".durations"))
15+
durations = {f"test_{i}": float(i) for i in range(1, 11)}
16+
with open(durations_path, "w") as f:
17+
json.dump(durations, f)
18+
with open(durations_path, "r") as f:
19+
yield f
20+
21+
22+
def test_slowest_tests(durations_file):
23+
with patch("pytest_split.cli.argparse.ArgumentParser", autospec=True) as arg_parser, patch(
24+
"sys.stdout", new_callable=StringIO
25+
):
26+
arg_parser().parse_args.return_value = argparse.Namespace(durations_path=durations_file, count=3)
27+
cli.list_slowest_tests()
28+
29+
output = sys.stdout.getvalue()
30+
assert output == "10.00 test_10\n" "9.00 test_9\n" "8.00 test_8\n"

0 commit comments

Comments
 (0)