From 9c87eaf3714a71ca7da6b47ae90982c83c59d910 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 14 Jan 2016 18:50:36 +0100 Subject: [PATCH] bdd: Allow to skip a test from JS. This is a bit tricky since the test will actually run, but be marked as skipped. The problem is we can't raise a pytest.skip.Exception during a test, or it'll show up as an exception in a virtual Qt method. Still this is better than nothing. --- tests/integration/features/conftest.py | 3 +-- tests/integration/quteprocess.py | 21 +++++++++++++++++++++ tests/integration/test_quteprocess.py | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/integration/features/conftest.py b/tests/integration/features/conftest.py index 9a05a18db..c071c9c8b 100644 --- a/tests/integration/features/conftest.py +++ b/tests/integration/features/conftest.py @@ -297,8 +297,7 @@ def ensure_not_logged(quteproc, pattern): 'logged')) def javascript_message_logged(quteproc, message): """Make sure the given message was logged via javascript.""" - quteproc.wait_for(category='js', function='javaScriptConsoleMessage', - message='[*] {}'.format(message)) + quteproc.wait_for_js(message) @bdd.then(bdd.parsers.parse('the javascript message "{message}" should not be ' diff --git a/tests/integration/quteprocess.py b/tests/integration/quteprocess.py index d48a3fbf5..e1e164b9d 100644 --- a/tests/integration/quteprocess.py +++ b/tests/integration/quteprocess.py @@ -225,6 +225,11 @@ class QuteProc(testprocess.Process): self._httpbin.port if port is None else port, path if path != '/' else '') + def wait_for_js(self, message): + """Wait for the given javascript console message.""" + self.wait_for(category='js', function='javaScriptConsoleMessage', + message='[*] {}'.format(message)) + def _is_error_logline(self, msg): """Check if the given LogLine is some kind of error message.""" is_js_error = (msg.category == 'js' and @@ -233,16 +238,32 @@ class QuteProc(testprocess.Process): value=msg.message)) return msg.loglevel > logging.INFO or is_js_error + def _is_js_skip_logline(self, msg): + """Check if a JS snippet wanted to skip a test.""" + return (msg.category == 'js' and + msg.function == 'javaScriptConsoleMessage' and + testutils.pattern_match(pattern='[*] [SKIP] *', + value=msg.message)) + def after_test(self): bad_msgs = [msg for msg in self._data if self._is_error_logline(msg) and not msg.expected] + skip_msgs = [msg for msg in self._data + if self._is_js_skip_logline(msg)] + super().after_test() + if bad_msgs: text = 'Logged unexpected errors:\n\n' + '\n'.join( str(e) for e in bad_msgs) # We'd like to use pytrace=False here but don't as a WORKAROUND # for https://github.com/pytest-dev/pytest/issues/1316 pytest.fail(text) + elif skip_msgs: + texts = [] + for msg in skip_msgs: + texts.append(msg.message.partition(' [SKIP] ')[2]) + pytest.skip(', '.join(texts)) def send_cmd(self, command, count=None): """Send a command to the running qutebrowser instance.""" diff --git a/tests/integration/test_quteprocess.py b/tests/integration/test_quteprocess.py index f998dab4c..2b9a14b8d 100644 --- a/tests/integration/test_quteprocess.py +++ b/tests/integration/test_quteprocess.py @@ -43,6 +43,23 @@ def test_quteproc_error_message(qtbot, quteproc, cmd): quteproc.after_test() +@pytest.mark.parametrize('texts, expected', [ + (["[SKIP] test"], "test"), + (["[SKIP] foo", "[SKIP] bar"], "foo, bar"), +]) +def test_quteproc_skip_via_js(qtbot, quteproc, texts, expected): + for text in texts: + quteproc.send_cmd(':jseval console.log("{}");'.format(text)) + quteproc.wait_for_js(text) + + # Usually we wouldn't call this from inside a test, but here we force the + # error to occur during the test rather than at teardown time. + with pytest.raises(pytest.skip.Exception) as excinfo: + quteproc.after_test() + + assert str(excinfo.value) == expected + + def test_qt_log_ignore(qtbot, quteproc): """Make sure the test passes when logging a qt_log_ignore message.""" with qtbot.waitSignal(quteproc.got_error):