diff --git a/tests/end2end/fixtures/test_quteprocess.py b/tests/end2end/fixtures/test_quteprocess.py index 31af8eeae..9362df442 100644 --- a/tests/end2end/fixtures/test_quteprocess.py +++ b/tests/end2end/fixtures/test_quteprocess.py @@ -113,7 +113,7 @@ def test_quteproc_error_message_did_fail(qtbot, quteproc, request_mock): def test_quteproc_skip_via_js(qtbot, quteproc): - with pytest.raises(pytest.skip.Exception) as excinfo: + with pytest.raises(pytest.skip.Exception, match='test'): quteproc.send_cmd(':jseval console.log("[SKIP] test");') quteproc.wait_for_js('[SKIP] test') @@ -121,8 +121,6 @@ def test_quteproc_skip_via_js(qtbot, quteproc): # the error to occur during the test rather than at teardown time. quteproc.after_test() - assert str(excinfo.value) == 'test' - def test_quteproc_skip_and_wait_for(qtbot, quteproc): """This test will skip *again* during teardown, but we don't care.""" @@ -312,14 +310,12 @@ class TestClickElementByText: quteproc.wait_for_js('click_element special chars') def test_duplicate(self, quteproc): - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match='not unique'): quteproc.click_element_by_text('Duplicate') - assert 'not unique' in str(excinfo.value) def test_nonexistent(self, quteproc): - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match='No element'): quteproc.click_element_by_text('no element exists with this text') - assert 'No element' in str(excinfo.value) @pytest.mark.parametrize('string, expected', [ diff --git a/tests/unit/browser/webkit/test_mhtml.py b/tests/unit/browser/webkit/test_mhtml.py index 47b9e3145..230565680 100644 --- a/tests/unit/browser/webkit/test_mhtml.py +++ b/tests/unit/browser/webkit/test_mhtml.py @@ -104,9 +104,8 @@ def test_refuses_non_ascii_header_value(checker, header, value): } defaults[header] = value writer = mhtml.MHTMLWriter(**defaults) - with pytest.raises(UnicodeEncodeError) as excinfo: + with pytest.raises(UnicodeEncodeError, match="'ascii' codec can't encode"): writer.write_to(checker.fp) - assert "'ascii' codec can't encode" in str(excinfo.value) def test_file_encoded_as_base64(checker): @@ -325,9 +324,8 @@ class TestNoCloseBytesIO: fp = mhtml._NoCloseBytesIO() fp.write(b'Value') fp.actual_close() - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="I/O operation on closed file."): + fp.getvalue() + with pytest.raises(ValueError, match="I/O operation on closed file."): fp.getvalue() - assert str(excinfo.value) == 'I/O operation on closed file.' - with pytest.raises(ValueError) as excinfo: fp.write(b'Closed') - assert str(excinfo.value) == 'I/O operation on closed file.' diff --git a/tests/unit/browser/webkit/test_webkitelem.py b/tests/unit/browser/webkit/test_webkitelem.py index e2febc860..deff844fe 100644 --- a/tests/unit/browser/webkit/test_webkitelem.py +++ b/tests/unit/browser/webkit/test_webkitelem.py @@ -239,9 +239,8 @@ class TestWebKitElement: def test_double_wrap(self, elem): """Test wrapping a WebKitElement.""" - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match="Trying to wrap a wrapper!"): webkitelem.WebKitElement(elem, tab=None) - assert str(excinfo.value) == "Trying to wrap a wrapper!" @pytest.mark.parametrize('code', [ pytest.param(str, id='str'), diff --git a/tests/unit/commands/test_argparser.py b/tests/unit/commands/test_argparser.py index 54a584e71..cf9eef016 100644 --- a/tests/unit/commands/test_argparser.py +++ b/tests/unit/commands/test_argparser.py @@ -65,9 +65,9 @@ class TestArgumentParser: assert excinfo.value.status == 0 def test_error(self, parser): - with pytest.raises(argparser.ArgumentParserError) as excinfo: + with pytest.raises(argparser.ArgumentParserError, + match="Unrecognized arguments: --foo"): parser.parse_args(['--foo']) - assert str(excinfo.value) == "Unrecognized arguments: --foo" def test_help(self, parser, tabbed_browser): parser.add_argument('--help', action=argparser.HelpAction, nargs=0) @@ -106,12 +106,6 @@ def test_type_conv_valid(types, value, expected, multi): def test_type_conv_invalid(typ, value, multi): param = inspect.Parameter('foo', inspect.Parameter.POSITIONAL_ONLY) - with pytest.raises(cmdexc.ArgumentTypeError) as excinfo: - if multi: - argparser.multitype_conv(param, [typ], value) - else: - argparser.type_conv(param, typ, value) - if multi: msg = 'foo: Invalid value {}'.format(value) elif typ is Enum: @@ -119,15 +113,19 @@ def test_type_conv_invalid(typ, value, multi): 'foo-bar'.format(value)) else: msg = 'foo: Invalid {} value {}'.format(typ.__name__, value) - assert str(excinfo.value) == msg + + with pytest.raises(cmdexc.ArgumentTypeError, match=msg): + if multi: + argparser.multitype_conv(param, [typ], value) + else: + argparser.type_conv(param, typ, value) def test_multitype_conv_invalid_type(): """Test using an invalid type with a multitype converter.""" param = inspect.Parameter('foo', inspect.Parameter.POSITIONAL_ONLY) - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="foo: Unknown type None!"): argparser.multitype_conv(param, [None], '') - assert str(excinfo.value) == "foo: Unknown type None!" @pytest.mark.parametrize('value, typ', [(None, None), (42, int)]) @@ -146,9 +144,8 @@ def test_conv_str_type(): no string annotations are there anymore. """ param = inspect.Parameter('foo', inspect.Parameter.POSITIONAL_ONLY) - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match='foo: Legacy string type!'): argparser.type_conv(param, 'val', None) - assert str(excinfo.value) == 'foo: Legacy string type!' def test_conv_str_choices_valid(): @@ -162,7 +159,6 @@ def test_conv_str_choices_valid(): def test_conv_str_choices_invalid(): """Calling str type with str_choices and invalid value.""" param = inspect.Parameter('foo', inspect.Parameter.POSITIONAL_ONLY) - with pytest.raises(cmdexc.ArgumentTypeError) as excinfo: + with pytest.raises(cmdexc.ArgumentTypeError, match='foo: Invalid value ' + 'val3 - expected one of: val1, val2'): argparser.type_conv(param, str, 'val3', str_choices=['val1', 'val2']) - msg = 'foo: Invalid value val3 - expected one of: val1, val2' - assert str(excinfo.value) == msg diff --git a/tests/unit/commands/test_cmdutils.py b/tests/unit/commands/test_cmdutils.py index 06740031c..f3a8cbfea 100644 --- a/tests/unit/commands/test_cmdutils.py +++ b/tests/unit/commands/test_cmdutils.py @@ -59,14 +59,10 @@ class TestCheckOverflow: def test_bad(self): int32_max = 2 ** 31 - 1 - with pytest.raises(cmdexc.CommandError) as excinfo: + with pytest.raises(cmdexc.CommandError, match="Numeric argument is " + "too large for internal int representation."): cmdutils.check_overflow(int32_max + 1, 'int') - expected_str = ("Numeric argument is too large for internal int " - "representation.") - - assert str(excinfo.value) == expected_str - class TestCheckExclusive: @@ -75,11 +71,10 @@ class TestCheckExclusive: cmdutils.check_exclusive(flags, []) def test_bad(self): - with pytest.raises(cmdexc.CommandError) as excinfo: + with pytest.raises(cmdexc.CommandError, + match="Only one of -x/-y/-z can be given!"): cmdutils.check_exclusive([True, True], 'xyz') - assert str(excinfo.value) == "Only one of -x/-y/-z can be given!" - class TestRegister: @@ -241,16 +236,14 @@ class TestRegister: assert cmdutils.cmd_dict['fun']._get_call_args(42) == ([0], {}) def test_count_without_default(self): - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match="fun: handler has count parameter " + "without default!"): @cmdutils.register() @cmdutils.argument('count', count=True) def fun(count): """Blah.""" pass - expected = "fun: handler has count parameter without default!" - assert str(excinfo.value) == expected - @pytest.mark.parametrize('hide', [True, False]) def test_pos_args(self, hide): @cmdutils.register() @@ -355,38 +348,31 @@ class TestRegister: """Blah.""" pass - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match="fun: handler has keyword only " + "argument 'target' without default!"): fun = cmdutils.register()(fun) - expected = ("fun: handler has keyword only argument 'target' without " - "default!") - assert str(excinfo.value) == expected - def test_typed_keyword_only_without_default(self): # https://github.com/qutebrowser/qutebrowser/issues/1872 def fun(*, target: int): """Blah.""" pass - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match="fun: handler has keyword only " + "argument 'target' without default!"): fun = cmdutils.register()(fun) - expected = ("fun: handler has keyword only argument 'target' without " - "default!") - assert str(excinfo.value) == expected - class TestArgument: """Test the @cmdutils.argument decorator.""" def test_invalid_argument(self): - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="fun has no argument foo!"): @cmdutils.argument('foo') def fun(bar): """Blah.""" pass - assert str(excinfo.value) == "fun has no argument foo!" def test_storage(self): @cmdutils.argument('foo', flag='x') @@ -402,27 +388,22 @@ class TestArgument: def test_wrong_order(self): """When @cmdutils.argument is used above (after) @register, fail.""" - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match=r"@cmdutils.argument got called " + "above \(after\) @cmdutils.register for fun!"): @cmdutils.argument('bar', flag='y') @cmdutils.register() def fun(bar): """Blah.""" pass - text = ("@cmdutils.argument got called above (after) " - "@cmdutils.register for fun!") - - assert str(excinfo.value) == text - def test_count_and_win_id_same_arg(self): - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, + match="Argument marked as both count/win_id!"): @cmdutils.argument('arg', count=True, win_id=True) def fun(arg=0): """Blah.""" pass - assert str(excinfo.value) == "Argument marked as both count/win_id!" - def test_no_docstring(self, caplog): with caplog.at_level(logging.WARNING): @cmdutils.register() @@ -464,9 +445,9 @@ class TestRun: if ok: cmd.run(win_id=0) else: - with pytest.raises(cmdexc.PrerequisitesError) as excinfo: + with pytest.raises(cmdexc.PrerequisitesError, + match=r'.* backend\.'): cmd.run(win_id=0) - assert str(excinfo.value).endswith(' backend.') def test_no_args(self): cmd = _get_cmd() @@ -488,6 +469,5 @@ class TestRun: monkeypatch.setattr(command.objects, 'backend', usertypes.Backend.QtWebKit) cmd = cmdutils.cmd_dict['fun'] - with pytest.raises(cmdexc.PrerequisitesError) as excinfo: + with pytest.raises(cmdexc.PrerequisitesError, match=r'.* backend\.'): cmd.run(win_id=0) - assert str(excinfo.value).endswith(' backend.') diff --git a/tests/unit/commands/test_userscripts.py b/tests/unit/commands/test_userscripts.py index c6348d028..df3c53c68 100644 --- a/tests/unit/commands/test_userscripts.py +++ b/tests/unit/commands/test_userscripts.py @@ -247,7 +247,6 @@ def test_unicode_error(caplog, qtbot, py_proc, runner): def test_unsupported(monkeypatch, tabbed_browser_stubs): monkeypatch.setattr(userscripts.os, 'name', 'toaster') - with pytest.raises(userscripts.UnsupportedError) as excinfo: + with pytest.raises(userscripts.UnsupportedError, match="Userscripts are " + "not supported on this platform!"): userscripts.run_async(tab=None, cmd=None, win_id=0, env=None) - expected = "Userscripts are not supported on this platform!" - assert str(excinfo.value) == expected diff --git a/tests/unit/config/test_configdata.py b/tests/unit/config/test_configdata.py index 50509820e..fdb7f00e4 100644 --- a/tests/unit/config/test_configdata.py +++ b/tests/unit/config/test_configdata.py @@ -39,6 +39,6 @@ def test_data(): def test_readonly_data(): """Make sure DATA is readonly.""" - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="Trying to modify a read-only " + "config!"): configdata.DATA['general'].setv('temp', 'ignore-case', 'true', 'true') - assert str(excinfo.value) == "Trying to modify a read-only config!" diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py index 0cb0763e7..f8494ed2b 100644 --- a/tests/unit/keyinput/test_basekeyparser.py +++ b/tests/unit/keyinput/test_basekeyparser.py @@ -128,12 +128,10 @@ class TestReadConfig: assert keyparser._modename is None # No config set so self._modename is None - with pytest.raises(AssertionError) as excinfo: + with pytest.raises(AssertionError, match="on_keyconfig_changed called " + "but no section defined!"): keyparser.on_keyconfig_changed('normal') - expected_text = "on_keyconfig_changed called but no section defined!" - assert str(excinfo.value) == expected_text - @pytest.mark.parametrize('mode,changed_mode, expected', [ ('normal', 'normal', True), ('normal', 'normal2', False), ]) diff --git a/tests/unit/misc/test_cmdhistory.py b/tests/unit/misc/test_cmdhistory.py index 717fd4a96..ed7af2a12 100644 --- a/tests/unit/misc/test_cmdhistory.py +++ b/tests/unit/misc/test_cmdhistory.py @@ -90,21 +90,20 @@ def test_getitem(hist): def test_setitem(hist): """Test __setitem__.""" - with pytest.raises(TypeError) as excinfo: + with pytest.raises(TypeError, match="'History' object does not support " + "item assignment"): hist[0] = 'foo' - expected = "'History' object does not support item assignment" - assert str(excinfo.value) == expected def test_not_browsing_error(hist): """Test that next/previtem throws a ValueError.""" - with pytest.raises(ValueError) as error1: + with pytest.raises(ValueError, match="Currently not browsing " + "history"): hist.nextitem() - assert str(error1.value) == "Currently not browsing history" - with pytest.raises(ValueError) as error2: + with pytest.raises(ValueError, match="Currently not browsing " + "history"): hist.previtem() - assert str(error2.value) == "Currently not browsing history" def test_nextitem_single(hist, monkeypatch): diff --git a/tests/unit/misc/test_ipc.py b/tests/unit/misc/test_ipc.py index cf5cc9a3f..e364d6cc6 100644 --- a/tests/unit/misc/test_ipc.py +++ b/tests/unit/misc/test_ipc.py @@ -269,9 +269,9 @@ class TestListen: def test_remove_error(self, ipc_server, monkeypatch): """Simulate an error in _remove_server.""" monkeypatch.setattr(ipc_server, '_socketname', None) - with pytest.raises(ipc.Error) as excinfo: + with pytest.raises(ipc.Error, + match="Error while removing server None!"): ipc_server.listen() - assert str(excinfo.value) == "Error while removing server None!" def test_error(self, ipc_server, monkeypatch): """Simulate an error while listening.""" @@ -369,13 +369,10 @@ class TestOnError: lambda: "Connection refused") socket.setErrorString("Connection refused.") - with pytest.raises(ipc.Error) as excinfo: + with pytest.raises(ipc.Error, match=r"Error while handling IPC " + r"connection: Connection refused \(error 0\)"): ipc_server.on_error(QLocalSocket.ConnectionRefusedError) - expected = ("Error while handling IPC connection: Connection refused " - "(error 0)") - assert str(excinfo.value) == expected - class TestHandleConnection: @@ -409,11 +406,10 @@ class TestHandleConnection: socket = FakeSocket(error=QLocalSocket.ConnectionError) ipc_server._server = FakeServer(socket) - with pytest.raises(ipc.Error) as excinfo: + with pytest.raises(ipc.Error, match=r"Error while handling IPC " + r"connection: Error string \(error 7\)"): ipc_server.handle_connection() - exc_msg = 'Error while handling IPC connection: Error string (error 7)' - assert str(excinfo.value) == exc_msg msg = "We got an error immediately." all_msgs = [r.message for r in caplog.records] assert msg in all_msgs @@ -550,12 +546,10 @@ class TestSendToRunningInstance: def test_socket_error(self): socket = FakeSocket(error=QLocalSocket.ConnectionError) - with pytest.raises(ipc.Error) as excinfo: + with pytest.raises(ipc.Error, match=r"Error while writing to running " + r"instance: Error string \(error 7\)"): ipc.send_to_running_instance('qute-test', [], None, socket=socket) - msg = "Error while writing to running instance: Error string (error 7)" - assert str(excinfo.value) == msg - def test_not_disconnected_immediately(self): socket = FakeSocket() ipc.send_to_running_instance('qute-test', [], None, socket=socket) @@ -563,13 +557,10 @@ class TestSendToRunningInstance: def test_socket_error_no_server(self): socket = FakeSocket(error=QLocalSocket.ConnectionError, connect_successful=False) - with pytest.raises(ipc.Error) as excinfo: + with pytest.raises(ipc.Error, match=r"Error while connecting to " + r"running instance: Error string \(error 7\)"): ipc.send_to_running_instance('qute-test', [], None, socket=socket) - msg = ("Error while connecting to running instance: Error string " - "(error 7)") - assert str(excinfo.value) == msg - @pytest.mark.not_osx(reason="https://github.com/qutebrowser/qutebrowser/" "issues/975") diff --git a/tests/unit/misc/test_lineparser.py b/tests/unit/misc/test_lineparser.py index b2dc90529..af439c006 100644 --- a/tests/unit/misc/test_lineparser.py +++ b/tests/unit/misc/test_lineparser.py @@ -58,10 +58,10 @@ class TestBaseLineParser: mocker.patch('builtins.open', mock.mock_open()) with lineparser._open('r'): - with pytest.raises(IOError) as excinf: + with pytest.raises(IOError, match="Refusing to double-open " + "AppendLineParser."): with lineparser._open('r'): pass - assert str(excinf.value) == 'Refusing to double-open AppendLineParser.' def test_binary(self, mocker): """Test if _open and _write correctly handle binary files.""" diff --git a/tests/unit/misc/test_sessions.py b/tests/unit/misc/test_sessions.py index c30ac6bdc..59b335f78 100644 --- a/tests/unit/misc/test_sessions.py +++ b/tests/unit/misc/test_sessions.py @@ -263,10 +263,9 @@ class TestSave: mocker.patch('qutebrowser.misc.sessions.yaml.dump', side_effect=exception) - with pytest.raises(sessions.SessionError) as excinfo: + with pytest.raises(sessions.SessionError, match=str(exception)): sess_man.save(str(tmpdir / 'foo.yml')) - assert str(excinfo.value) == str(exception) assert not tmpdir.listdir() def test_load_next_time(self, tmpdir, state_config, sess_man): diff --git a/tests/unit/misc/test_utilcmds.py b/tests/unit/misc/test_utilcmds.py index aa0234c61..8235509fb 100644 --- a/tests/unit/misc/test_utilcmds.py +++ b/tests/unit/misc/test_utilcmds.py @@ -41,9 +41,8 @@ def _trapped_segv(handler): def test_debug_crash_exception(): """Verify that debug_crash crashes as intended.""" - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception, match="Forced crash"): utilcmds.debug_crash(typ='exception') - assert str(excinfo.value) == 'Forced crash' @pytest.mark.skipif(os.name == 'nt', @@ -60,11 +59,10 @@ def test_debug_crash_segfault(): with _trapped_segv(_handler): # since we handle the segfault, execution will continue and run into # the "Segfault failed (wat.)" Exception - with pytest.raises(Exception) as excinfo: + with pytest.raises(Exception, match="Segfault failed"): utilcmds.debug_crash(typ='segfault') time.sleep(0.001) assert caught - assert 'Segfault failed' in str(excinfo.value) def test_debug_trace(mocker): @@ -84,18 +82,16 @@ def test_debug_trace_exception(mocker): hunter_mock = mocker.patch('qutebrowser.misc.utilcmds.hunter') hunter_mock.trace.side_effect = _mock_exception - with pytest.raises(cmdexc.CommandError) as excinfo: + with pytest.raises(cmdexc.CommandError, match='Exception: message'): utilcmds.debug_trace() - assert str(excinfo.value) == 'Exception: message' def test_debug_trace_no_hunter(monkeypatch): """Test that an error is shown if debug_trace is called without hunter.""" monkeypatch.setattr(utilcmds, 'hunter', None) - with pytest.raises(cmdexc.CommandError) as excinfo: + with pytest.raises(cmdexc.CommandError, match="You need to install " + "'hunter' to use this command!"): utilcmds.debug_trace() - assert str(excinfo.value) == "You need to install 'hunter' to use this " \ - "command!" def test_repeat_command_initial(mocker, mode_manager): @@ -106,9 +102,9 @@ def test_repeat_command_initial(mocker, mode_manager): """ objreg_mock = mocker.patch('qutebrowser.misc.utilcmds.objreg') objreg_mock.get.return_value = mode_manager - with pytest.raises(cmdexc.CommandError) as excinfo: + with pytest.raises(cmdexc.CommandError, + match="You didn't do anything yet."): utilcmds.repeat_command(win_id=0) - assert str(excinfo.value) == "You didn't do anything yet." def test_debug_log_level(mocker): diff --git a/tests/unit/utils/test_qtutils.py b/tests/unit/utils/test_qtutils.py index f7bf559a5..99e1091b4 100644 --- a/tests/unit/utils/test_qtutils.py +++ b/tests/unit/utils/test_qtutils.py @@ -258,9 +258,8 @@ def test_check_qdatastream(status, raising, message): stream = QDataStream() stream.setStatus(status) if raising: - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match=message): qtutils.check_qdatastream(stream) - assert str(excinfo.value) == message else: qtutils.check_qdatastream(stream) @@ -306,11 +305,11 @@ class TestSerializeStream: """Test serialize_stream with an error already set.""" stream_mock.status.return_value = QDataStream.ReadCorruptData - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream has read corrupt " + "data."): qtutils.serialize_stream(stream_mock, QPoint()) assert not stream_mock.__lshift__.called - assert str(excinfo.value) == "The data stream has read corrupt data." def test_serialize_post_error_mock(self, stream_mock): """Test serialize_stream with an error while serializing.""" @@ -318,21 +317,21 @@ class TestSerializeStream: stream_mock.__lshift__.side_effect = lambda _other: self._set_status( stream_mock, QDataStream.ReadCorruptData) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream has read corrupt " + "data."): qtutils.serialize_stream(stream_mock, obj) assert stream_mock.__lshift__.called_once_with(obj) - assert str(excinfo.value) == "The data stream has read corrupt data." def test_deserialize_pre_error_mock(self, stream_mock): """Test deserialize_stream with an error already set.""" stream_mock.status.return_value = QDataStream.ReadCorruptData - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream has read corrupt " + "data."): qtutils.deserialize_stream(stream_mock, QPoint()) assert not stream_mock.__rshift__.called - assert str(excinfo.value) == "The data stream has read corrupt data." def test_deserialize_post_error_mock(self, stream_mock): """Test deserialize_stream with an error while deserializing.""" @@ -340,11 +339,11 @@ class TestSerializeStream: stream_mock.__rshift__.side_effect = lambda _other: self._set_status( stream_mock, QDataStream.ReadCorruptData) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream has read corrupt " + "data."): qtutils.deserialize_stream(stream_mock, obj) assert stream_mock.__rshift__.called_once_with(obj) - assert str(excinfo.value) == "The data stream has read corrupt data." def test_round_trip_real_stream(self): """Test a round trip with a real QDataStream.""" @@ -365,10 +364,9 @@ class TestSerializeStream: """Test serialize_stream with a read-only stream.""" data = QByteArray() stream = QDataStream(data, QIODevice.ReadOnly) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream cannot write to " + "the underlying device."): qtutils.serialize_stream(stream, QPoint()) - assert str(excinfo.value) == ("The data stream cannot write to the " - "underlying device.") @pytest.mark.qt_log_ignore('QIODevice::read.*: WriteOnly device') def test_deserialize_writeonly_stream(self): @@ -376,10 +374,9 @@ class TestSerializeStream: data = QByteArray() obj = QPoint() stream = QDataStream(data, QIODevice.WriteOnly) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="The data stream has read past the " + "end of the data in the underlying device."): qtutils.deserialize_stream(stream, obj) - assert str(excinfo.value) == ("The data stream has read past the end " - "of the data in the underlying device.") class SavefileTestException(Exception): @@ -409,13 +406,12 @@ class TestSavefileOpen: qsavefile_mock.open.return_value = False qsavefile_mock.errorString.return_value = "Hello World" - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="Hello World"): with qtutils.savefile_open('filename'): pass qsavefile_mock.open.assert_called_once_with(QIODevice.WriteOnly) qsavefile_mock.cancelWriting.assert_called_once_with() - assert str(excinfo.value) == "Hello World" def test_mock_exception(self, qsavefile_mock): """Test with a mock and an exception in the block.""" @@ -433,14 +429,13 @@ class TestSavefileOpen: qsavefile_mock.open.return_value = True qsavefile_mock.commit.return_value = False - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="Commit failed!"): with qtutils.savefile_open('filename'): pass qsavefile_mock.open.assert_called_once_with(QIODevice.WriteOnly) assert not qsavefile_mock.cancelWriting.called assert not qsavefile_mock.errorString.called - assert str(excinfo.value) == "Commit failed!" def test_mock_successful(self, qsavefile_mock): """Test with a mock and a successful write.""" @@ -503,23 +498,21 @@ class TestSavefileOpen: def test_failing_flush(self, tmpdir): """Test with the file being closed before flushing.""" filename = tmpdir / 'foo' - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="IO operation on closed device!"): with qtutils.savefile_open(str(filename), binary=True) as f: f.write(b'Hello') f.dev.commit() # provoke failing flush - assert str(excinfo.value) == "IO operation on closed device!" assert tmpdir.listdir() == [filename] def test_failing_commit(self, tmpdir): """Test with the file being closed before committing.""" filename = tmpdir / 'foo' - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match='Commit failed!'): with qtutils.savefile_open(str(filename), binary=True) as f: f.write(b'Hello') f.dev.cancelWriting() # provoke failing commit - assert str(excinfo.value) == "Commit failed!" assert tmpdir.listdir() == [] def test_line_endings(self, tmpdir): @@ -694,9 +687,8 @@ class TestPyQIODevice: args: The arguments to pass. """ func = getattr(pyqiodev, method) - with pytest.raises(ValueError) as excinfo: + with pytest.raises(ValueError, match="IO operation on closed device!"): func(*args) - assert str(excinfo.value) == "IO operation on closed device!" @pytest.mark.parametrize('method', ['readline', 'read']) def test_unreadable(self, pyqiodev, method): @@ -707,16 +699,15 @@ class TestPyQIODevice: """ pyqiodev.open(QIODevice.WriteOnly) func = getattr(pyqiodev, method) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="Trying to read unreadable file!"): func() - assert str(excinfo.value) == "Trying to read unreadable file!" def test_unwritable(self, pyqiodev): """Test writing with a read-only device.""" pyqiodev.open(QIODevice.ReadOnly) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="Trying to write to unwritable " + "file!"): pyqiodev.write(b'') - assert str(excinfo.value) == "Trying to write to unwritable file!" @pytest.mark.parametrize('data', [b'12345', b'']) def test_len(self, pyqiodev, data): @@ -769,9 +760,8 @@ class TestPyQIODevice: f.write(b'1234567890') pyqiodev.open(QIODevice.ReadOnly) if raising: - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="seek failed!"): pyqiodev.seek(offset, whence) - assert str(excinfo.value) == "seek failed!" else: pyqiodev.seek(offset, whence) assert pyqiodev.tell() == pos @@ -800,12 +790,10 @@ class TestPyQIODevice: proc.start(*py_proc('print("Hello World")')) dev = qtutils.PyQIODevice(proc) assert not dev.closed - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match='Random access not allowed!'): dev.seek(0) - assert str(excinfo.value) == 'Random access not allowed!' - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match='Random access not allowed!'): dev.tell() - assert str(excinfo.value) == 'Random access not allowed!' proc.waitForFinished(1000) proc.kill() assert bytes(dev.read()).rstrip() == b'Hello World' @@ -900,9 +888,8 @@ class TestPyQIODevice: def test_write_error(self, pyqiodev_failing): """Test writing with FailingQIODevice.""" - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match="Writing failed"): pyqiodev_failing.write(b'x') - assert str(excinfo.value) == 'Writing failed' @pytest.mark.posix @pytest.mark.skipif(not os.path.exists('/dev/full'), @@ -912,10 +899,9 @@ class TestPyQIODevice: qf = QFile('/dev/full') qf.open(QIODevice.WriteOnly | QIODevice.Unbuffered) dev = qtutils.PyQIODevice(qf) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match='No space left on device'): dev.write(b'foo') qf.close() - assert str(excinfo.value) == 'No space left on device' @pytest.mark.parametrize('size, chunks', [ (-1, [b'1234567890']), @@ -951,9 +937,8 @@ class TestPyQIODevice: args: A list of arguments to pass. """ func = getattr(pyqiodev_failing, method) - with pytest.raises(OSError) as excinfo: + with pytest.raises(OSError, match='Reading failed'): func(*args) - assert str(excinfo.value) == 'Reading failed' @pytest.mark.usefixtures('qapp') diff --git a/tests/unit/utils/test_urlutils.py b/tests/unit/utils/test_urlutils.py index c91e603e7..10bd60bed 100644 --- a/tests/unit/utils/test_urlutils.py +++ b/tests/unit/utils/test_urlutils.py @@ -471,13 +471,12 @@ def test_raise_cmdexc_if_invalid(url, valid, has_err_string): urlutils.raise_cmdexc_if_invalid(qurl) else: assert bool(qurl.errorString()) == has_err_string - with pytest.raises(cmdexc.CommandError) as excinfo: - urlutils.raise_cmdexc_if_invalid(qurl) if has_err_string: expected_text = "Invalid URL - " + qurl.errorString() else: expected_text = "Invalid URL" - assert str(excinfo.value) == expected_text + with pytest.raises(cmdexc.CommandError, match=expected_text): + urlutils.raise_cmdexc_if_invalid(qurl) @pytest.mark.parametrize('qurl, output', [