From 7412e4f72306e1bfe29fca673fda3b51a933e5e4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 11 Aug 2015 07:41:25 +0200 Subject: [PATCH] Reorganize utils.debug tests and add some more. --- tests/utils/debug/test_log_time.py | 45 ------- tests/utils/debug/test_qenum_key.py | 64 ---------- tests/utils/debug/test_qflags_key.py | 77 ------------ tests/utils/debug/test_signal.py | 52 -------- tests/utils/test_debug.py | 173 +++++++++++++++++++++++++++ 5 files changed, 173 insertions(+), 238 deletions(-) delete mode 100644 tests/utils/debug/test_log_time.py delete mode 100644 tests/utils/debug/test_qenum_key.py delete mode 100644 tests/utils/debug/test_qflags_key.py delete mode 100644 tests/utils/debug/test_signal.py create mode 100644 tests/utils/test_debug.py diff --git a/tests/utils/debug/test_log_time.py b/tests/utils/debug/test_log_time.py deleted file mode 100644 index 95bafaf92..000000000 --- a/tests/utils/debug/test_log_time.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2014-2015 Florian Bruhin (The Compiler) -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -"""Tests for qutebrowser.utils.debug.log_time.""" - -import logging -import re -import time - -from qutebrowser.utils import debug - - -def test_log_time(caplog): - """Test if log_time logs properly.""" - logger_name = 'qt-tests' - - with caplog.atLevel(logging.DEBUG, logger_name): - with debug.log_time(logging.getLogger(logger_name), action='foobar'): - time.sleep(0.1) - - records = caplog.records() - assert len(records) == 1 - - pattern = re.compile(r'^Foobar took ([\d.]*) seconds\.$') - match = pattern.match(records[0].msg) - assert match - - duration = float(match.group(1)) - assert 0 < duration < 1 diff --git a/tests/utils/debug/test_qenum_key.py b/tests/utils/debug/test_qenum_key.py deleted file mode 100644 index c43279a4a..000000000 --- a/tests/utils/debug/test_qenum_key.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2014-2015 Florian Bruhin (The Compiler) -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -"""Tests for qutebrowser.utils.debug.qenum_key.""" - -import pytest - -from PyQt5.QtWidgets import QStyle, QFrame - -from qutebrowser.utils import debug - - -def test_no_metaobj(): - """Test with an enum with no meta-object.""" - assert not hasattr(QStyle.PrimitiveElement, 'staticMetaObject') - key = debug.qenum_key(QStyle, QStyle.PE_PanelButtonCommand) - assert key == 'PE_PanelButtonCommand' - - -def test_metaobj(): - """Test with an enum with meta-object.""" - assert hasattr(QFrame, 'staticMetaObject') - key = debug.qenum_key(QFrame, QFrame.Sunken) - assert key == 'Sunken' - - -def test_add_base(): - """Test with add_base=True.""" - key = debug.qenum_key(QFrame, QFrame.Sunken, add_base=True) - assert key == 'QFrame.Sunken' - - -def test_int_noklass(): - """Test passing an int without explicit klass given.""" - with pytest.raises(TypeError): - debug.qenum_key(QFrame, 42) - - -def test_int(): - """Test passing an int with explicit klass given.""" - key = debug.qenum_key(QFrame, 0x0030, klass=QFrame.Shadow) - assert key == 'Sunken' - - -def test_unknown(): - """Test passing an unknown value.""" - key = debug.qenum_key(QFrame, 0x1337, klass=QFrame.Shadow) - assert key == '0x1337' diff --git a/tests/utils/debug/test_qflags_key.py b/tests/utils/debug/test_qflags_key.py deleted file mode 100644 index 6a2a85069..000000000 --- a/tests/utils/debug/test_qflags_key.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2014-2015 Florian Bruhin (The Compiler) -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -"""Tests for qutebrowser.utils.debug.qflags_key. - -https://github.com/The-Compiler/qutebrowser/issues/42 -""" - -import pytest - -from PyQt5.QtCore import Qt -from qutebrowser.utils import debug - - -fixme = pytest.mark.xfail(reason="See issue #42", raises=AssertionError) - - -@fixme -def test_single(): - """Test with single value.""" - flags = debug.qflags_key(Qt, Qt.AlignTop) - assert flags == 'AlignTop' - - -@fixme -def test_multiple(): - """Test with multiple values.""" - flags = debug.qflags_key(Qt, Qt.AlignLeft | Qt.AlignTop) - assert flags == 'AlignLeft|AlignTop' - - -def test_combined(): - """Test with a combined value.""" - flags = debug.qflags_key(Qt, Qt.AlignCenter) - assert flags == 'AlignHCenter|AlignVCenter' - - -@fixme -def test_add_base(): - """Test with add_base=True.""" - flags = debug.qflags_key(Qt, Qt.AlignTop, add_base=True) - assert flags == 'Qt.AlignTop' - - -def test_int_noklass(): - """Test passing an int without explicit klass given.""" - with pytest.raises(TypeError): - debug.qflags_key(Qt, 42) - - -@fixme -def test_int(): - """Test passing an int with explicit klass given.""" - flags = debug.qflags_key(Qt, 0x0021, klass=Qt.Alignment) - assert flags == 'AlignLeft|AlignTop' - - -def test_unknown(): - """Test passing an unknown value.""" - flags = debug.qflags_key(Qt, 0x1100, klass=Qt.Alignment) - assert flags == '0x0100|0x1000' diff --git a/tests/utils/debug/test_signal.py b/tests/utils/debug/test_signal.py deleted file mode 100644 index 58b1c13d9..000000000 --- a/tests/utils/debug/test_signal.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2014-2015 Florian Bruhin (The Compiler) -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -"""Test signal debug output functions.""" - -import pytest - -from qutebrowser.utils import debug - - -@pytest.fixture -def signal(stubs): - """Fixture to provide a faked pyqtSignal.""" - return stubs.FakeSignal() - - -def test_signal_name(signal): - """Test signal_name().""" - assert debug.signal_name(signal) == 'fake' - - -def test_dbg_signal(signal): - """Test dbg_signal().""" - assert debug.dbg_signal(signal, [23, 42]) == 'fake(23, 42)' - - -def test_dbg_signal_eliding(signal): - """Test eliding in dbg_signal().""" - dbg_signal = debug.dbg_signal(signal, ['x' * 201]) - assert dbg_signal == "fake('{}\u2026)".format('x' * 198) - - -def test_dbg_signal_newline(signal): - """Test dbg_signal() with a newline.""" - dbg_signal = debug.dbg_signal(signal, ['foo\nbar']) - assert dbg_signal == r"fake('foo\nbar')" diff --git a/tests/utils/test_debug.py b/tests/utils/test_debug.py new file mode 100644 index 000000000..0ff7a7e00 --- /dev/null +++ b/tests/utils/test_debug.py @@ -0,0 +1,173 @@ +# Copyright 2014-2015 Florian Bruhin (The Compiler) +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Tests for qutebrowser.utils.debug.""" + +import logging +import re +import time + +import pytest +from PyQt5.QtCore import pyqtSignal, Qt, QEvent, QObject +from PyQt5.QtWidgets import QStyle, QFrame + +from qutebrowser.utils import debug + + +@debug.log_events +class EventObject(QObject): + + pass + + +def test_log_events(qapp, caplog): + obj = EventObject() + qapp.postEvent(obj, QEvent(QEvent.User)) + qapp.processEvents() + records = caplog.records() + assert len(records) == 1 + assert records[0].msg == 'Event in test_debug.EventObject: User' + + +class SignalObject(QObject): + + signal1 = pyqtSignal() + signal2 = pyqtSignal(str, str) + + def __repr__(self): + """This is not a nice thing to do, but it makes our tests easier.""" + return '' + + +@debug.log_signals +class DecoratedSignalObject(SignalObject): + + pass + + +@pytest.fixture(params=[(SignalObject, True), (DecoratedSignalObject, False)]) +def signal_obj(request): + klass, wrap = request.param + if wrap: + debug.log_signals(klass) + return klass() + + +def test_log_signals(caplog, signal_obj): + signal_obj.signal1.emit() + signal_obj.signal2.emit('foo', 'bar') + + records = caplog.records() + assert len(records) == 2 + assert records[0].msg == 'Signal in : signal1()' + assert records[1].msg == "Signal in : signal2('foo', 'bar')" + + +def test_log_time(caplog): + logger_name = 'qt-tests' + + with caplog.atLevel(logging.DEBUG, logger_name): + with debug.log_time(logging.getLogger(logger_name), action='foobar'): + time.sleep(0.1) + + records = caplog.records() + assert len(records) == 1 + + pattern = re.compile(r'^Foobar took ([\d.]*) seconds\.$') + match = pattern.match(records[0].msg) + assert match + + duration = float(match.group(1)) + assert 0 < duration < 1 + + +class TestQEnumKey: + + def test_metaobj(self): + """Make sure the classes we use in the tests have a metaobj or not. + + If Qt/PyQt even changes and our tests wouldn't test the full + functionality of qenum_key because of that, this test will tell us. + """ + assert not hasattr(QStyle.PrimitiveElement, 'staticMetaObject') + assert hasattr(QFrame, 'staticMetaObject') + + @pytest.mark.parametrize('base, value, klass, expected', [ + (QStyle, QStyle.PE_PanelButtonCommand, None, 'PE_PanelButtonCommand'), + (QFrame, QFrame.Sunken, None, 'Sunken'), + (QFrame, 0x0030, QFrame.Shadow, 'Sunken'), + (QFrame, 0x1337, QFrame.Shadow, '0x1337'), + ]) + def test_qenum_key(self, base, value, klass, expected): + key = debug.qenum_key(base, value, klass=klass) + assert key == expected + + def test_add_base(self): + key = debug.qenum_key(QFrame, QFrame.Sunken, add_base=True) + assert key == 'QFrame.Sunken' + + def test_int_noklass(self): + """Test passing an int without explicit klass given.""" + with pytest.raises(TypeError): + debug.qenum_key(QFrame, 42) + + +class TestQFlagsKey: + + """Tests for qutebrowser.utils.debug.qflags_key. + + https://github.com/The-Compiler/qutebrowser/issues/42 + """ + + fixme = pytest.mark.xfail(reason="See issue #42", raises=AssertionError) + + @pytest.mark.parametrize('base, value, klass, expected', [ + fixme((Qt, Qt.AlignTop, None, 'AlignTop')), + fixme((Qt, Qt.AlignLeft | Qt.AlignTop, None, 'AlignLeft|AlignTop')), + (Qt, Qt.AlignCenter, None, 'AlignHCenter|AlignVCenter'), + fixme((Qt, 0x0021, Qt.Alignment, 'AlignLeft|AlignTop')), + (Qt, 0x1100, Qt.Alignment, '0x0100|0x1000'), + ]) + def test_qflags_key(self, base, value, klass, expected): + flags = debug.qflags_key(base, value, klass=klass) + assert flags == expected + + @fixme + def test_add_base(self): + """Test with add_base=True.""" + flags = debug.qflags_key(Qt, Qt.AlignTop, add_base=True) + assert flags == 'Qt.AlignTop' + + def test_int_noklass(self): + """Test passing an int without explicit klass given.""" + with pytest.raises(TypeError): + debug.qflags_key(Qt, 42) + + +def test_signal_name(stubs): + assert debug.signal_name(stubs.FakeSignal()) == 'fake' + + +@pytest.mark.parametrize('args, expected', [ + ([23, 42], 'fake(23, 42)'), + (['x' * 201], "fake('{}\u2026)".format('x' * 198)), + (['foo\nbar'], r"fake('foo\nbar')"), +]) +def test_dbg_signal(stubs, args, expected): + assert debug.dbg_signal(stubs.FakeSignal(), args) == expected