Converted test_basekeyparser to pytest

This commit is contained in:
Bruno Oliveira 2015-04-04 12:29:17 -03:00
parent 9128ac41cb
commit 7e7a1b7b28
4 changed files with 140 additions and 139 deletions

View File

@ -62,3 +62,22 @@ def webpage():
nam = page.networkAccessManager() nam = page.networkAccessManager()
nam.setNetworkAccessible(QNetworkAccessManager.NotAccessible) nam.setNetworkAccessible(QNetworkAccessManager.NotAccessible)
return page return page
@pytest.fixture
def fake_keyevent_factory():
"""
Fixture that when called will return a mock instance of a QKeyEvent.
"""
from unittest import mock
from PyQt5.QtGui import QKeyEvent
def fake_keyevent(key, modifiers=0, text=''):
"""Generate a new fake QKeyPressEvent."""
evtmock = mock.create_autospec(QKeyEvent, instance=True)
evtmock.key.return_value = key
evtmock.modifiers.return_value = modifiers
evtmock.text.return_value = text
return evtmock
return fake_keyevent

View File

@ -21,9 +21,6 @@
import logging import logging
import contextlib import contextlib
from unittest import mock
from PyQt5.QtGui import QKeyEvent
@contextlib.contextmanager @contextlib.contextmanager
@ -36,15 +33,6 @@ def disable_logger(name):
logging.getLogger(name).propagate = True logging.getLogger(name).propagate = True
def fake_keyevent(key, modifiers=0, text=''):
"""Generate a new fake QKeyPressEvent."""
evtmock = mock.create_autospec(QKeyEvent, instance=True)
evtmock.key.return_value = key
evtmock.modifiers.return_value = modifiers
evtmock.text.return_value = text
return evtmock
class MessageModule: class MessageModule:
"""A drop-in replacement for qutebrowser.utils.message.""" """A drop-in replacement for qutebrowser.utils.message."""

View File

