Skip to content

Commit 736db2a

Browse files
committed
Tests for line_profiler.cli_utils.add_argument
tests/test_cli.py parser() New fixture (example parser) test_boolean_argument_help_text() New test for the help texts for boolean options generated by `line_profiler.cli_utils.add_argument()` test_boolean_argument_parsing() New test for the parsing of long and short boolean options
1 parent 51511f8 commit 736db2a

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

tests/test_cli.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,117 @@
1+
import re
2+
from argparse import ArgumentParser, HelpFormatter
3+
from contextlib import nullcontext
4+
from functools import partial
5+
from io import StringIO
16
from os.path import join
7+
from shlex import split
28
from sys import executable
9+
import pytest
10+
from line_profiler.cli_utils import add_argument
11+
12+
13+
@pytest.fixture
14+
def parser():
15+
"""
16+
Argument parser with the following boolean flags:
17+
18+
-f, -F, --foo -> foo
19+
-b, --bar -> bar
20+
-B, --baz -> baz
21+
--no-spam -> spam (negated)
22+
--ham -> ham
23+
-c -> c
24+
"""
25+
parser = ArgumentParser(
26+
formatter_class=partial(HelpFormatter,
27+
max_help_position=float('inf'),
28+
width=float('inf')))
29+
# Normal boolean flag (w/2 short forms)
30+
# -> adds 3 actions (long, short, long-negated)
31+
add_argument(parser, '-f', '-F', '--foo', action='store_true')
32+
# Boolean flag w/o parenthetical remark in help text
33+
# -> adds 3 actions (long, short, long-negated)
34+
add_argument(parser, '-b', '--bar', action='store_true', help='Set `bar`')
35+
# Boolean flag w/parenthetical remark in help text
36+
# -> adds 3 actions (long, short, long-negated)
37+
add_argument(parser, '-B', '--baz',
38+
action='store_true', help='Set `baz` (BAZ)')
39+
# Negative boolean flag
40+
# -> adds 1 action (long-negated)
41+
add_argument(parser, '--no-spam',
42+
action='store_false', dest='spam', help='Set `spam` to false')
43+
# Boolean flag w/o short form
44+
# -> adds 2 actions (long, long-negated)
45+
add_argument(parser, '--ham', action='store_true', help='Set `ham`')
46+
# Short-form-only boolean flag
47+
# -> adds 1 action (short)
48+
add_argument(parser, '-e',
49+
action='store_true', dest='eggs', help='Set `eggs`')
50+
yield parser
51+
52+
53+
def test_boolean_argument_help_text(parser):
54+
"""
55+
Test the help texts generated from boolean arguments added by
56+
`line_profiler.cli_utils.add_argument(action=...)`.
57+
"""
58+
assert len(parser._actions) == 14 # One extra option from `--help`
59+
with StringIO() as sio:
60+
parser.print_help(sio)
61+
help_text = sio.getvalue()
62+
matches = partial(re.search, string=help_text, flags=re.MULTILINE)
63+
assert matches(r'^ --foo \[.*\] +'
64+
+ re.escape('(Short forms: -f, -F)')
65+
+ '$')
66+
assert matches(r'^ --bar \[.*\] +'
67+
+ re.escape('Set `bar` (Short form: -b)')
68+
+ '$')
69+
assert matches(r'^ --baz \[.*\] +'
70+
+ re.escape('Set `baz` (BAZ; short form: -B)')
71+
+ '$')
72+
assert matches(r'^ --no-spam \[.*\] +'
73+
+ re.escape('Set `spam` to false')
74+
+ '$')
75+
assert matches(r'^ --ham \[.*\] +'
76+
+ re.escape('Set `ham`')
77+
+ '$')
78+
assert matches(r'^ -e +'
79+
+ re.escape('Set `eggs`')
80+
+ '$')
81+
82+
83+
@pytest.mark.parametrize(
84+
('args', 'foo', 'bar', 'baz', 'spam', 'ham', 'eggs', 'expect_error'),
85+
[('--foo q', *((None,) * 6), True), # Can't parse `q` into boolean
86+
('-fbB' # Test short-flag concatenation
87+
' --ham=', # Empty string -> set to false
88+
True, True, True, None, False, None, False),
89+
('--foo' # No-arg -> set to true
90+
' --bar=0' # Falsy arg -> set to false
91+
' --no-baz' # No-arg (negated flag) -> set to false
92+
' --no-spam=no' # Falsy arg (negated flag) -> set to true
93+
' --ham=on' # Truey arg -> set to true
94+
' -e', # No-arg -> set to true
95+
True, False, False, True, True, True, False)])
96+
def test_boolean_argument_parsing(
97+
parser, capsys, args, foo, bar, baz, spam, ham, eggs, expect_error):
98+
"""
99+
Test the handling of boolean flags.
100+
"""
101+
if expect_error:
102+
ctx = pytest.raises(SystemExit)
103+
match_stderr = 'usage: .* error: argument'
104+
else:
105+
ctx = nullcontext()
106+
match_stderr = '^$'
107+
with ctx:
108+
result = vars(parser.parse_args(split(args)))
109+
stderr = capsys.readouterr().err
110+
assert re.match(match_stderr, stderr, flags=re.DOTALL)
111+
if expect_error:
112+
return
113+
expected = dict(foo=foo, bar=bar, baz=baz, spam=spam, ham=ham, eggs=eggs)
114+
assert result == expected
3115

4116

5117
def test_cli():

0 commit comments

Comments
 (0)