From 8398fe3bdd8a69dc7204f75687b07217b01836fd Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 8 May 2015 00:06:55 +0200 Subject: [PATCH 1/5] Rewrite test_log.py to use pytest. See #660. --- tests/utils/test_log.py | 316 +++++++++++++++++++++------------------- 1 file changed, 163 insertions(+), 153 deletions(-) diff --git a/tests/utils/test_log.py b/tests/utils/test_log.py index d52adf552..d86707d80 100644 --- a/tests/utils/test_log.py +++ b/tests/utils/test_log.py @@ -22,231 +22,241 @@ """Tests for qutebrowser.utils.log.""" import logging -import unittest import argparse +import itertools import sys -from unittest import mock + +import pytest +from PyQt5.QtCore import qWarning from qutebrowser.utils import log -from PyQt5.QtCore import qWarning - -class BaseTest(unittest.TestCase): - - """Base class for logging tests. +@pytest.yield_fixture(autouse=True) +def restore_loggers(): + """Fixture to save/restore the logging state. Based on CPython's Lib/test/test_logging.py. """ + logger_dict = logging.getLogger().manager.loggerDict + logging._acquireLock() + try: + saved_handlers = logging._handlers.copy() + saved_handler_list = logging._handlerList[:] + saved_loggers = saved_loggers = logger_dict.copy() + saved_name_to_level = logging._nameToLevel.copy() + saved_level_to_name = logging._levelToName.copy() + logger_states = {} + for name in saved_loggers: + logger_states[name] = getattr(saved_loggers[name], 'disabled', + None) + finally: + logging._releaseLock() - def setUp(self): - """Save the old logging configuration.""" + root_logger = logging.getLogger("") + root_handlers = root_logger.handlers[:] + original_logging_level = root_logger.getEffectiveLevel() + + yield + + while root_logger.handlers: + h = root_logger.handlers[0] + root_logger.removeHandler(h) + h.close() + root_logger.setLevel(original_logging_level) + for h in root_handlers: + root_logger.addHandler(h) + logging._acquireLock() + try: + logging._levelToName.clear() + logging._levelToName.update(saved_level_to_name) + logging._nameToLevel.clear() + logging._nameToLevel.update(saved_name_to_level) + logging._handlers.clear() + logging._handlers.update(saved_handlers) + logging._handlerList[:] = saved_handler_list logger_dict = logging.getLogger().manager.loggerDict - logging._acquireLock() - try: - self.saved_handlers = logging._handlers.copy() - self.saved_handler_list = logging._handlerList[:] - self.saved_loggers = saved_loggers = logger_dict.copy() - self.saved_name_to_level = logging._nameToLevel.copy() - self.saved_level_to_name = logging._levelToName.copy() - self.logger_states = {} - for name in saved_loggers: - self.logger_states[name] = getattr(saved_loggers[name], - 'disabled', None) - finally: - logging._releaseLock() - - self.root_logger = logging.getLogger("") - self.root_handlers = self.root_logger.handlers[:] - self.original_logging_level = self.root_logger.getEffectiveLevel() - - def tearDown(self): - """Restore the original logging configuration.""" - while self.root_logger.handlers: - h = self.root_logger.handlers[0] - self.root_logger.removeHandler(h) - h.close() - self.root_logger.setLevel(self.original_logging_level) - for h in self.root_handlers: - self.root_logger.addHandler(h) - logging._acquireLock() - try: - logging._levelToName.clear() - logging._levelToName.update(self.saved_level_to_name) - logging._nameToLevel.clear() - logging._nameToLevel.update(self.saved_name_to_level) - logging._handlers.clear() - logging._handlers.update(self.saved_handlers) - logging._handlerList[:] = self.saved_handler_list - logger_dict = logging.getLogger().manager.loggerDict - logger_dict.clear() - logger_dict.update(self.saved_loggers) - logger_states = self.logger_states - for name in self.logger_states: - if logger_states[name] is not None: - self.saved_loggers[name].disabled = logger_states[name] - finally: - logging._releaseLock() + logger_dict.clear() + logger_dict.update(saved_loggers) + logger_states = logger_states + for name in logger_states: + if logger_states[name] is not None: + saved_loggers[name].disabled = logger_states[name] + finally: + logging._releaseLock() -class LogFilterTests(unittest.TestCase): +@pytest.fixture(scope='session') +def log_counter(): + """Counter for logger fixture to get unique loggers.""" + return itertools.count() - """Tests for LogFilter. - Attributes: - logger: The logger we use to create records. +@pytest.fixture +def logger(log_counter): + """Fixture which provides a logger for tests. + + Unique throwaway loggers are used to make sure the tests don't influence + each other. """ + i = next(log_counter) + return logging.getLogger('qutebrowser-unittest-logger-{}'.format(i)) - def setUp(self): - self.logger = logging.getLogger("foo") - def _make_record(self, name, level=logging.DEBUG): +class TestLogFilter: + + """Tests for LogFilter.""" + + def _make_record(self, logger, name, level=logging.DEBUG): """Create a bogus logging record with the supplied logger name.""" - return self.logger.makeRecord(name, level=level, fn=None, lno=0, - msg="", args=None, exc_info=None) + return logger.makeRecord(name, level=level, fn=None, lno=0, msg="", + args=None, exc_info=None) - def test_empty(self): + def test_empty(self, logger): """Test if an empty filter lets all messages through.""" logfilter = log.LogFilter(None) - record = self._make_record("eggs.bacon.spam") - self.assertTrue(logfilter.filter(record)) - record = self._make_record("eggs") - self.assertTrue(logfilter.filter(record)) + record = self._make_record(logger, "eggs.bacon.spam") + assert logfilter.filter(record) + record = self._make_record(logger, "eggs") + assert logfilter.filter(record) - def test_matching(self): + def test_matching(self, logger): """Test if a filter lets an exactly matching log record through.""" logfilter = log.LogFilter(["eggs", "bacon"]) - record = self._make_record("eggs") - self.assertTrue(logfilter.filter(record)) - record = self._make_record("bacon") - self.assertTrue(logfilter.filter(record)) - record = self._make_record("spam") - self.assertFalse(logfilter.filter(record)) + record = self._make_record(logger, "eggs") + assert logfilter.filter(record) + record = self._make_record(logger, "bacon") + assert logfilter.filter(record) + record = self._make_record(logger, "spam") + assert not logfilter.filter(record) logfilter = log.LogFilter(["eggs.bacon"]) - record = self._make_record("eggs.bacon") - self.assertTrue(logfilter.filter(record)) + record = self._make_record(logger, "eggs.bacon") + assert logfilter.filter(record) - def test_equal_start(self): + def test_equal_start(self, logger): """Test if a filter blocks a logger which looks equal but isn't.""" logfilter = log.LogFilter(["eggs"]) - record = self._make_record("eggsauce") - self.assertFalse(logfilter.filter(record)) + record = self._make_record(logger, "eggsauce") + assert not logfilter.filter(record) logfilter = log.LogFilter("eggs.bacon") - record = self._make_record("eggs.baconstrips") - self.assertFalse(logfilter.filter(record)) + record = self._make_record(logger, "eggs.baconstrips") + assert not logfilter.filter(record) - def test_child(self): + def test_child(self, logger): """Test if a filter lets through a logger which is a child.""" logfilter = log.LogFilter(["eggs.bacon", "spam.ham"]) - record = self._make_record("eggs.bacon.spam") - self.assertTrue(logfilter.filter(record)) - record = self._make_record("spam.ham.salami") - self.assertTrue(logfilter.filter(record)) + record = self._make_record(logger, "eggs.bacon.spam") + assert logfilter.filter(record) + record = self._make_record(logger, "spam.ham.salami") + assert logfilter.filter(record) - def test_debug(self): + def test_debug(self, logger): """Test if messages more important than debug are never filtered.""" logfilter = log.LogFilter(["eggs"]) # First check if the filter works as intended with debug messages - record = self._make_record("eggs") - self.assertTrue(logfilter.filter(record)) - record = self._make_record("bacon") - self.assertFalse(logfilter.filter(record)) + record = self._make_record(logger, "eggs") + assert logfilter.filter(record) + record = self._make_record(logger, "bacon") + assert not logfilter.filter(record) # Then check if info is not filtered - record = self._make_record("eggs", level=logging.INFO) - self.assertTrue(logfilter.filter(record)) - record = self._make_record("bacon", level=logging.INFO) - self.assertTrue(logfilter.filter(record)) + record = self._make_record(logger, "eggs", level=logging.INFO) + assert logfilter.filter(record) + record = self._make_record(logger, "bacon", level=logging.INFO) + assert logfilter.filter(record) -class RAMHandlerTests(BaseTest): +class TestRAMHandler: - """Tests for RAMHandler. + """Tests for RAMHandler.""" - Attributes: - logger: The logger we use to log to the handler. - handler: The RAMHandler we're testing. - old_level: The level the root logger had before executing the test. - old_handlers: The handlers the root logger had before executing the - test. - """ + @pytest.fixture + def handler(self, logger): + """Fixture providing a RAMHandler.""" + handler = log.RAMHandler(capacity=2) + handler.setLevel(logging.NOTSET) + logger.addHandler(handler) + return handler - def setUp(self): - super().setUp() - self.logger = logging.getLogger() - self.logger.handlers = [] - self.logger.setLevel(logging.NOTSET) - self.handler = log.RAMHandler(capacity=2) - self.handler.setLevel(logging.NOTSET) - self.logger.addHandler(self.handler) - - def test_filled(self): + def test_filled(self, handler, logger): """Test handler with exactly as much records as it can hold.""" - self.logger.debug("One") - self.logger.debug("Two") - self.assertEqual(len(self.handler._data), 2) - self.assertEqual(self.handler._data[0].msg, "One") - self.assertEqual(self.handler._data[1].msg, "Two") + logger.debug("One") + logger.debug("Two") + assert len(handler._data) == 2 + assert handler._data[0].msg == "One" + assert handler._data[1].msg == "Two" - def test_overflow(self): + def test_overflow(self, handler, logger): """Test handler with more records as it can hold.""" - self.logger.debug("One") - self.logger.debug("Two") - self.logger.debug("Three") - self.assertEqual(len(self.handler._data), 2) - self.assertEqual(self.handler._data[0].msg, "Two") - self.assertEqual(self.handler._data[1].msg, "Three") + logger.debug("One") + logger.debug("Two") + logger.debug("Three") + assert len(handler._data) == 2 + assert handler._data[0].msg == "Two" + assert handler._data[1].msg == "Three" - def test_dump_log(self): + def test_dump_log(self, handler, logger): """Test dump_log().""" - self.logger.debug("One") - self.logger.debug("Two") - self.logger.debug("Three") - self.assertEqual(self.handler.dump_log(), "Two\nThree") + logger.debug("One") + logger.debug("Two") + logger.debug("Three") + assert handler.dump_log() == "Two\nThree" -@mock.patch('qutebrowser.utils.log.qInstallMessageHandler', autospec=True) -class InitLogTests(BaseTest): +class TestInitLog: """Tests for init_log.""" - def setUp(self): - super().setUp() - self.args = argparse.Namespace(debug=True, loglevel=logging.DEBUG, - color=True, loglines=10, logfilter="") + @pytest.fixture(autouse=True) + def setup(self, mocker): + """Mock out qInstallMessageHandler.""" + mocker.patch('qutebrowser.utils.log.qInstallMessageHandler', + autospec=True) - def test_stderr_none(self, _mock): + @pytest.fixture + def args(self): + """Fixture providing an argparse namespace.""" + return argparse.Namespace(debug=True, loglevel=logging.DEBUG, + color=True, loglines=10, logfilter="") + + def test_stderr_none(self, args): """Test init_log with sys.stderr = None.""" old_stderr = sys.stderr sys.stderr = None - log.init_log(self.args) + log.init_log(args) sys.stderr = old_stderr -class HideQtWarningTests(BaseTest): +class TestHideQtWarning: """Tests for hide_qt_warning/QtWarningFilter.""" - def test_unfiltered(self): + def test_unfiltered(self, caplog): """Test a message which is not filtered.""" with log.hide_qt_warning("World", logger='qt-tests'): - with self.assertLogs('qt-tests', logging.WARNING): + with caplog.atLevel(logging.WARNING, logger='qt-tests'): qWarning("Hello World") + assert len(caplog.records()) == 1 + record = caplog.records()[0] + assert record.levelname == 'WARNING' + assert record.message == "Hello World" - def test_filtered_exact(self): + def test_filtered_exact(self, caplog): """Test a message which is filtered (exact match).""" with log.hide_qt_warning("Hello", logger='qt-tests'): - qWarning("Hello") + with caplog.atLevel(logging.WARNING, logger='qt-tests'): + qWarning("Hello") + assert not caplog.records() - def test_filtered_start(self): + def test_filtered_start(self, caplog): """Test a message which is filtered (match at line start).""" with log.hide_qt_warning("Hello", logger='qt-tests'): - qWarning("Hello World") + with caplog.atLevel(logging.WARNING, logger='qt-tests'): + qWarning("Hello World") + assert not caplog.records() - def test_filtered_whitespace(self): + def test_filtered_whitespace(self, caplog): """Test a message which is filtered (match with whitespace).""" with log.hide_qt_warning("Hello", logger='qt-tests'): - qWarning(" Hello World ") - - -if __name__ == '__main__': - unittest.main() + with caplog.atLevel(logging.WARNING, logger='qt-tests'): + qWarning(" Hello World ") + assert not caplog.records() From 021c94eece3ad9f7303c00d6c75a8fd1c538be3d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 7 May 2015 22:57:19 +0200 Subject: [PATCH 2/5] Rewrite test_enum.py to use pytest. See #660. --- tests/utils/usertypes/test_enum.py | 63 +++++++++++++----------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/tests/utils/usertypes/test_enum.py b/tests/utils/usertypes/test_enum.py index ed9b6fb09..e1443b7be 100644 --- a/tests/utils/usertypes/test_enum.py +++ b/tests/utils/usertypes/test_enum.py @@ -19,45 +19,38 @@ """Tests for the Enum class.""" -import unittest - from qutebrowser.utils import usertypes +import pytest + # FIXME: Add some more tests, e.g. for is_int -class EnumTests(unittest.TestCase): - - """Test simple enums. - - Attributes: - enum: The enum we're testing. - """ - - def setUp(self): - self.enum = usertypes.enum('Enum', ['one', 'two']) - - def test_values(self): - """Test if enum members resolve to the right values.""" - self.assertEqual(self.enum.one.value, 1) - self.assertEqual(self.enum.two.value, 2) - - def test_name(self): - """Test .name mapping.""" - self.assertEqual(self.enum.one.name, 'one') - self.assertEqual(self.enum.two.name, 'two') - - def test_unknown(self): - """Test invalid values which should raise an AttributeError.""" - with self.assertRaises(AttributeError): - _ = self.enum.three - - def test_start(self): - """Test the start= argument.""" - e = usertypes.enum('Enum', ['three', 'four'], start=3) - self.assertEqual(e.three.value, 3) - self.assertEqual(e.four.value, 4) +@pytest.fixture +def enum(): + return usertypes.enum('Enum', ['one', 'two']) -if __name__ == '__main__': - unittest.main() +def test_values(enum): + """Test if enum members resolve to the right values.""" + assert enum.one.value == 1 + assert enum.two.value == 2 + + +def test_name(enum): + """Test .name mapping.""" + assert enum.one.name == 'one' + assert enum.two.name == 'two' + + +def test_unknown(enum): + """Test invalid values which should raise an AttributeError.""" + with pytest.raises(AttributeError): + _ = enum.three + + +def test_start(): + """Test the start= argument.""" + e = usertypes.enum('Enum', ['three', 'four'], start=3) + assert e.three.value == 3 + assert e.four.value == 4 From 392fb3e1d705a62b6371c91020a219030a910d0e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 10 May 2015 15:25:04 +0200 Subject: [PATCH 3/5] Rewrite test_neighborlist.py to use pytest. See #660. --- tests/utils/usertypes/test_neighborlist.py | 427 ++++++++++----------- 1 file changed, 197 insertions(+), 230 deletions(-) diff --git a/tests/utils/usertypes/test_neighborlist.py b/tests/utils/usertypes/test_neighborlist.py index ebde77a60..41e4f547a 100644 --- a/tests/utils/usertypes/test_neighborlist.py +++ b/tests/utils/usertypes/test_neighborlist.py @@ -21,364 +21,331 @@ """Tests for the NeighborList class.""" -import unittest - from qutebrowser.utils import usertypes +import pytest -class InitTests(unittest.TestCase): - """Just try to init some neighborlists. +class TestInit: - Attributes: - nl: The NeighborList we're testing. - """ + """Just try to init some neighborlists.""" def test_empty(self): """Test constructing an empty NeighborList.""" nl = usertypes.NeighborList() - self.assertEqual(nl.items, []) + assert nl.items == [] def test_items(self): """Test constructing an NeighborList with items.""" nl = usertypes.NeighborList([1, 2, 3]) - self.assertEqual(nl.items, [1, 2, 3]) + assert nl.items == [1, 2, 3] def test_len(self): """Test len() on NeighborList.""" nl = usertypes.NeighborList([1, 2, 3]) - self.assertEqual(len(nl), 3) + assert len(nl) == 3 def test_contains(self): """Test 'in' on NeighborList.""" nl = usertypes.NeighborList([1, 2, 3]) - self.assertIn(2, nl) - self.assertNotIn(4, nl) + assert 2 in nl + assert 4 not in nl -class DefaultTests(unittest.TestCase): +class TestDefaultArg: - """Test the default argument. - - Attributes: - nl: The NeighborList we're testing. - """ + """Test the default argument.""" def test_simple(self): """Test default with a numeric argument.""" nl = usertypes.NeighborList([1, 2, 3], default=2) - self.assertEqual(nl._idx, 1) + assert nl._idx == 1 def test_none(self): """Test default 'None'.""" nl = usertypes.NeighborList([1, 2, None], default=None) - self.assertEqual(nl._idx, 2) + assert nl._idx == 2 def test_unset(self): """Test unset default value.""" nl = usertypes.NeighborList([1, 2, 3]) - self.assertIsNone(nl._idx) + assert nl._idx is None -class EmptyTests(unittest.TestCase): +class TestEmpty: - """Tests with no items. + """Tests with no items.""" - Attributes: - nl: The NeighborList we're testing. - """ + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList() - def setUp(self): - self.nl = usertypes.NeighborList() - - def test_curitem(self): + def test_curitem(self, neighborlist): """Test curitem with no item.""" - with self.assertRaises(IndexError): - self.nl.curitem() + with pytest.raises(IndexError): + neighborlist.curitem() - def test_firstitem(self): + def test_firstitem(self, neighborlist): """Test firstitem with no item.""" - with self.assertRaises(IndexError): - self.nl.firstitem() + with pytest.raises(IndexError): + neighborlist.firstitem() - def test_lastitem(self): + def test_lastitem(self, neighborlist): """Test lastitem with no item.""" - with self.assertRaises(IndexError): - self.nl.lastitem() + with pytest.raises(IndexError): + neighborlist.lastitem() - def test_getitem(self): + def test_getitem(self, neighborlist): """Test getitem with no item.""" - with self.assertRaises(IndexError): - self.nl.getitem(1) + with pytest.raises(IndexError): + neighborlist.getitem(1) -class ItemTests(unittest.TestCase): +class TestItems: - """Tests with items. + """Tests with items.""" - Attributes: - nl: The NeighborList we're testing. - """ + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList([1, 2, 3, 4, 5], default=3) - def setUp(self): - self.nl = usertypes.NeighborList([1, 2, 3, 4, 5], default=3) - - def test_curitem(self): + def test_curitem(self, neighborlist): """Test curitem().""" - self.assertEqual(self.nl._idx, 2) - self.assertEqual(self.nl.curitem(), 3) - self.assertEqual(self.nl._idx, 2) + assert neighborlist._idx == 2 + assert neighborlist.curitem() == 3 + assert neighborlist._idx == 2 - def test_nextitem(self): + def test_nextitem(self, neighborlist): """Test nextitem().""" - self.assertEqual(self.nl.nextitem(), 4) - self.assertEqual(self.nl._idx, 3) - self.assertEqual(self.nl.nextitem(), 5) - self.assertEqual(self.nl._idx, 4) + assert neighborlist.nextitem() == 4 + assert neighborlist._idx == 3 + assert neighborlist.nextitem() == 5 + assert neighborlist._idx == 4 - def test_previtem(self): + def test_previtem(self, neighborlist): """Test previtem().""" - self.assertEqual(self.nl.previtem(), 2) - self.assertEqual(self.nl._idx, 1) - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 0) + assert neighborlist.previtem() == 2 + assert neighborlist._idx == 1 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 0 - def test_firstitem(self): + def test_firstitem(self, neighborlist): """Test firstitem().""" - self.assertEqual(self.nl.firstitem(), 1) - self.assertEqual(self.nl._idx, 0) + assert neighborlist.firstitem() == 1 + assert neighborlist._idx == 0 - def test_lastitem(self): + def test_lastitem(self, neighborlist): """Test lastitem().""" - self.assertEqual(self.nl.lastitem(), 5) - self.assertEqual(self.nl._idx, 4) + assert neighborlist.lastitem() == 5 + assert neighborlist._idx == 4 - def test_reset(self): + def test_reset(self, neighborlist): """Test reset().""" - self.nl.nextitem() - self.assertEqual(self.nl._idx, 3) - self.nl.reset() - self.assertEqual(self.nl._idx, 2) + neighborlist.nextitem() + assert neighborlist._idx == 3 + neighborlist.reset() + assert neighborlist._idx == 2 - def test_getitem(self): + def test_getitem(self, neighborlist): """Test getitem().""" - self.assertEqual(self.nl.getitem(2), 5) - self.assertEqual(self.nl._idx, 4) - self.nl.reset() - self.assertEqual(self.nl.getitem(-2), 1) - self.assertEqual(self.nl._idx, 0) + assert neighborlist.getitem(2) == 5 + assert neighborlist._idx == 4 + neighborlist.reset() + assert neighborlist.getitem(-2) == 1 + assert neighborlist._idx == 0 -class OneTests(unittest.TestCase): +class TestSingleItem: - """Tests with a list with only one item. + """Tests with a list with only one item.""" - Attributes: - nl: The NeighborList we're testing. - """ + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList([1], default=1) - def setUp(self): - self.nl = usertypes.NeighborList([1], default=1) - - def test_first_wrap(self): + def test_first_wrap(self, neighborlist): """Test out of bounds previtem() with mode=wrap.""" - self.nl._mode = usertypes.NeighborList.Modes.wrap - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.wrap + neighborlist.firstitem() + assert neighborlist._idx == 0 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 0 - def test_first_block(self): + def test_first_block(self, neighborlist): """Test out of bounds previtem() with mode=block.""" - self.nl._mode = usertypes.NeighborList.Modes.block - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.block + neighborlist.firstitem() + assert neighborlist._idx == 0 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 0 - def test_first_raise(self): + def test_first_raise(self, neighborlist): """Test out of bounds previtem() with mode=raise.""" - self.nl._mode = usertypes.NeighborList.Modes.exception - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - with self.assertRaises(IndexError): - self.nl.previtem() - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.exception + neighborlist.firstitem() + assert neighborlist._idx == 0 + with pytest.raises(IndexError): + neighborlist.previtem() + assert neighborlist._idx == 0 - def test_last_wrap(self): + def test_last_wrap(self, neighborlist): """Test out of bounds nextitem() with mode=wrap.""" - self.nl._mode = usertypes.NeighborList.Modes.wrap - self.nl.lastitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.nextitem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.wrap + neighborlist.lastitem() + assert neighborlist._idx == 0 + assert neighborlist.nextitem() == 1 + assert neighborlist._idx == 0 - def test_last_block(self): + def test_last_block(self, neighborlist): """Test out of bounds nextitem() with mode=block.""" - self.nl._mode = usertypes.NeighborList.Modes.block - self.nl.lastitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.nextitem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.block + neighborlist.lastitem() + assert neighborlist._idx == 0 + assert neighborlist.nextitem() == 1 + assert neighborlist._idx == 0 - def test_last_raise(self): + def test_last_raise(self, neighborlist): """Test out of bounds nextitem() with mode=raise.""" - self.nl._mode = usertypes.NeighborList.Modes.exception - self.nl.lastitem() - self.assertEqual(self.nl._idx, 0) - with self.assertRaises(IndexError): - self.nl.nextitem() - self.assertEqual(self.nl._idx, 0) + neighborlist._mode = usertypes.NeighborList.Modes.exception + neighborlist.lastitem() + assert neighborlist._idx == 0 + with pytest.raises(IndexError): + neighborlist.nextitem() + assert neighborlist._idx == 0 -class BlockTests(unittest.TestCase): +class TestBlockMode: - """Tests with mode=block. + """Tests with mode=block.""" - Attributes: - nl: The NeighborList we're testing. - """ - - def setUp(self): - self.nl = usertypes.NeighborList( + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList( [1, 2, 3, 4, 5], default=3, mode=usertypes.NeighborList.Modes.block) - def test_first(self): + def test_first(self, neighborlist): """Test out of bounds previtem().""" - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist.firstitem() + assert neighborlist._idx == 0 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 0 - def test_last(self): + def test_last(self, neighborlist): """Test out of bounds nextitem().""" - self.nl.lastitem() - self.assertEqual(self.nl._idx, 4) - self.assertEqual(self.nl.nextitem(), 5) - self.assertEqual(self.nl._idx, 4) + neighborlist.lastitem() + assert neighborlist._idx == 4 + assert neighborlist.nextitem() == 5 + assert neighborlist._idx == 4 -class WrapTests(unittest.TestCase): +class TestWrapMode: - """Tests with mode=wrap. + """Tests with mode=wrap.""" - Attributes: - nl: The NeighborList we're testing. - """ - - def setUp(self): - self.nl = usertypes.NeighborList( + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList( [1, 2, 3, 4, 5], default=3, mode=usertypes.NeighborList.Modes.wrap) - def test_first(self): + def test_first(self, neighborlist): """Test out of bounds previtem().""" - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - self.assertEqual(self.nl.previtem(), 5) - self.assertEqual(self.nl._idx, 4) + neighborlist.firstitem() + assert neighborlist._idx == 0 + assert neighborlist.previtem() == 5 + assert neighborlist._idx == 4 - def test_last(self): + def test_last(self, neighborlist): """Test out of bounds nextitem().""" - self.nl.lastitem() - self.assertEqual(self.nl._idx, 4) - self.assertEqual(self.nl.nextitem(), 1) - self.assertEqual(self.nl._idx, 0) + neighborlist.lastitem() + assert neighborlist._idx == 4 + assert neighborlist.nextitem() == 1 + assert neighborlist._idx == 0 -class RaiseTests(unittest.TestCase): +class TestExceptionMode: - """Tests with mode=exception. + """Tests with mode=exception.""" - Attributes: - nl: The NeighborList we're testing. - """ - - def setUp(self): - self.nl = usertypes.NeighborList( + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList( [1, 2, 3, 4, 5], default=3, mode=usertypes.NeighborList.Modes.exception) - def test_first(self): + def test_first(self, neighborlist): """Test out of bounds previtem().""" - self.nl.firstitem() - self.assertEqual(self.nl._idx, 0) - with self.assertRaises(IndexError): - self.nl.previtem() - self.assertEqual(self.nl._idx, 0) + neighborlist.firstitem() + assert neighborlist._idx == 0 + with pytest.raises(IndexError): + neighborlist.previtem() + assert neighborlist._idx == 0 - def test_last(self): + def test_last(self, neighborlist): """Test out of bounds nextitem().""" - self.nl.lastitem() - self.assertEqual(self.nl._idx, 4) - with self.assertRaises(IndexError): - self.nl.nextitem() - self.assertEqual(self.nl._idx, 4) + neighborlist.lastitem() + assert neighborlist._idx == 4 + with pytest.raises(IndexError): + neighborlist.nextitem() + assert neighborlist._idx == 4 -class SnapInTests(unittest.TestCase): +class TestSnapIn: - """Tests for the fuzzyval/_snap_in features. + """Tests for the fuzzyval/_snap_in features.""" - Attributes: - nl: The NeighborList we're testing. - """ + @pytest.fixture + def neighborlist(self): + return usertypes.NeighborList([20, 9, 1, 5]) - def setUp(self): - self.nl = usertypes.NeighborList([20, 9, 1, 5]) - - def test_bigger(self): + def test_bigger(self, neighborlist): """Test fuzzyval with snapping to a bigger value.""" - self.nl.fuzzyval = 7 - self.assertEqual(self.nl.nextitem(), 9) - self.assertEqual(self.nl._idx, 1) - self.assertEqual(self.nl.nextitem(), 1) - self.assertEqual(self.nl._idx, 2) + neighborlist.fuzzyval = 7 + assert neighborlist.nextitem() == 9 + assert neighborlist._idx == 1 + assert neighborlist.nextitem() == 1 + assert neighborlist._idx == 2 - def test_smaller(self): + def test_smaller(self, neighborlist): """Test fuzzyval with snapping to a smaller value.""" - self.nl.fuzzyval = 7 - self.assertEqual(self.nl.previtem(), 5) - self.assertEqual(self.nl._idx, 3) - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 2) + neighborlist.fuzzyval = 7 + assert neighborlist.previtem() == 5 + assert neighborlist._idx == 3 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 2 - def test_equal_bigger(self): + def test_equal_bigger(self, neighborlist): """Test fuzzyval with matching value, snapping to a bigger value.""" - self.nl.fuzzyval = 20 - self.assertEqual(self.nl.nextitem(), 9) - self.assertEqual(self.nl._idx, 1) + neighborlist.fuzzyval = 20 + assert neighborlist.nextitem() == 9 + assert neighborlist._idx == 1 - def test_equal_smaller(self): + def test_equal_smaller(self, neighborlist): """Test fuzzyval with matching value, snapping to a smaller value.""" - self.nl.fuzzyval = 5 - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 2) + neighborlist.fuzzyval = 5 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 2 - def test_too_big_next(self): + def test_too_big_next(self, neighborlist): """Test fuzzyval/next with a value bigger than any in the list.""" - self.nl.fuzzyval = 30 - self.assertEqual(self.nl.nextitem(), 20) - self.assertEqual(self.nl._idx, 0) + neighborlist.fuzzyval = 30 + assert neighborlist.nextitem() == 20 + assert neighborlist._idx == 0 - def test_too_big_prev(self): + def test_too_big_prev(self, neighborlist): """Test fuzzyval/prev with a value bigger than any in the list.""" - self.nl.fuzzyval = 30 - self.assertEqual(self.nl.previtem(), 20) - self.assertEqual(self.nl._idx, 0) + neighborlist.fuzzyval = 30 + assert neighborlist.previtem() == 20 + assert neighborlist._idx == 0 - def test_too_small_next(self): + def test_too_small_next(self, neighborlist): """Test fuzzyval/next with a value smaller than any in the list.""" - self.nl.fuzzyval = 0 - self.assertEqual(self.nl.nextitem(), 1) - self.assertEqual(self.nl._idx, 2) + neighborlist.fuzzyval = 0 + assert neighborlist.nextitem() == 1 + assert neighborlist._idx == 2 - def test_too_small_prev(self): + def test_too_small_prev(self, neighborlist): """Test fuzzyval/prev with a value smaller than any in the list.""" - self.nl.fuzzyval = 0 - self.assertEqual(self.nl.previtem(), 1) - self.assertEqual(self.nl._idx, 2) - - -if __name__ == '__main__': - unittest.main() + neighborlist.fuzzyval = 0 + assert neighborlist.previtem() == 1 + assert neighborlist._idx == 2 From db0a54b03fd61eaa52f06669914d24652f32ec9d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 10 May 2015 15:27:35 +0200 Subject: [PATCH 4/5] Rewrite test_crashdialog.py to use pytest. See #660. --- tests/misc/test_crashdialog.py | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/tests/misc/test_crashdialog.py b/tests/misc/test_crashdialog.py index 6c93833b1..ae0078c99 100644 --- a/tests/misc/test_crashdialog.py +++ b/tests/misc/test_crashdialog.py @@ -19,8 +19,6 @@ """Tests for qutebrowser.misc.crashdialog.""" -import unittest - from qutebrowser.misc import crashdialog @@ -52,7 +50,7 @@ Hello world! """ -class ParseFatalStacktraceTests(unittest.TestCase): +class TestParseFatalStacktrace: """Tests for parse_fatal_stacktrace.""" @@ -60,30 +58,22 @@ class ParseFatalStacktraceTests(unittest.TestCase): """Test parse_fatal_stacktrace with a valid text.""" text = VALID_CRASH_TEXT.strip().replace('_', ' ') typ, func = crashdialog.parse_fatal_stacktrace(text) - self.assertEqual(typ, "Segmentation fault") - self.assertEqual(func, 'testfunc') + assert (typ, func) == ("Segmentation fault", 'testfunc') def test_valid_text_thread(self): """Test parse_fatal_stacktrace with a valid text #2.""" text = VALID_CRASH_TEXT_THREAD.strip().replace('_', ' ') typ, func = crashdialog.parse_fatal_stacktrace(text) - self.assertEqual(typ, "Segmentation fault") - self.assertEqual(func, 'testfunc') + assert (typ, func) == ("Segmentation fault", 'testfunc') def test_valid_text_empty(self): """Test parse_fatal_stacktrace with a valid text but empty function.""" text = VALID_CRASH_TEXT_EMPTY.strip().replace('_', ' ') typ, func = crashdialog.parse_fatal_stacktrace(text) - self.assertEqual(typ, 'Aborted') - self.assertEqual(func, '') + assert (typ, func) == ('Aborted', '') def test_invalid_text(self): """Test parse_fatal_stacktrace with an invalid text.""" text = INVALID_CRASH_TEXT.strip().replace('_', ' ') typ, func = crashdialog.parse_fatal_stacktrace(text) - self.assertEqual(typ, '') - self.assertEqual(func, '') - - -if __name__ == '__main__': - unittest.main() + assert (typ, func) == ('', '') From 452e03f9af6a7f4cf96fcbb18bfd002815fb5653 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 10 May 2015 15:53:24 +0200 Subject: [PATCH 5/5] Rewrite test_lineparser.py to use pytest. See #660. --- tests/misc/test_lineparser.py | 136 ++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 63 deletions(-) diff --git a/tests/misc/test_lineparser.py b/tests/misc/test_lineparser.py index c473eda50..87bc9b287 100644 --- a/tests/misc/test_lineparser.py +++ b/tests/misc/test_lineparser.py @@ -23,10 +23,10 @@ import io import os -import unittest -from unittest import mock -from qutebrowser.misc import lineparser +import pytest + +from qutebrowser.misc import lineparser as lineparsermod class LineParserWrapper: @@ -71,116 +71,126 @@ class LineParserWrapper: self._test_save_prepared = True -class TestableAppendLineParser(LineParserWrapper, lineparser.AppendLineParser): +class TestableAppendLineParser(LineParserWrapper, + lineparsermod.AppendLineParser): """Wrapper over AppendLineParser to make it testable.""" pass -class TestableLineParser(LineParserWrapper, lineparser.LineParser): +class TestableLineParser(LineParserWrapper, lineparsermod.LineParser): """Wrapper over LineParser to make it testable.""" pass -class TestableLimitLineParser(LineParserWrapper, lineparser.LimitLineParser): +class TestableLimitLineParser(LineParserWrapper, + lineparsermod.LimitLineParser): """Wrapper over LimitLineParser to make it testable.""" pass -@mock.patch('qutebrowser.misc.lineparser.os.path') -@mock.patch('qutebrowser.misc.lineparser.os') -class BaseLineParserTests(unittest.TestCase): +class TestBaseLineParser: """Tests for BaseLineParser.""" - def setUp(self): - self._confdir = "this really doesn't matter" - self._fname = "and neither does this" - self._lineparser = lineparser.BaseLineParser( - self._confdir, self._fname) + CONFDIR = "this really doesn't matter" + FILENAME = "and neither does this" - def test_prepare_save_existing(self, os_mock, os_path_mock): + @pytest.fixture + def lineparser(self): + """Fixture providing a BaseLineParser.""" + return lineparsermod.BaseLineParser(self.CONFDIR, self.FILENAME) + + def test_prepare_save_existing(self, mocker, lineparser): """Test if _prepare_save does what it's supposed to do.""" - os_path_mock.exists.return_value = True - self._lineparser._prepare_save() - self.assertFalse(os_mock.makedirs.called) + exists_mock = mocker.patch( + 'qutebrowser.misc.lineparser.os.path.exists') + makedirs_mock = mocker.patch('qutebrowser.misc.lineparser.os.makedirs') + exists_mock.return_value = True - def test_prepare_save_missing(self, os_mock, os_path_mock): + lineparser._prepare_save() + assert not makedirs_mock.called + + def test_prepare_save_missing(self, mocker, lineparser): """Test if _prepare_save does what it's supposed to do.""" - os_path_mock.exists.return_value = False - self._lineparser._prepare_save() - os_mock.makedirs.assert_called_with(self._confdir, 0o755) + exists_mock = mocker.patch( + 'qutebrowser.misc.lineparser.os.path.exists') + exists_mock.return_value = False + makedirs_mock = mocker.patch('qutebrowser.misc.lineparser.os.makedirs') + + lineparser._prepare_save() + makedirs_mock.assert_called_with(self.CONFDIR, 0o755) -class AppendLineParserTests(unittest.TestCase): +class TestAppendLineParser: """Tests for AppendLineParser.""" - def setUp(self): - self._lineparser = TestableAppendLineParser('this really', - 'does not matter') - self._lineparser.new_data = ['old data 1', 'old data 2'] - self._expected_data = self._lineparser.new_data - self._lineparser.save() + BASE_DATA = ['old data 1', 'old data 2'] - def _get_expected(self): + @pytest.fixture + def lineparser(self): + """Fixture to get an AppendLineParser for tests.""" + lp = TestableAppendLineParser('this really', 'does not matter') + lp.new_data = self.BASE_DATA + lp.save() + return lp + + def _get_expected(self, new_data): """Get the expected data with newlines.""" - return '\n'.join(self._expected_data) + '\n' + return '\n'.join(self.BASE_DATA + new_data) + '\n' - def test_save(self): + def test_save(self, lineparser): """Test save().""" - self._lineparser.new_data = ['new data 1', 'new data 2'] - self._expected_data += self._lineparser.new_data - self._lineparser.save() - self.assertEqual(self._lineparser._data, self._get_expected()) + new_data = ['new data 1', 'new data 2'] + lineparser.new_data = new_data + lineparser.save() + assert lineparser._data == self._get_expected(new_data) - def test_iter_without_open(self): + def test_iter_without_open(self, lineparser): """Test __iter__ without having called open().""" - with self.assertRaises(ValueError): - iter(self._lineparser) + with pytest.raises(ValueError): + iter(lineparser) - def test_iter(self): + def test_iter(self, lineparser): """Test __iter__.""" - self._lineparser.new_data = ['new data 1', 'new data 2'] - self._expected_data += self._lineparser.new_data - with self._lineparser.open(): - self.assertEqual(list(self._lineparser), self._expected_data) + new_data = ['new data 1', 'new data 2'] + lineparser.new_data = new_data + with lineparser.open(): + assert list(lineparser) == self.BASE_DATA + new_data - @mock.patch('qutebrowser.misc.lineparser.AppendLineParser._open') - def test_iter_not_found(self, open_mock): + def test_iter_not_found(self, mocker): """Test __iter__ with no file.""" + open_mock = mocker.patch( + 'qutebrowser.misc.lineparser.AppendLineParser._open') open_mock.side_effect = FileNotFoundError - linep = lineparser.AppendLineParser('foo', 'bar') - linep.new_data = ['new data 1', 'new data 2'] - expected_data = linep.new_data + new_data = ['new data 1', 'new data 2'] + linep = lineparsermod.AppendLineParser('foo', 'bar') + linep.new_data = new_data with linep.open(): - self.assertEqual(list(linep), expected_data) + assert list(linep) == new_data def test_get_recent_none(self): """Test get_recent with no data.""" linep = TestableAppendLineParser('this really', 'does not matter') - self.assertEqual(linep.get_recent(), []) + assert linep.get_recent() == [] - def test_get_recent_little(self): + def test_get_recent_little(self, lineparser): """Test get_recent with little data.""" - data = [e + '\n' for e in self._expected_data] - self.assertEqual(self._lineparser.get_recent(), data) + data = [e + '\n' for e in self.BASE_DATA] + assert lineparser.get_recent() == data - def test_get_recent_much(self): + def test_get_recent_much(self, lineparser): """Test get_recent with much data.""" size = 64 new_data = ['new data {}'.format(i) for i in range(size)] - self._lineparser.new_data = new_data - self._lineparser.save() - data = '\n'.join(self._expected_data + new_data) + lineparser.new_data = new_data + lineparser.save() + data = '\n'.join(self.BASE_DATA + new_data) data = [e + '\n' for e in data[-(size - 1):].splitlines()] - self.assertEqual(self._lineparser.get_recent(size), data) - - -if __name__ == '__main__': - unittest.main() + assert lineparser.get_recent(size) == data