Skip to content

Commit 57532b1

Browse files
committed
Add -k to pytest-benchmark compare, just like pytest -k
1 parent 86ae1ed commit 57532b1

4 files changed

Lines changed: 63 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
Changelog
33
=========
44

5+
v5.2.4 (unreleased)
6+
--------------------
7+
8+
* Added ``-k`` filter option to the ``compare`` CLI command, using the same expression syntax as pytest's ``-k`` option.
9+
510
v5.2.3 (2025-11-09)
611
--------------------
712

docs/usage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ The compare ``command`` takes almost all the ``--benchmark`` options, minus the
235235
--csv=FILENAME Save a csv report. If FILENAME contains slashes ('/')
236236
then directories will be created. Default:
237237
'benchmark_<date>_<time>'
238+
-k EXPR Only show benchmarks matching the given expression.
239+
Uses the same syntax as pytest's ``-k`` option
240+
(e.g. ``'foo and not bar'``).
238241

239242
examples:
240243

src/pytest_benchmark/cli.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ def make_parser():
110110
add_histogram_options(compare_command.add_argument, prefix='')
111111
add_glob_or_file(compare_command.add_argument)
112112
add_csv_options(compare_command.add_argument, prefix='')
113+
compare_command.add_argument(
114+
'-k',
115+
metavar='EXPR',
116+
dest='filter_expr',
117+
default=None,
118+
help="Only show benchmarks matching the given expression. Uses the same syntax as pytest's -k option (e.g. 'foo and not bar').",
119+
)
113120

114121
return parser
115122

@@ -159,8 +166,19 @@ def main():
159166
config=Config.fromdictargs({'benchmark_time_unit': args.time_unit}, []),
160167
),
161168
)
169+
benchmarks = storage.load_benchmarks(*args.glob_or_file)
170+
if args.filter_expr:
171+
from _pytest.mark.expression import Expression # noqa: PLC0415
172+
173+
expr = Expression.compile(args.filter_expr)
174+
175+
def _evaluate_expr(benchmark):
176+
name = benchmark.get('fullname') or benchmark.get('name', '')
177+
return expr.evaluate(lambda key: key in name)
178+
179+
benchmarks = filter(_evaluate_expr, benchmarks)
162180
groups = hook.pytest_benchmark_group_stats(
163-
benchmarks=storage.load_benchmarks(*args.glob_or_file),
181+
benchmarks=benchmarks,
164182
group_by=args.group_by,
165183
config=None,
166184
)

tests/test_cli.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def test_help_compare(testdir, args):
9393
' [--columns LABELS] [--name FORMAT]',
9494
' [--time-unit COLUMN]',
9595
' [--histogram [FILENAME-PREFIX]]',
96-
' [--csv [FILENAME]]',
96+
' [--csv [FILENAME]] [-k EXPR]',
9797
' [[]glob_or_file *[]]',
9898
'',
9999
'Compare saved runs.',
@@ -125,6 +125,9 @@ def test_help_compare(testdir, args):
125125
" --csv [FILENAME] Save a csv report. If FILENAME contains slashes ('/')",
126126
' then directories will be created. Default:',
127127
" 'benchmark_*'",
128+
' -k EXPR Only show benchmarks matching the given expression.',
129+
" Uses the same syntax as pytest's -k option (e.g. 'foo",
130+
" and not bar').",
128131
'',
129132
'examples:',
130133
'',
@@ -358,3 +361,35 @@ def func():
358361
)
359362
result = testdir.run('py.test-benchmark', 'compare', '--csv')
360363
result.stderr.fnmatch_lines(['Generated csv: *.csv'])
364+
365+
366+
def test_compare_filter(testdir):
367+
test = testdir.makepyfile("""
368+
import pytest
369+
@pytest.mark.parametrize("arg", ["foo", "bar"])
370+
def test_alpha(benchmark, arg):
371+
benchmark(lambda: None)
372+
def test_beta(benchmark):
373+
benchmark(lambda: None)
374+
""")
375+
result = testdir.runpytest_subprocess('--benchmark-autosave', test)
376+
result.stderr.fnmatch_lines(['Saved benchmark data in: *'])
377+
378+
# Filter to only test_alpha benchmarks
379+
result = testdir.run('py.test-benchmark', 'compare', '-k', 'alpha', '--columns', 'min,max')
380+
result.stdout.fnmatch_lines(['*benchmark: 2 tests*'])
381+
assert 'test_beta' not in result.stdout.str()
382+
383+
# Filter with "not" expression
384+
result = testdir.run('py.test-benchmark', 'compare', '-k', 'not alpha', '--columns', 'min,max')
385+
result.stdout.fnmatch_lines(['*benchmark: 1 tests*'])
386+
assert 'test_alpha' not in result.stdout.str()
387+
388+
# Filter with "and" expression
389+
result = testdir.run('py.test-benchmark', 'compare', '-k', 'alpha and foo', '--columns', 'min,max')
390+
result.stdout.fnmatch_lines(['*benchmark: 1 tests*'])
391+
assert 'bar' not in result.stdout.str()
392+
393+
# No filter shows all
394+
result = testdir.run('py.test-benchmark', 'compare', '--columns', 'min,max')
395+
result.stdout.fnmatch_lines(['*benchmark: 3 tests*'])

0 commit comments

Comments
 (0)