Skip to content

Commit 1c62075

Browse files
committed
Enabled ruff PT ruleset for pytest best practices
1 parent 72ff51c commit 1c62075

File tree

9 files changed

+50
-58
lines changed

9 files changed

+50
-58
lines changed

plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def app_cmd(self, command: str, echo: Optional[bool] = None) -> cmd2.CommandResu
3939
:param echo: Flag whether the command's output should be echoed to stdout/stderr
4040
:return: A CommandResult object that captures stdout, stderr, and the command's result object
4141
"""
42-
assert isinstance(self, cmd2.Cmd) and isinstance(self, ExternalTestMixin)
42+
assert isinstance(self, cmd2.Cmd)
43+
assert isinstance(self, ExternalTestMixin)
4344
try:
4445
self._in_py = True
4546

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ select = [
199199
"PLE", # Pylint Errors
200200
# "PLR", # Pylint Refactoring suggestions
201201
"PLW", # Pylint Warnings
202-
# "PT", # flake8-pytest-style (warnings about unit test best practices)
202+
"PT", # flake8-pytest-style (warnings about unit test best practices)
203203
# "PTH", # flake8-use-pathlib (force use of pathlib instead of os.path)
204204
"PYI", # flake8-pyi (warnings related to type hint best practices)
205205
# "Q", # flake8-quotes (force double quotes)

tests/test_cmd2.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -622,15 +622,16 @@ def test_passthrough_exception_in_command(base_app):
622622
"""Test raising a PassThroughException in a command"""
623623
import types
624624

625+
expected_err = "Pass me up"
626+
625627
def do_passthrough(self, _):
626-
wrapped_ex = OSError("Pass me up")
628+
wrapped_ex = OSError(expected_err)
627629
raise exceptions.PassThroughException(wrapped_ex=wrapped_ex)
628630

629631
setattr(base_app, 'do_passthrough', types.MethodType(do_passthrough, base_app))
630632

631-
with pytest.raises(OSError) as excinfo:
633+
with pytest.raises(OSError, match=expected_err):
632634
base_app.onecmd_plus_hooks('passthrough')
633-
assert 'Pass me up' in str(excinfo.value)
634635

635636

636637
def test_output_redirection(base_app):
@@ -1033,7 +1034,7 @@ def test_cmdloop_without_rawinput():
10331034

10341035
expected = app.intro + '\n'
10351036

1036-
with pytest.raises(OSError):
1037+
with pytest.raises(OSError): # noqa: PT011
10371038
app.cmdloop()
10381039
out = app.stdout.getvalue()
10391040
assert out == expected
@@ -1794,11 +1795,11 @@ def test_commandresult_falsy(commandresult_app):
17941795

17951796
def test_is_text_file_bad_input(base_app):
17961797
# Test with a non-existent file
1797-
with pytest.raises(OSError):
1798+
with pytest.raises(FileNotFoundError):
17981799
utils.is_text_file('does_not_exist.txt')
17991800

18001801
# Test with a directory
1801-
with pytest.raises(OSError):
1802+
with pytest.raises(IsADirectoryError):
18021803
utils.is_text_file('.')
18031804

18041805

tests/test_history.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ def test_history_class_span(hist):
225225
assert span[3].statement.raw == 'third'
226226

227227
value_errors = ['fred', 'fred:joe', '2', '-2', 'a..b', '2 ..', '1 : 3', '1:0', '0:3']
228+
expected_err = "History indices must be positive or negative integers, and may not be zero."
228229
for tryit in value_errors:
229-
with pytest.raises(ValueError):
230+
with pytest.raises(ValueError, match=expected_err):
230231
hist.span(tryit)
231232

232233

@@ -275,8 +276,9 @@ def test_persisted_history_span(persisted_hist):
275276
assert span[5].statement.raw == 'fifth'
276277

277278
value_errors = ['fred', 'fred:joe', '2', '-2', 'a..b', '2 ..', '1 : 3', '1:0', '0:3']
279+
expected_err = "History indices must be positive or negative integers, and may not be zero."
278280
for tryit in value_errors:
279-
with pytest.raises(ValueError):
281+
with pytest.raises(ValueError, match=expected_err):
280282
persisted_hist.span(tryit)
281283

282284

@@ -358,7 +360,8 @@ def test_history_from_json(hist):
358360
invalid_ver_json = hist.to_json()
359361
History._history_version = backed_up_ver
360362

361-
with pytest.raises(ValueError):
363+
expected_err = "Unsupported history file version: BAD_VERSION. This application uses version 1.0.0."
364+
with pytest.raises(ValueError, match=expected_err):
362365
hist.from_json(invalid_ver_json)
363366

364367

@@ -652,7 +655,8 @@ def test_history_with_span_index_error(base_app):
652655
run_cmd(base_app, 'help')
653656
run_cmd(base_app, 'help history')
654657
run_cmd(base_app, '!ls -hal :')
655-
with pytest.raises(ValueError):
658+
expected_err = "History indices must be positive or negative integers, and may not be zero."
659+
with pytest.raises(ValueError, match=expected_err):
656660
base_app.onecmd('history "hal :"')
657661

658662

tests/test_plugin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,9 +949,9 @@ def test_cmdfinalization_hook_passthrough_exception():
949949
app = PluggedApp()
950950
app.register_cmdfinalization_hook(app.cmdfinalization_hook_passthrough_exception)
951951

952-
with pytest.raises(OSError) as excinfo:
952+
expected_err = "Pass me up"
953+
with pytest.raises(OSError, match=expected_err):
953954
app.onecmd_plus_hooks('say hello')
954-
assert 'Pass me up' in str(excinfo.value)
955955
assert app.called_cmdfinalization == 1
956956

957957

tests/test_table_creator.py

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,16 @@
2727

2828
def test_column_creation():
2929
# Width less than 1
30-
with pytest.raises(ValueError) as excinfo:
30+
with pytest.raises(ValueError, match="Column width cannot be less than 1"):
3131
Column("Column 1", width=0)
32-
assert "Column width cannot be less than 1" in str(excinfo.value)
3332

3433
# Width specified
3534
c = Column("header", width=20)
3635
assert c.width == 20
3736

3837
# max_data_lines less than 1
39-
with pytest.raises(ValueError) as excinfo:
38+
with pytest.raises(ValueError, match="Max data lines cannot be less than 1"):
4039
Column("Column 1", max_data_lines=0)
41-
assert "Max data lines cannot be less than 1" in str(excinfo.value)
4240

4341
# No width specified, blank label
4442
c = Column("")
@@ -311,15 +309,13 @@ def test_generate_row_exceptions():
311309
# Unprintable characters
312310
for arg in ['fill_char', 'pre_line', 'inter_cell', 'post_line']:
313311
kwargs = {arg: '\n'}
314-
with pytest.raises(ValueError) as excinfo:
312+
with pytest.raises(ValueError, match=f"{arg} contains an unprintable character"):
315313
tc.generate_row(row_data=row_data, is_header=False, **kwargs)
316-
assert "{} contains an unprintable character".format(arg) in str(excinfo.value)
317314

318315
# Data with too many columns
319316
row_data = ['Data 1', 'Extra Column']
320-
with pytest.raises(ValueError) as excinfo:
317+
with pytest.raises(ValueError, match="Length of row_data must match length of cols"):
321318
tc.generate_row(row_data=row_data, is_header=False)
322-
assert "Length of row_data must match length of cols" in str(excinfo.value)
323319

324320

325321
def test_tabs():
@@ -332,9 +328,8 @@ def test_tabs():
332328
row = tc.generate_row(row_data, is_header=True, fill_char='\t', pre_line='\t', inter_cell='\t', post_line='\t')
333329
assert row == ' Col 1 Col 2 '
334330

335-
with pytest.raises(ValueError) as excinfo:
331+
with pytest.raises(ValueError, match="Tab width cannot be less than 1" ):
336332
TableCreator([column_1, column_2], tab_width=0)
337-
assert "Tab width cannot be less than 1" in str(excinfo.value)
338333

339334

340335
def test_simple_table_creation():
@@ -439,24 +434,20 @@ def test_simple_table_creation():
439434
)
440435

441436
# Invalid column spacing
442-
with pytest.raises(ValueError) as excinfo:
437+
with pytest.raises(ValueError, match="Column spacing cannot be less than 0"):
443438
SimpleTable([column_1, column_2], column_spacing=-1)
444-
assert "Column spacing cannot be less than 0" in str(excinfo.value)
445439

446440
# Invalid divider character
447-
with pytest.raises(TypeError) as excinfo:
441+
with pytest.raises(TypeError, match="Divider character must be exactly one character long"):
448442
SimpleTable([column_1, column_2], divider_char='too long')
449-
assert "Divider character must be exactly one character long" in str(excinfo.value)
450443

451-
with pytest.raises(ValueError) as excinfo:
444+
with pytest.raises(ValueError, match="Divider character is an unprintable character"):
452445
SimpleTable([column_1, column_2], divider_char='\n')
453-
assert "Divider character is an unprintable character" in str(excinfo.value)
454446

455447
# Invalid row spacing
456448
st = SimpleTable([column_1, column_2])
457-
with pytest.raises(ValueError) as excinfo:
449+
with pytest.raises(ValueError, match="Row spacing cannot be less than 0"):
458450
st.generate_table(row_data, row_spacing=-1)
459-
assert "Row spacing cannot be less than 0" in str(excinfo.value)
460451

461452
# Test header and data colors
462453
st = SimpleTable([column_1, column_2], divider_char=None, header_bg=Bg.GREEN, data_bg=Bg.LIGHT_BLUE)
@@ -487,9 +478,8 @@ def test_simple_table_width():
487478
assert SimpleTable.base_width(num_cols) == (num_cols - 1) * 2
488479

489480
# Invalid num_cols value
490-
with pytest.raises(ValueError) as excinfo:
481+
with pytest.raises(ValueError, match="Column count cannot be less than 1"):
491482
SimpleTable.base_width(0)
492-
assert "Column count cannot be less than 1" in str(excinfo.value)
493483

494484
# Total width
495485
column_1 = Column("Col 1", width=16)
@@ -509,9 +499,8 @@ def test_simple_generate_data_row_exceptions():
509499

510500
# Data with too many columns
511501
row_data = ['Data 1', 'Extra Column']
512-
with pytest.raises(ValueError) as excinfo:
502+
with pytest.raises(ValueError, match="Length of row_data must match length of cols"):
513503
tc.generate_data_row(row_data=row_data)
514-
assert "Length of row_data must match length of cols" in str(excinfo.value)
515504

516505

517506
def test_bordered_table_creation():
@@ -573,9 +562,8 @@ def test_bordered_table_creation():
573562
)
574563

575564
# Invalid padding
576-
with pytest.raises(ValueError) as excinfo:
565+
with pytest.raises(ValueError, match="Padding cannot be less than 0"):
577566
BorderedTable([column_1, column_2], padding=-1)
578-
assert "Padding cannot be less than 0" in str(excinfo.value)
579567

580568
# Test border, header, and data colors
581569
bt = BorderedTable([column_1, column_2], border_fg=Fg.LIGHT_YELLOW, border_bg=Bg.WHITE,
@@ -629,9 +617,8 @@ def test_bordered_table_width():
629617
assert BorderedTable.base_width(3, padding=3) == 22
630618

631619
# Invalid num_cols value
632-
with pytest.raises(ValueError) as excinfo:
620+
with pytest.raises(ValueError, match="Column count cannot be less than 1"):
633621
BorderedTable.base_width(0)
634-
assert "Column count cannot be less than 1" in str(excinfo.value)
635622

636623
# Total width
637624
column_1 = Column("Col 1", width=15)
@@ -651,9 +638,8 @@ def test_bordered_generate_data_row_exceptions():
651638

652639
# Data with too many columns
653640
row_data = ['Data 1', 'Extra Column']
654-
with pytest.raises(ValueError) as excinfo:
641+
with pytest.raises(ValueError, match="Length of row_data must match length of cols"):
655642
tc.generate_data_row(row_data=row_data)
656-
assert "Length of row_data must match length of cols" in str(excinfo.value)
657643

658644

659645
def test_alternating_table_creation():
@@ -711,9 +697,8 @@ def test_alternating_table_creation():
711697
)
712698

713699
# Invalid padding
714-
with pytest.raises(ValueError) as excinfo:
700+
with pytest.raises(ValueError, match="Padding cannot be less than 0"):
715701
AlternatingTable([column_1, column_2], padding=-1)
716-
assert "Padding cannot be less than 0" in str(excinfo.value)
717702

718703
# Test border, header, and data colors
719704
at = AlternatingTable([column_1, column_2], border_fg=Fg.LIGHT_YELLOW, border_bg=Bg.WHITE,

tests/test_utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ def test_context_flag_bool(context_flag):
329329

330330

331331
def test_context_flag_exit_err(context_flag):
332-
with pytest.raises(ValueError):
332+
with pytest.raises(ValueError, match="count has gone below 0"):
333333
context_flag.__exit__()
334334

335335

@@ -423,14 +423,14 @@ def test_truncate_line_already_fits():
423423
def test_truncate_line_with_newline():
424424
line = 'fo\no'
425425
max_width = 2
426-
with pytest.raises(ValueError):
426+
with pytest.raises(ValueError, match="text contains an unprintable character"):
427427
cu.truncate_line(line, max_width)
428428

429429

430430
def test_truncate_line_width_is_too_small():
431431
line = 'foo'
432432
max_width = 0
433-
with pytest.raises(ValueError):
433+
with pytest.raises(ValueError, match="max_width must be at least 1"):
434434
cu.truncate_line(line, max_width)
435435

436436

@@ -548,7 +548,7 @@ def test_align_text_width_is_too_small():
548548
text = 'foo'
549549
fill_char = '-'
550550
width = 0
551-
with pytest.raises(ValueError):
551+
with pytest.raises(ValueError, match="width must be at least 1"):
552552
cu.align_text(text, cu.TextAlignment.LEFT, fill_char=fill_char, width=width)
553553

554554

@@ -564,7 +564,7 @@ def test_align_text_fill_char_is_newline():
564564
text = 'foo'
565565
fill_char = '\n'
566566
width = 5
567-
with pytest.raises(ValueError):
567+
with pytest.raises(ValueError, match="Fill character is an unprintable character"):
568568
cu.align_text(text, cu.TextAlignment.LEFT, fill_char=fill_char, width=width)
569569

570570

@@ -613,7 +613,7 @@ def test_align_text_has_unprintable():
613613
text = 'foo\x02'
614614
fill_char = '-'
615615
width = 5
616-
with pytest.raises(ValueError):
616+
with pytest.raises(ValueError, match="Text to align contains an unprintable character"):
617617
cu.align_text(text, cu.TextAlignment.LEFT, fill_char=fill_char, width=width)
618618

619619

@@ -830,7 +830,7 @@ def test_to_bool_str_false():
830830

831831

832832
def test_to_bool_str_invalid():
833-
with pytest.raises(ValueError):
833+
with pytest.raises(ValueError): # noqa: PT011
834834
cu.to_bool('other')
835835

836836

tests_isolated/test_commandset/conftest.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
mock,
1616
)
1717

18+
import pytest
1819
from cmd2_ext_test import (
1920
ExternalTestMixin,
2021
)
21-
from pytest import (
22-
fixture,
23-
)
2422

2523
import cmd2
2624
from cmd2.rl_utils import (
@@ -134,7 +132,7 @@ def run_cmd(app, cmd):
134132
return normalize(out), normalize(err)
135133

136134

137-
@fixture
135+
@pytest.fixture
138136
def base_app():
139137
return cmd2.Cmd()
140138

@@ -183,13 +181,13 @@ def __init__(self, *args, **kwargs):
183181
super(WithCommandSets, self).__init__(*args, **kwargs)
184182

185183

186-
@fixture
184+
@pytest.fixture
187185
def command_sets_app():
188186
app = WithCommandSets()
189187
return app
190188

191189

192-
@fixture
190+
@pytest.fixture
193191
def command_sets_manual():
194192
app = WithCommandSets(auto_load_commands=False)
195193
return app

tests_isolated/test_commandset/test_commandset.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,10 @@ def __init__(self):
11491149
cmdset_nopfx = WithSettablesNoPrefix()
11501150
app.register_command_set(cmdset_nopfx)
11511151

1152-
with pytest.raises(ValueError):
1152+
with pytest.raises(
1153+
ValueError,
1154+
match="Cannot force settable prefixes. CommandSet WithSettablesNoPrefix does not have a settable prefix defined.",
1155+
):
11531156
app.always_prefix_settables = True
11541157

11551158
app.unregister_command_set(cmdset_nopfx)

0 commit comments

Comments
 (0)