Various unittest fixes and improvements.

This commit is contained in:
Florian Bruhin 2015-02-27 12:43:54 +01:00
parent 072210c47b
commit 84643b4a39
4 changed files with 62 additions and 80 deletions

View File

@ -25,6 +25,7 @@ import logging
from qutebrowser.browser import http
from qutebrowser.test import stubs
from qutebrowser.utils import log
DEFAULT_NAME = 'qutebrowser-download'
@ -48,7 +49,8 @@ class AttachmentTestCase(unittest.TestCase):
def _check_ignored(self, header):
"""Check if the passed header is ignored."""
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
with self.assertLogs(log.rfc6266, logging.ERROR):
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertTrue(cd_inline)
@ -93,7 +95,8 @@ class InlineTests(unittest.TestCase):
This is invalid syntax, thus the header should be ignored.
"""
self._check_ignored('"inline"')
with self.assertLogs(log.rfc6266, logging.ERROR):
self._check_ignored('"inline"')
def test_inlwithasciifilename(self):
"""'inline', specifying a filename of foo.html
@ -891,15 +894,5 @@ class OurTests(AttachmentTestCase):
'foo bar.html')
def setUpModule():
"""Disable logging."""
logging.disable(logging.ERROR)
def tearDownModule():
"""Restore logging."""
logging.disable(logging.NOTSET)
if __name__ == '__main__':
unittest.main()

View File