@ -22,13 +22,12 @@
"""Tests for BaseKeyParser.""" """Tests for BaseKeyParser."""
import logging import logging
import unittest
from unittest import mock from unittest import mock
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
import pytest
from qutebrowser.keyinput import basekeyparser from qutebrowser.keyinput import basekeyparser
from qutebrowser.test import stubs, helpers
from qutebrowser.utils import objreg, log from qutebrowser.utils import objreg, log
@ -43,11 +42,28 @@ BINDINGS = {'test': {'<Ctrl-a>': 'ctrla',
'test2': {'foo': 'bar', '<Ctrl+X>': 'ctrlx'}} 'test2': {'foo': 'bar', '<Ctrl+X>': 'ctrlx'}}
fake_keyconfig = mock.Mock(spec=['get_bindings_for']) @pytest.yield_fixture
fake_keyconfig.get_bindings_for.side_effect = lambda s: BINDINGS[s] def fake_keyconfig():
"""
Creates a mock of a KeyConfiguration and registers it into objreg.
"""
fake_keyconfig = mock.Mock(spec=['get_bindings_for'])
fake_keyconfig.get_bindings_for.side_effect = lambda s: BINDINGS[s]
objreg.register('key-config', fake_keyconfig)
yield
objreg.delete('key-config')
class SplitCountTests(unittest.TestCase): @pytest.fixture
def mock_timer(mocker, stubs):
"""Mocks the QTimer class used by the
"qutebrowser.keyinput.basekeyparser.usertypes" module with a stub version.
"""
mocker.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer',
new=stubs.FakeTimer)
class TestSplitCount:
"""Test the _split_count method. """Test the _split_count method.
@ -55,57 +71,51 @@ class SplitCountTests(unittest.TestCase):
kp: The BaseKeyParser we're testing. kp: The BaseKeyParser we're testing.
""" """
def setUp(self): @pytest.fixture(autouse=True)
def setup(self):
self.kp = basekeyparser.BaseKeyParser(0, supports_count=True) self.kp = basekeyparser.BaseKeyParser(0, supports_count=True)
def test_onlycount(self): def test_onlycount(self):
"""Test split_count with only a count.""" """Test split_count with only a count."""
self.kp._keystring = '10' self.kp._keystring = '10'
self.assertEqual(self.kp._split_count(), (10, '')) assert self.kp._split_count() == (10, '')
def test_normalcount(self): def test_normalcount(self):
"""Test split_count with count and text.""" """Test split_count with count and text."""
self.kp._keystring = '10foo' self.kp._keystring = '10foo'
self.assertEqual(self.kp._split_count(), (10, 'foo')) assert self.kp._split_count() == (10, 'foo')
def test_minuscount(self): def test_minuscount(self):
"""Test split_count with a negative count.""" """Test split_count with a negative count."""
self.kp._keystring = '-1foo' self.kp._keystring = '-1foo'
self.assertEqual(self.kp._split_count(), (None, '-1foo')) assert self.kp._split_count() == (None, '-1foo')
def test_expcount(self): def test_expcount(self):
"""Test split_count with an exponential count.""" """Test split_count with an exponential count."""
self.kp._keystring = '10e4foo' self.kp._keystring = '10e4foo'
self.assertEqual(self.kp._split_count(), (10, 'e4foo')) assert self.kp._split_count() == (10, 'e4foo')
def test_nocount(self): def test_nocount(self):
"""Test split_count with only a command.""" """Test split_count with only a command."""
self.kp._keystring = 'foo' self.kp._keystring = 'foo'
self.assertEqual(self.kp._split_count(), (None, 'foo')) assert self.kp._split_count() == (None, 'foo')
def test_nosupport(self): def test_nosupport(self):
"""Test split_count with a count when counts aren't supported.""" """Test split_count with a count when counts aren't supported."""
self.kp._supports_count = False self.kp._supports_count = False
self.kp._keystring = '10foo' self.kp._keystring = '10foo'
self.assertEqual(self.kp._split_count(), (None, '10foo')) assert self.kp._split_count() == (None, '10foo')
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer', @pytest.mark.usefixtures('fake_keyconfig', 'mock_timer')
new=stubs.FakeTimer) class TestReadConfig:
class ReadConfigTests(unittest.TestCase):
"""Test reading the config.""" """Test reading the config."""
def setUp(self):
objreg.register('key-config', fake_keyconfig)
def tearDown(self):
objreg.delete('key-config')
def test_read_config_invalid(self): def test_read_config_invalid(self):
"""Test reading config without setting it before.""" """Test reading config without setting it before."""
kp = basekeyparser.BaseKeyParser(0) kp = basekeyparser.BaseKeyParser(0)
with self.assertRaises(ValueError): with pytest.raises(ValueError):
kp.read_config() kp.read_config()
def test_read_config_valid(self): def test_read_config_valid(self):
@ -113,18 +123,17 @@ class ReadConfigTests(unittest.TestCase):
kp = basekeyparser.BaseKeyParser(0, supports_count=True, kp = basekeyparser.BaseKeyParser(0, supports_count=True,
supports_chains=True) supports_chains=True)
kp.read_config('test') kp.read_config('test')
self.assertIn('ccc', kp.bindings) assert 'ccc' in kp.bindings
self.assertIn('ctrl+a', kp.special_bindings) assert 'ctrl+a' in kp.special_bindings
kp.read_config('test2') kp.read_config('test2')
self.assertNotIn('ccc', kp.bindings) assert 'ccc' not in kp.bindings
self.assertNotIn('ctrl+a', kp.special_bindings) assert 'ctrl+a' not in kp.special_bindings
self.assertIn('foo', kp.bindings) assert 'foo' in kp.bindings
self.assertIn('ctrl+x', kp.special_bindings) assert 'ctrl+x' in kp.special_bindings
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer', @pytest.mark.usefixtures('mock_timer')
new=stubs.FakeTimer) class TestSpecialKeys:
class SpecialKeysTests(unittest.TestCase):
"""Check execute() with special keys. """Check execute() with special keys.
@ -132,40 +141,36 @@ class SpecialKeysTests(unittest.TestCase):
kp: The BaseKeyParser to be tested. kp: The BaseKeyParser to be tested.
""" """
def setUp(self): @pytest.fixture(autouse=True)
objreg.register('key-config', fake_keyconfig) def setup(self, caplog, fake_keyconfig):
self.kp = basekeyparser.BaseKeyParser(0) self.kp = basekeyparser.BaseKeyParser(0)
self.kp.execute = mock.Mock() self.kp.execute = mock.Mock()
with self.assertLogs(log.keyboard, logging.WARNING): with caplog.atLevel(logging.WARNING, log.keyboard.name):
# Ignoring keychain 'ccc' in mode 'test' because keychains are not # Ignoring keychain 'ccc' in mode 'test' because keychains are not
# supported there. # supported there.
self.kp.read_config('test') self.kp.read_config('test')
def tearDown(self): def test_valid_key(self, fake_keyevent_factory):
objreg.delete('key-config')
def test_valid_key(self):
"""Test a valid special keyevent.""" """Test a valid special keyevent."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier)) self.kp.handle(fake_keyevent_factory(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier)) self.kp.handle(fake_keyevent_factory(Qt.Key_X, Qt.ControlModifier))
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special) self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
def test_invalid_key(self): def test_invalid_key(self, fake_keyevent_factory):
"""Test an invalid special keyevent.""" """Test an invalid special keyevent."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier | self.kp.handle(fake_keyevent_factory(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier))) Qt.AltModifier)))
self.assertFalse(self.kp.execute.called) assert not self.kp.execute.called
def test_keychain(self): def test_keychain(self, fake_keyevent_factory):
"""Test a keychain.""" """Test a keychain."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_B)) self.kp.handle(fake_keyevent_factory(Qt.Key_B))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A)) self.kp.handle(fake_keyevent_factory(Qt.Key_A))
self.assertFalse(self.kp.execute.called) assert not self.kp.execute.called
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer', @pytest.mark.usefixtures('mock_timer')
new=stubs.FakeTimer) class TestKeyChain:
class KeyChainTests(unittest.TestCase):
"""Test execute() with keychain support. """Test execute() with keychain support.
@ -173,127 +178,116 @@ class KeyChainTests(unittest.TestCase):
kp: The BaseKeyParser to be tested. kp: The BaseKeyParser to be tested.
""" """
def setUp(self): @pytest.fixture(autouse=True)
def setup(self, fake_keyconfig):
"""Set up mocks and read the test config.""" """Set up mocks and read the test config."""
objreg.register('key-config', fake_keyconfig)
self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True, self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True,
supports_count=False) supports_count=False)
self.kp.execute = mock.Mock() self.kp.execute = mock.Mock()
self.kp.read_config('test') self.kp.read_config('test')
def tearDown(self): def test_valid_special_key(self, fake_keyevent_factory):
objreg.delete('key-config')
def test_valid_special_key(self):
"""Test valid special key.""" """Test valid special key."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier)) self.kp.handle(fake_keyevent_factory(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier)) self.kp.handle(fake_keyevent_factory(Qt.Key_X, Qt.ControlModifier))
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special) self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_invalid_special_key(self): def test_invalid_special_key(self, fake_keyevent_factory):
"""Test invalid special key.""" """Test invalid special key."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier | self.kp.handle(fake_keyevent_factory(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier))) Qt.AltModifier)))
self.assertFalse(self.kp.execute.called) assert not self.kp.execute.called
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_keychain(self): def test_keychain(self, fake_keyevent_factory):
"""Test valid keychain.""" """Test valid keychain."""
# Press 'x' which is ignored because of no match # Press 'x' which is ignored because of no match
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x')) self.kp.handle(fake_keyevent_factory(Qt.Key_X, text='x'))
# Then start the real chain # Then start the real chain
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None) self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
@mock.patch('qutebrowser.keyinput.basekeyparser.config', def test_ambigious_keychain(self, fake_keyevent_factory, mocker, stubs):
new=stubs.ConfigStub(CONFIG))
def test_ambigious_keychain(self):
"""Test ambigious keychain.""" """Test ambigious keychain."""
mocker.patch('qutebrowser.keyinput.basekeyparser.config',
new=stubs.ConfigStub(CONFIG))
timer = self.kp._ambigious_timer timer = self.kp._ambigious_timer
self.assertFalse(timer.isActive()) assert not timer.isActive()
# We start with 'a' where the keychain gives us an ambigious result. # We start with 'a' where the keychain gives us an ambigious result.
# Then we check if the timer has been set up correctly # Then we check if the timer has been set up correctly
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='a'))
self.assertFalse(self.kp.execute.called) assert not self.kp.execute.called
self.assertTrue(timer.isSingleShot()) assert timer.isSingleShot()
self.assertEqual(timer.interval(), 100) assert timer.interval() == 100
self.assertTrue(timer.isActive()) assert timer.isActive()
# Now we type an 'x' and check 'ax' has been executed and the timer # Now we type an 'x' and check 'ax' has been executed and the timer
# stopped. # stopped.
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x')) self.kp.handle(fake_keyevent_factory(Qt.Key_X, text='x'))
self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None) self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None)
self.assertFalse(timer.isActive()) assert not timer.isActive()
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_invalid_keychain(self): def test_invalid_keychain(self, fake_keyevent_factory):
"""Test invalid keychain.""" """Test invalid keychain."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_C, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_C, text='c'))
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer', @pytest.mark.usefixtures('mock_timer')
new=stubs.FakeTimer) class TestCount:
class CountTests(unittest.TestCase):
"""Test execute() with counts.""" """Test execute() with counts."""
def setUp(self): @pytest.fixture(autouse=True)
objreg.register('key-config', fake_keyconfig) def setup(self, fake_keyconfig):
self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True, self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True,
supports_count=True) supports_count=True)
self.kp.execute = mock.Mock() self.kp.execute = mock.Mock()
self.kp.read_config('test') self.kp.read_config('test')
def test_no_count(self): def test_no_count(self, fake_keyevent_factory):
"""Test with no count added.""" """Test with no count added."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None) self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_count_0(self): def test_count_0(self, fake_keyevent_factory):
"""Test with count=0.""" """Test with count=0."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_0, text='0')) self.kp.handle(fake_keyevent_factory(Qt.Key_0, text='0'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 0) self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 0)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_count_42(self): def test_count_42(self, fake_keyevent_factory):
"""Test with count=42.""" """Test with count=42."""
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4')) self.kp.handle(fake_keyevent_factory(Qt.Key_4, text='4'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2')) self.kp.handle(fake_keyevent_factory(Qt.Key_2, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 42) self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 42)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def test_count_42_invalid(self): def test_count_42_invalid(self, fake_keyevent_factory):
"""Test with count=42 and invalid command.""" """Test with count=42 and invalid command."""
# Invalid call with ccx gets ignored # Invalid call with ccx gets ignored
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4')) self.kp.handle(fake_keyevent_factory(Qt.Key_4, text='4'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2')) self.kp.handle(fake_keyevent_factory(Qt.Key_2, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='x')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='x'))
self.assertFalse(self.kp.execute.called) assert not self.kp.execute.called
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
# Valid call with ccc gets the correct count # Valid call with ccc gets the correct count
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='2')) self.kp.handle(fake_keyevent_factory(Qt.Key_4, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='3')) self.kp.handle(fake_keyevent_factory(Qt.Key_2, text='3'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_B, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c')) self.kp.handle(fake_keyevent_factory(Qt.Key_A, text='c'))
self.kp.execute.assert_called_once_with('ccc', self.kp.Type.chain, 23) self.kp.execute.assert_called_once_with('ccc', self.kp.Type.chain, 23)
self.assertEqual(self.kp._keystring, '') assert self.kp._keystring == ''
def tearDown(self):
objreg.global_registry.clear()
if __name__ == '__main__':
unittest.main()

View File

@ -257,7 +257,7 @@ class FakeTimer(QObject):
def setSingleShot(self, singleshot): def setSingleShot(self, singleshot):
self._singleshot = singleshot self._singleshot = singleshot
def singleShot(self): def isSingleShot(self):
return self._singleshot return self._singleshot
def start(self): def start(self):