@ -29,7 +29,7 @@ from PyQt5.QtCore import Qt
from qutebrowser.keyinput import basekeyparser
from qutebrowser.test import stubs, helpers
from qutebrowser.utils import objreg
from qutebrowser.utils import objreg, log
CONFIG = {'input': {'timeout': 100}}
@ -47,17 +47,6 @@ fake_keyconfig = mock.Mock(spec=['get_bindings_for'])
fake_keyconfig.get_bindings_for.side_effect = lambda s: BINDINGS[s]
def setUpModule():
"""Mock out some imports in basekeyparser."""
basekeyparser.QObject = mock.Mock()
logging.disable(logging.WARNING)
def tearDownModule():
"""Restore mocked out stuff."""
logging.disable(logging.NOTSET)
class SplitCountTests(unittest.TestCase):
"""Test the _split_count method.
@ -101,13 +90,14 @@ class SplitCountTests(unittest.TestCase):
self.assertEqual(self.kp._split_count(), (None, '10foo'))
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer',
new=stubs.FakeTimer)
class ReadConfigTests(unittest.TestCase):
"""Test reading the config."""
def setUp(self):
objreg.register('key-config', fake_keyconfig)
basekeyparser.usertypes.Timer = mock.Mock()
def tearDown(self):
objreg.delete('key-config')
@ -132,6 +122,8 @@ class ReadConfigTests(unittest.TestCase):
self.assertIn('ctrl+x', kp.special_bindings)
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer',
new=stubs.FakeTimer)
class SpecialKeysTests(unittest.TestCase):
"""Check execute() with special keys.
@ -141,15 +133,13 @@ class SpecialKeysTests(unittest.TestCase):
"""
def setUp(self):
patcher = mock.patch(
'qutebrowser.keyinput.basekeyparser.usertypes.Timer',
autospec=True)
patcher.start()
objreg.register('key-config', fake_keyconfig)
self.addCleanup(patcher.stop)
self.kp = basekeyparser.BaseKeyParser(0)
self.kp.execute = mock.Mock()
self.kp.read_config('test')
with self.assertLogs(log.keyboard, logging.WARNING):
# Ignoring keychain 'ccc' in mode 'test' because keychains are not
# supported there.
self.kp.read_config('test')
def tearDown(self):
objreg.delete('key-config')
@ -173,20 +163,19 @@ class SpecialKeysTests(unittest.TestCase):
self.assertFalse(self.kp.execute.called)
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer',
new=stubs.FakeTimer)
class KeyChainTests(unittest.TestCase):
"""Test execute() with keychain support.
Attributes:
kp: The BaseKeyParser to be tested.
timermock: The mock to be used as timer.
"""
def setUp(self):
"""Set up mocks and read the test config."""
objreg.register('key-config', fake_keyconfig)
self.timermock = mock.Mock()
basekeyparser.usertypes.Timer = mock.Mock(return_value=self.timermock)
self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True,
supports_count=False)
self.kp.execute = mock.Mock()
@ -222,22 +211,20 @@ class KeyChainTests(unittest.TestCase):
def test_ambigious_keychain(self):
"""Test ambigious keychain."""
basekeyparser.config = stubs.ConfigStub(CONFIG)
timer = self.kp._ambigious_timer
self.assertFalse(timer.isActive())
# We start with 'a' where the keychain gives us an ambigious result.
# Then we check if the timer has been set up correctly
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.assertFalse(self.kp.execute.called)
basekeyparser.usertypes.Timer.assert_called_once_with(
self.kp, 'ambigious-match')
self.timermock.setSingleShot.assert_called_once_with(True)
self.timermock.setInterval.assert_called_once_with(100)
self.assertTrue(self.timermock.timeout.connect.called)
self.assertFalse(self.timermock.stop.called)
self.timermock.start.assert_called_once_with()
self.assertTrue(timer.isSingleShot())
self.assertEqual(timer.interval(), 100)
self.assertTrue(timer.isActive())
# Now we type an 'x' and check 'ax' has been executed and the timer
# stopped.
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x'))
self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None)
self.timermock.stop.assert_called_once_with()
self.assertFalse(timer.isActive())
self.assertEqual(self.kp._keystring, '')
def test_invalid_keychain(self):
@ -247,13 +234,14 @@ class KeyChainTests(unittest.TestCase):
self.assertEqual(self.kp._keystring, '')
@mock.patch('qutebrowser.keyinput.basekeyparser.usertypes.Timer',
new=stubs.FakeTimer)
class CountTests(unittest.TestCase):
"""Test execute() with counts."""
def setUp(self):
objreg.register('key-config', fake_keyconfig)
basekeyparser.usertypes.Timer = mock.Mock()
self.kp = basekeyparser.BaseKeyParser(0, supports_chains=True,
supports_count=True)
self.kp.execute = mock.Mock()

View File

@ -24,7 +24,6 @@
import os
import os.path
import unittest
import logging
from unittest import mock
from PyQt5.QtCore import QProcess
@ -33,18 +32,8 @@ from qutebrowser.misc import editor
from qutebrowser.test import stubs
def setUpModule():
"""Disable logging and mock out some imports."""
logging.disable(logging.INFO)
editor.message = mock.Mock()
editor.QProcess = stubs.FakeQProcess
def tearDownModule():
"""Restore logging."""
logging.disable(logging.NOTSET)
@mock.patch('qutebrowser.misc.editor.QProcess',
new_callable=stubs.FakeQProcess)
class ArgTests(unittest.TestCase):
"""Test argument handling.
@ -56,14 +45,14 @@ class ArgTests(unittest.TestCase):
def setUp(self):
self.editor = editor.ExternalEditor(0)
def test_simple_start_args(self):
def test_simple_start_args(self, _proc_mock):
"""Test starting editor without arguments."""
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}})
self.editor.edit("")
self.editor._proc.start.assert_called_with("bin", [])
def test_start_args(self):
def test_start_args(self, _proc_mock):
"""Test starting editor with static arguments."""
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo', 'bar'],
@ -71,17 +60,17 @@ class ArgTests(unittest.TestCase):
self.editor.edit("")
self.editor._proc.start.assert_called_with("bin", ["foo", "bar"])
def test_placeholder(self):
def test_placeholder(self, _proc_mock):
"""Test starting editor with placeholder argument."""
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo', '{}', 'bar'],
'editor-encoding': 'utf-8'}})
self.editor.edit("")
filename = self.editor._filename
self.editor._proc.start.assert_called_with("bin",
["foo", filename, "bar"])
self.editor._proc.start.assert_called_with(
"bin", ["foo", filename, "bar"])
def test_in_arg_placeholder(self):
def test_in_arg_placeholder(self, _proc_mock):
"""Test starting editor with placeholder argument inside argument."""
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo{}bar'],
@ -93,6 +82,8 @@ class ArgTests(unittest.TestCase):
self.editor._cleanup() # pylint: disable=protected-access
@mock.patch('qutebrowser.misc.editor.QProcess',
new_callable=stubs.FakeQProcess)
class FileHandlingTests(unittest.TestCase):
"""Test creation/deletion of tempfile.
@ -106,7 +97,7 @@ class FileHandlingTests(unittest.TestCase):
editor.config = stubs.ConfigStub(
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
def test_file_handling_closed_ok(self):
def test_file_handling_closed_ok(self, _proc_mock):
"""Test file handling when closing with an exitstatus == 0."""
self.editor.edit("")
filename = self.editor._filename
@ -114,7 +105,7 @@ class FileHandlingTests(unittest.TestCase):
self.editor.on_proc_closed(0, QProcess.NormalExit)
self.assertFalse(os.path.exists(filename))
def test_file_handling_closed_error(self):
def test_file_handling_closed_error(self, _proc_mock):
"""Test file handling when closing with an exitstatus != 0."""
self.editor.edit("")
filename = self.editor._filename
@ -122,7 +113,7 @@ class FileHandlingTests(unittest.TestCase):
self.editor.on_proc_closed(1, QProcess.NormalExit)
self.assertFalse(os.path.exists(filename))
def test_file_handling_closed_crash(self):
def test_file_handling_closed_crash(self, _proc_mock):
"""Test file handling when closing with a crash."""
self.editor.edit("")
filename = self.editor._filename
@ -132,6 +123,8 @@ class FileHandlingTests(unittest.TestCase):
self.assertFalse(os.path.exists(filename))
@mock.patch('qutebrowser.misc.editor.QProcess',
new_callable=stubs.FakeQProcess)
class TextModifyTests(unittest.TestCase):
"""Tests to test if the text gets saved/loaded correctly.
@ -167,7 +160,7 @@ class TextModifyTests(unittest.TestCase):
data = f.read()
return data
def test_empty_input(self):
def test_empty_input(self, _proc_mock):
"""Test if an empty input gets modified correctly."""
self.editor.edit("")
self.assertEqual(self._read(), "")
@ -175,7 +168,7 @@ class TextModifyTests(unittest.TestCase):
self.editor.on_proc_closed(0, QProcess.NormalExit)
self.editor.editing_finished.emit.assert_called_with("Hello")
def test_simple_input(self):
def test_simple_input(self, _proc_mock):
"""Test if an empty input gets modified correctly."""
self.editor.edit("Hello")
self.assertEqual(self._read(), "Hello")
@ -183,7 +176,7 @@ class TextModifyTests(unittest.TestCase):
self.editor.on_proc_closed(0, QProcess.NormalExit)
self.editor.editing_finished.emit.assert_called_with("World")
def test_umlaut(self):
def test_umlaut(self, _proc_mock):
"""Test if umlauts works correctly."""
self.editor.edit("Hällö Wörld")
self.assertEqual(self._read(), "Hällö Wörld")
@ -191,7 +184,7 @@ class TextModifyTests(unittest.TestCase):
self.editor.on_proc_closed(0, QProcess.NormalExit)
self.editor.editing_finished.emit.assert_called_with("Überprüfung")
def test_unicode(self):
def test_unicode(self, _proc_mock):
"""Test if other UTF8 chars work correctly."""
self.editor.edit("\u2603") # Unicode snowman
self.assertEqual(self._read(), "\u2603")
@ -200,6 +193,9 @@ class TextModifyTests(unittest.TestCase):
self.editor.editing_finished.emit.assert_called_with("\u2601")
@mock.patch('qutebrowser.misc.editor.QProcess',
new_callable=stubs.FakeQProcess)
@mock.patch('qutebrowser.misc.editor.message', autospec=True)
class ErrorMessageTests(unittest.TestCase):
"""Test if statusbar error messages get emitted correctly.
@ -215,17 +211,17 @@ class ErrorMessageTests(unittest.TestCase):
editor.config = stubs.ConfigStub(
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
def test_proc_error(self):
def test_proc_error(self, msg_mock, _proc_mock):
"""Test on_proc_error."""
self.editor.edit("")
self.editor.on_proc_error(QProcess.Crashed)
self.assertTrue(editor.message.error.called)
self.assertTrue(msg_mock.error.called)
def test_proc_return(self):
def test_proc_return(self, msg_mock, _proc_mock):
"""Test on_proc_finished with a bad exit status."""
self.editor.edit("")
self.editor.on_proc_closed(1, QProcess.NormalExit)
self.assertTrue(editor.message.error.called)
self.assertTrue(msg_mock.error.called)
if __name__ == '__main__':

View File

@ -27,6 +27,7 @@ from PyQt5.QtCore import QPoint, QProcess
from PyQt5.QtNetwork import QNetworkRequest
from qutebrowser.config import configexc
from qutebrowser.utils import usertypes
class ConfigStub:
@ -178,11 +179,11 @@ class FakeNetworkReply:
self.headers[key] = value
class FakeQProcess:
class FakeQProcess(mock.Mock):
"""QProcess stub.
Gets some enum values from the real QProcess and uses mocks for signals.
Gets some enum values from the real QProcess.
"""
NormalExit = QProcess.NormalExit
@ -195,11 +196,6 @@ class FakeQProcess:
ReadError = QProcess.ReadError
UnknownError = QProcess.UnknownError
def __init__(self, parent=None): # pylint: disable=unused-argument
self.finished = mock.Mock()
self.error = mock.Mock()
self.start = mock.Mock()
class FakeSignal:
@ -223,3 +219,12 @@ class FakeCommand:
def __init__(self, desc):
self.desc = desc
class FakeTimer(usertypes.Timer):
"""Stub for a usertypes.Timer."""
def __init__(self, parent=None, name=None):
super().__init__(parent, name)
self.blockSignals(True)