From b0a131eb1c301026264b46e091bd206cb4ad6139 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 27 May 2014 13:06:13 +0200 Subject: [PATCH] Add docstrings to tests --- .../test/keyinput/test_basekeyparser.py | 60 ++++++++++++- qutebrowser/test/test_helpers.py | 4 + qutebrowser/test/utils/test_editor.py | 36 ++++++-- qutebrowser/test/utils/test_misc.py | 69 +++++++++++++- qutebrowser/test/utils/test_signal.py | 6 +- qutebrowser/test/utils/test_url.py | 51 +++++++++++ qutebrowser/test/utils/test_webelem.py | 34 +++++-- qutebrowser/test/utils/usertypes/test_enum.py | 10 ++- .../test/utils/usertypes/test_fakedict.py | 13 ++- .../test/utils/usertypes/test_neighborlist.py | 89 +++++++++++++++++-- 10 files changed, 341 insertions(+), 31 deletions(-) diff --git a/qutebrowser/test/keyinput/test_basekeyparser.py b/qutebrowser/test/keyinput/test_basekeyparser.py index b15184cd8..5dd6cf185 100644 --- a/qutebrowser/test/keyinput/test_basekeyparser.py +++ b/qutebrowser/test/keyinput/test_basekeyparser.py @@ -30,13 +30,18 @@ from PyQt5.QtCore import Qt def setUpModule(): + """Mock out some imports in basekeyparser.""" basekeyparser.QObject = Mock() logging.disable(logging.ERROR) class ConfigStub: - """Stub for basekeyparser.config.""" + """Stub for basekeyparser.config. + + Class attributes: + DATA: The config data to return. + """ DATA = {'test': {'': 'ctrla', 'a': 'a', @@ -47,11 +52,23 @@ class ConfigStub: 'test2': {'foo': 'bar', '': 'ctrlx'}} def section(self, name): + """Get a section from the config. + + Args: + name: The section name to get. + + Raise: + ValueError if section isn't test1/test2. + + Return: + The section as dict. + """ if name not in ['test', 'test2']: raise ValueError("section called with section '{}'!".format(name)) return self.DATA[name] def get(self, sect, opt): + """Get a value from the config.""" return self.DATA[sect][opt] @@ -73,6 +90,7 @@ class NormalizeTests(TestCase): self.kp = basekeyparser.BaseKeyParser() def test_normalize(self): + """Test normalize with some strings.""" STRINGS = [ ('Control+x', 'Ctrl+X'), ('Windows+x', 'Meta+X'), @@ -87,32 +105,42 @@ class NormalizeTests(TestCase): class SplitCountTests(TestCase): - """Test the _split_count method.""" + """Test the _split_count method. + + Attributes: + kp: The BaseKeyParser we're testing. + """ def setUp(self): self.kp = basekeyparser.BaseKeyParser(supports_count=True) def test_onlycount(self): + """Test split_count with only a count.""" self.kp._keystring = '10' self.assertEqual(self.kp._split_count(), (10, '')) def test_normalcount(self): + """Test split_count with count and text.""" self.kp._keystring = '10foo' self.assertEqual(self.kp._split_count(), (10, 'foo')) def test_minuscount(self): + """Test split_count with a negative count.""" self.kp._keystring = '-1foo' self.assertEqual(self.kp._split_count(), (None, '-1foo')) def test_expcount(self): + """Test split_count with an exponential count.""" self.kp._keystring = '10e4foo' self.assertEqual(self.kp._split_count(), (10, 'e4foo')) def test_nocount(self): + """Test split_count with only a command.""" self.kp._keystring = 'foo' self.assertEqual(self.kp._split_count(), (None, 'foo')) def test_nosupport(self): + """Test split_count with a count when counts aren't supported.""" self.kp._supports_count = False self.kp._keystring = '10foo' self.assertEqual(self.kp._split_count(), (None, '10foo')) @@ -127,11 +155,13 @@ class ReadConfigTests(TestCase): basekeyparser.QTimer = Mock() def test_read_config_invalid(self): + """Test reading config without setting it before.""" kp = basekeyparser.BaseKeyParser() with self.assertRaises(ValueError): kp.read_config() def test_read_config_valid(self): + """Test reading config.""" kp = basekeyparser.BaseKeyParser(supports_count=True, supports_chains=True) kp.read_config('test') @@ -146,7 +176,11 @@ class ReadConfigTests(TestCase): class SpecialKeysTests(TestCase): - """Check execute() with special keys.""" + """Check execute() with special keys. + + Attributes: + kp: The BaseKeyParser to be tested. + """ def setUp(self): basekeyparser.config = ConfigStub() @@ -156,16 +190,19 @@ class SpecialKeysTests(TestCase): self.kp.read_config('test') def test_valid_key(self): + """Test a valid special keyevent.""" self.kp.handle(FakeKeyEvent(Qt.Key_A, Qt.ControlModifier)) self.kp.handle(FakeKeyEvent(Qt.Key_X, Qt.ControlModifier)) self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special) def test_invalid_key(self): + """Test an invalid special keyevent.""" self.kp.handle(FakeKeyEvent(Qt.Key_A, (Qt.ControlModifier | Qt.AltModifier))) self.assertFalse(self.kp.execute.called) def test_keychain(self): + """Test a keychain.""" self.kp.handle(FakeKeyEvent(Qt.Key_B)) self.kp.handle(FakeKeyEvent(Qt.Key_A)) self.assertFalse(self.kp.execute.called) @@ -173,9 +210,15 @@ class SpecialKeysTests(TestCase): class KeyChainTests(TestCase): - """Test execute() with keychain support.""" + """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.""" basekeyparser.config = ConfigStub() self.timermock = Mock() basekeyparser.QTimer = Mock(return_value=self.timermock) @@ -185,18 +228,21 @@ class KeyChainTests(TestCase): self.kp.read_config('test') def test_valid_special_key(self): + """Test valid special key.""" self.kp.handle(FakeKeyEvent(Qt.Key_A, Qt.ControlModifier)) self.kp.handle(FakeKeyEvent(Qt.Key_X, Qt.ControlModifier)) self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special) self.assertEqual(self.kp._keystring, '') def test_invalid_special_key(self): + """Test invalid special key.""" self.kp.handle(FakeKeyEvent(Qt.Key_A, (Qt.ControlModifier | Qt.AltModifier))) self.assertFalse(self.kp.execute.called) self.assertEqual(self.kp._keystring, '') def test_keychain(self): + """Test valid keychain.""" # Press 'x' which is ignored because of no match self.kp.handle(FakeKeyEvent(Qt.Key_X, text='x')) # Then start the real chain @@ -206,6 +252,7 @@ class KeyChainTests(TestCase): self.assertEqual(self.kp._keystring, '') def test_ambigious_keychain(self): + """Test ambigious keychain.""" # 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(FakeKeyEvent(Qt.Key_A, text='a')) @@ -224,6 +271,7 @@ class KeyChainTests(TestCase): self.assertEqual(self.kp._keystring, '') def test_invalid_keychain(self): + """Test invalid keychain.""" self.kp.handle(FakeKeyEvent(Qt.Key_B, text='b')) self.kp.handle(FakeKeyEvent(Qt.Key_C, text='c')) self.assertEqual(self.kp._keystring, '') @@ -242,12 +290,14 @@ class CountTests(TestCase): self.kp.read_config('test') def test_no_count(self): + """Test with no count added.""" self.kp.handle(FakeKeyEvent(Qt.Key_B, text='b')) self.kp.handle(FakeKeyEvent(Qt.Key_A, text='a')) self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None) self.assertEqual(self.kp._keystring, '') def test_count_0(self): + """Test with count=0.""" self.kp.handle(FakeKeyEvent(Qt.Key_0, text='0')) self.kp.handle(FakeKeyEvent(Qt.Key_B, text='b')) self.kp.handle(FakeKeyEvent(Qt.Key_A, text='a')) @@ -255,6 +305,7 @@ class CountTests(TestCase): self.assertEqual(self.kp._keystring, '') def test_count_42(self): + """Test with count=42.""" self.kp.handle(FakeKeyEvent(Qt.Key_4, text='4')) self.kp.handle(FakeKeyEvent(Qt.Key_2, text='2')) self.kp.handle(FakeKeyEvent(Qt.Key_B, text='b')) @@ -263,6 +314,7 @@ class CountTests(TestCase): self.assertEqual(self.kp._keystring, '') def test_count_42_invalid(self): + """Test with count=42 and invalid command.""" # Invalid call with ccx gets ignored self.kp.handle(FakeKeyEvent(Qt.Key_4, text='4')) self.kp.handle(FakeKeyEvent(Qt.Key_2, text='2')) diff --git a/qutebrowser/test/test_helpers.py b/qutebrowser/test/test_helpers.py index bde7fd8fb..c72142b6c 100644 --- a/qutebrowser/test/test_helpers.py +++ b/qutebrowser/test/test_helpers.py @@ -27,13 +27,17 @@ from qutebrowser.test.helpers import environ_set_temp class TestEnvironSetTemp(TestCase): + """Test the environ_set_temp helper.""" + def test_environ_set(self): + """Test environ_set_temp with something which was set already.""" os.environ['QUTEBROWSER_ENVIRON_TEST'] = 'oldval' with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'): self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval') self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'oldval') def test_environ_unset(self): + """Test environ_set_temp with something which wasn't set yet.""" with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'): self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval') self.assertNotIn('QUTEBROWSER_ENVIRON_TEST', os.environ) diff --git a/qutebrowser/test/utils/test_editor.py b/qutebrowser/test/utils/test_editor.py index dfaf9cf6a..c618408f0 100644 --- a/qutebrowser/test/utils/test_editor.py +++ b/qutebrowser/test/utils/test_editor.py @@ -79,7 +79,11 @@ def setUpModule(): class ArgTests(TestCase): - """Test argument handling.""" + """Test argument handling. + + Attributes: + editor: The ExternalEditor instance to test. + """ def setUp(self): self.editor = editor.ExternalEditor() @@ -117,7 +121,11 @@ class ArgTests(TestCase): class FileHandlingTests(TestCase): - """Test creation/deletion of tempfile.""" + """Test creation/deletion of tempfile. + + Attributes: + editor: The ExternalEditor instance to test. + """ def setUp(self): self.editor = editor.ExternalEditor() @@ -151,7 +159,11 @@ class FileHandlingTests(TestCase): class TextModifyTests(TestCase): - """Tests to test if the text gets saved/loaded correctly.""" + """Tests to test if the text gets saved/loaded correctly. + + Attributes: + editor: The ExternalEditor instance to test. + """ def setUp(self): self.editor = editor.ExternalEditor() @@ -159,13 +171,21 @@ class TextModifyTests(TestCase): editor.config = ConfigStub(editor=[""]) def _write(self, text): - """Write a text to the file opened in the fake editor.""" + """Write a text to the file opened in the fake editor. + + Args: + text: The text to write to the file. + """ filename = self.editor.filename with open(filename, 'w', encoding='utf-8') as f: f.write(text) def _read(self): - """Read a text from the file opened in the fake editor.""" + """Read a text from the file opened in the fake editor. + + Return: + The text which was read. + """ filename = self.editor.filename with open(filename, 'r', encoding='utf-8') as f: data = f.read() @@ -206,7 +226,11 @@ class TextModifyTests(TestCase): class ErrorMessageTests(TestCase): - """Test if statusbar error messages get emitted correctly.""" + """Test if statusbar error messages get emitted correctly. + + Attributes: + editor: The ExternalEditor instance to test. + """ def setUp(self): self.editor = editor.ExternalEditor() diff --git a/qutebrowser/test/utils/test_misc.py b/qutebrowser/test/utils/test_misc.py index ef71f9f10..b28d1fb29 100644 --- a/qutebrowser/test/utils/test_misc.py +++ b/qutebrowser/test/utils/test_misc.py @@ -41,22 +41,35 @@ class ElidingTests(TestCase): ELLIPSIS = '\u2026' def test_too_small(self): + """Test eliding to 0 chars which should fail.""" with self.assertRaises(ValueError): utils.elide('foo', 0) def test_length_one(self): + """Test eliding to 1 char which should yield ...""" self.assertEqual(utils.elide('foo', 1), self.ELLIPSIS) def test_fits(self): + """Test eliding with a string which fits exactly.""" self.assertEqual(utils.elide('foo', 3), 'foo') def test_elided(self): + """Test eliding with a string which should get elided.""" self.assertEqual(utils.elide('foobar', 3), 'fo' + self.ELLIPSIS) class CheckOverflowTests(TestCase): - """Test check_overflow.""" + """Test check_overflow. + + Class attributes: + INT32_MIN: Minimum valid value for a signed int32. + INT32_MAX: Maximum valid value for a signed int32. + INT64_MIN: Minimum valid value for a signed int64. + INT64_MAX: Maximum valid value for a signed int64. + GOOD_VALUES: A dict of types mapped to a list of good values. + BAD_VALUES: A dict of types mapped to a list of bad values. + """ INT32_MIN = -(2 ** 31) INT32_MAX = 2 ** 31 - 1 @@ -78,17 +91,20 @@ class CheckOverflowTests(TestCase): } def test_good_values(self): + """Test values which are inside bounds.""" for ctype, vals in self.GOOD_VALUES.items(): for val in vals: utils.check_overflow(val, ctype) def test_bad_values_fatal(self): + """Test values which are outside bounds with fatal=True.""" for ctype, vals in self.BAD_VALUES.items(): for (val, _) in vals: with self.assertRaises(OverflowError, msg=ctype): utils.check_overflow(val, ctype) def test_bad_values_nonfatal(self): + """Test values which are outside bounds with fatal=False.""" for ctype, vals in self.BAD_VALUES.items(): for (val, replacement) in vals: newval = utils.check_overflow(val, ctype, fatal=False) @@ -101,20 +117,29 @@ class ReadFileTests(TestCase): """Test read_file.""" def test_readfile(self): + """Read a testfile.""" content = utils.read_file(os.path.join('test', 'testfile')) self.assertEqual(content.splitlines()[0], "Hello World!") class DottedGetattrTests(TestCase): - """Test dotted_getattr.""" + """Test dotted_getattr. + + Attributes: + test: Test class instance for getattr. + """ class Test: + """Sample class used to test dotted_getattr.""" + foo = None class Test2: + """Sample class used to test dotted_getattr.""" + bar = 1 def setUp(self): @@ -122,10 +147,12 @@ class DottedGetattrTests(TestCase): self.test.foo = self.Test2() def test_dotted_getattr(self): + """Test dotted_getattr with a valid path.""" attr = utils.dotted_getattr(self, 'test.foo.bar') self.assertEqual(attr, 1) def test_invalid_path(self): + """Test dotted_getattr with an invalid path.""" with self.assertRaises(AttributeError): _ = utils.dotted_getattr(self, 'test.foo.baz') @@ -135,32 +162,48 @@ class SafeShlexSplitTests(TestCase): """Test safe_shlex_split.""" def test_normal(self): + """Test safe_shlex_split with a simple string.""" items = utils.safe_shlex_split('one two') self.assertEqual(items, ['one', 'two']) def test_quoted(self): + """Test safe_shlex_split with a normally quoted string.""" items = utils.safe_shlex_split('one "two three" four') self.assertEqual(items, ['one', 'two three', 'four']) def test_escaped(self): + """Test safe_shlex_split with a normal escaped string.""" items = utils.safe_shlex_split(r'one "two\" three" four') self.assertEqual(items, ['one', 'two" three', 'four']) def test_unbalanced_quotes(self): + """Test safe_shlex_split with unbalanded quotes.""" items = utils.safe_shlex_split(r'one "two three') self.assertEqual(items, ['one', 'two three']) def test_unfinished_escape(self): + """Test safe_shlex_split with an unfinished escape.""" items = utils.safe_shlex_split('one\\') self.assertEqual(items, ['one\\']) def test_both(self): + """Test safe_shlex_split with an unfinished escape and quotes..""" items = utils.safe_shlex_split('one "two\\') self.assertEqual(items, ['one', 'two\\']) class ShellEscapeTests(TestCase): + """Tests for shell_escape. + + Class attributes: + TEXTS_LINUX: A list of (input, output) of expected texts for Linux. + TEXTS_WINDOWS: A list of (input, output) of expected texts for Windows. + + Attributes: + platform: The saved sys.platform value. + """ + TEXTS_LINUX = [ ('', "''"), ('foo%bar+baz', 'foo%bar+baz'), @@ -214,6 +257,13 @@ class ShellEscapeTests(TestCase): class GetStandardDirLinuxTests(TestCase): + """Tests for get_standard_dir under Linux. + + Attributes: + temp_dir: A temporary directory. + app: The QCoreApplication used. + """ + def setUp(self): self.temp_dir = mkdtemp() self.app = QCoreApplication([]) @@ -221,6 +271,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_data_explicit(self): + """Test data dir with XDG_DATA_HOME explicitely set.""" with environ_set_temp('XDG_DATA_HOME', self.temp_dir): cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation) self.assertEqual(cur_dir, os.path.join(self.temp_dir, @@ -229,6 +280,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_config_explicit(self): + """Test config dir with XDG_CONFIG_HOME explicitely set.""" with environ_set_temp('XDG_CONFIG_HOME', self.temp_dir): cur_dir = utils.get_standard_dir(QStandardPaths.ConfigLocation) self.assertEqual(cur_dir, os.path.join(self.temp_dir, @@ -237,6 +289,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_cache_explicit(self): + """Test cache dir with XDG_CACHE_HOME explicitely set.""" with environ_set_temp('XDG_CACHE_HOME', self.temp_dir): cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation) self.assertEqual(cur_dir, os.path.join(self.temp_dir, @@ -245,6 +298,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_data(self): + """Test data dir with XDG_DATA_HOME not set.""" with environ_set_temp('HOME', self.temp_dir): cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation) self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.local', @@ -253,6 +307,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_config(self): + """Test config dir with XDG_CONFIG_HOME not set.""" with environ_set_temp('HOME', self.temp_dir): cur_dir = utils.get_standard_dir( QStandardPaths.ConfigLocation) @@ -262,6 +317,7 @@ class GetStandardDirLinuxTests(TestCase): @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") def test_cache(self): + """Test cache dir with XDG_CACHE_HOME not set.""" with environ_set_temp('HOME', self.temp_dir): cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation) self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.cache', @@ -275,6 +331,12 @@ class GetStandardDirLinuxTests(TestCase): class GetStandardDirWindowsTests(TestCase): + """Tests for get_standard_dir under Windows. + + Attributes: + app: The QCoreApplication used. + """ + def setUp(self): self.app = QCoreApplication([]) # We can't store the files in a temp dir, so we don't chose qutebrowser @@ -282,6 +344,7 @@ class GetStandardDirWindowsTests(TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_data(self): + """Test data dir.""" cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation) self.assertEqual(cur_dir.split(os.sep)[-1], 'qutebrowser_test', cur_dir) @@ -292,6 +355,7 @@ class GetStandardDirWindowsTests(TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_config(self): + """Test config dir.""" cur_dir = utils.get_standard_dir(QStandardPaths.ConfigLocation) self.assertEqual(cur_dir.split(os.sep)[-1], 'qutebrowser_test', cur_dir) @@ -302,6 +366,7 @@ class GetStandardDirWindowsTests(TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_cache(self): + """Test cache dir.""" cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation) self.assertEqual(cur_dir.split(os.sep)[-2:], ['qutebrowser_test', 'cache'], cur_dir) diff --git a/qutebrowser/test/utils/test_signal.py b/qutebrowser/test/utils/test_signal.py index f5698993e..1a84e2361 100644 --- a/qutebrowser/test/utils/test_signal.py +++ b/qutebrowser/test/utils/test_signal.py @@ -35,7 +35,11 @@ class FakeSignal: class TestDebug(TestCase): - """Test signal debug output functions.""" + """Test signal debug output functions. + + Attributes: + signal: The FakeSignal to be tested. + """ def setUp(self): self.signal = FakeSignal() diff --git a/qutebrowser/test/utils/test_url.py b/qutebrowser/test/utils/test_url.py index 8ee1bd418..82bf8cd0d 100644 --- a/qutebrowser/test/utils/test_url.py +++ b/qutebrowser/test/utils/test_url.py @@ -29,6 +29,12 @@ import qutebrowser.utils.url as urlutils class ConfigStub: + """Stub which is used to mock out the config. + + Attributes: + _DATA: The config data to use + """ + _DATA = { 'general': {'auto-search': True}, 'searchengines': { @@ -39,9 +45,16 @@ class ConfigStub: class NoOptionError(Exception): + """NoOptionError exception which does nothing.""" + pass def get(self, section, option): + """Get a value from section/option. + + Raise: + NoOptionError if the option was not found. + """ sect = self._DATA[section] try: return sect[option] @@ -51,24 +64,34 @@ class ConfigStub: class ConversionTests(TestCase): + """Test conversions between QUrl and url string. + + Attributes: + URL: The URL to check conversion with. + """ + URL = 'http://www.qutebrowser.org/' def test_qurl2qurl(self): + """Test converting a QUrl to a QUrl.""" q = urlutils.qurl(QUrl(self.URL)) self.assertIsInstance(q, QUrl) self.assertFalse(q.isEmpty()) def test_str2qurl(self): + """Test converting a string to a QUrl.""" q = urlutils.qurl(self.URL) self.assertIsInstance(q, QUrl) self.assertFalse(q.isEmpty()) def test_str2str(self): + """Test converting a string to a string.""" s = urlutils.urlstring(self.URL) self.assertIsInstance(s, str) self.assertEqual(s, self.URL) def test_qurl2str(self): + """Test converting a QUrl to a string.""" s = urlutils.urlstring(QUrl(self.URL)) self.assertIsInstance(s, str) self.assertEqual(s, self.URL) @@ -76,6 +99,13 @@ class ConversionTests(TestCase): class SpecialURLTests(TestCase): + """Test is_special_url. + + Attributes: + SPECIAL_URLS: URLs which are special. + NORMAL_URLS: URLs which are not special. + """ + SPECIAL_URLS = [ 'file:///tmp/foo', 'about:blank', @@ -88,36 +118,48 @@ class SpecialURLTests(TestCase): ] def test_special_urls(self): + """Test special URLs.""" for url in self.SPECIAL_URLS: self.assertTrue(urlutils.is_special_url(url)) def test_normal_urls(self): + """Test non-special URLs.""" for url in self.NORMAL_URLS: self.assertFalse(urlutils.is_special_url(url)) class SearchUrlTests(TestCase): + """Test _get_search_url. + + Attributes: + config: The urlutils.config instance. + """ + def setUp(self): self.config = urlutils.config urlutils.config = ConfigStub() def test_default_engine(self): + """Test default search engine.""" url = urlutils._get_search_url('testfoo') self.assertEqual(url.host(), 'www.example.com') self.assertEqual(url.query(), 'q=testfoo') def test_engine_post(self): + """Test search engine with an appended !hasbang.""" url = urlutils._get_search_url('testfoo !test') self.assertEqual(url.host(), 'www.qutebrowser.org') self.assertEqual(url.query(), 'q=testfoo') def test_engine_pre(self): + """Test search engine with a prepended !hasbang.""" url = urlutils._get_search_url('!test testfoo') self.assertEqual(url.host(), 'www.qutebrowser.org') self.assertEqual(url.query(), 'q=testfoo') def test_engine_wrong(self): + """Test with wrong search engine.""" with self.assertRaises(urlutils.SearchEngineError): _ = urlutils._get_search_url('!blub testfoo') @@ -127,6 +169,13 @@ class SearchUrlTests(TestCase): class IsUrlNaiveTests(TestCase): + """Tests for _is_url_naive. + + Class attributes: + URLS: A list of strings which are URLs. + NOT_URLS: A list of strings which aren't URLs. + """ + URLS = [ 'http://foobar', 'localhost:8080', @@ -141,10 +190,12 @@ class IsUrlNaiveTests(TestCase): ] def test_urls(self): + """Test things which are URLs.""" for url in self.URLS: self.assertTrue(urlutils._is_url_naive(url), url) def test_not_urls(self): + """Test things which are not URLs.""" for url in self.NOT_URLS: self.assertFalse(urlutils._is_url_naive(url), url) diff --git a/qutebrowser/test/utils/test_webelem.py b/qutebrowser/test/utils/test_webelem.py index 657640c89..24501f571 100644 --- a/qutebrowser/test/utils/test_webelem.py +++ b/qutebrowser/test/utils/test_webelem.py @@ -108,7 +108,11 @@ class FakeChildrenFrame: class IsVisibleInvalidTests(TestCase): - """Tests for is_visible with invalid elements.""" + """Tests for is_visible with invalid elements. + + Attributes: + frame: The FakeWebFrame we're using to test. + """ def setUp(self): self.frame = FakeWebFrame(QRect(0, 0, 100, 100)) @@ -146,23 +150,33 @@ class IsVisibleInvalidTests(TestCase): class IsVisibleScrollTests(TestCase): - """Tests for is_visible when the frame is scrolled.""" + """Tests for is_visible when the frame is scrolled. + + Attributes: + frame: The FakeWebFrame we're using to test. + """ def setUp(self): self.frame = FakeWebFrame(QRect(0, 0, 100, 100), scroll=QPoint(10, 10)) def test_invisible(self): + """Test elements which should be invisible due to scrolling.""" elem = FakeWebElement(QRect(5, 5, 4, 4), self.frame) self.assertFalse(webelem.is_visible(elem, self.frame)) def test_visible(self): + """Test elements which still should be visible after scrolling.""" elem = FakeWebElement(QRect(10, 10, 1, 1), self.frame) self.assertTrue(webelem.is_visible(elem, self.frame)) class IsVisibleCssTests(TestCase): - """Tests for is_visible with CSS attributes.""" + """Tests for is_visible with CSS attributes. + + Attributes: + frame: The FakeWebFrame we're using to test. + """ def setUp(self): self.frame = FakeWebFrame(QRect(0, 0, 100, 100)) @@ -193,7 +207,13 @@ class IsVisibleCssTests(TestCase): class IsVisibleIframeTests(TestCase): - """Tests for is_visible with a child frame.""" + """Tests for is_visible with a child frame. + + Attributes: + frame: The FakeWebFrame we're using to test. + iframe: The iframe inside frame. + elem1-elem4: FakeWebElements to test. + """ def setUp(self): """Set up this base situation @@ -264,7 +284,11 @@ class IsVisibleIframeTests(TestCase): class JavascriptEscapeTests(TestCase): - """Check javascript_escape.""" + """Check javascript_escape. + + Class attributes: + STRINGS: A list of (input, output) tuples. + """ STRINGS = [ ('foo\\bar', r'foo\\bar'), diff --git a/qutebrowser/test/utils/usertypes/test_enum.py b/qutebrowser/test/utils/usertypes/test_enum.py index 898f1c4a8..cc835eb81 100644 --- a/qutebrowser/test/utils/usertypes/test_enum.py +++ b/qutebrowser/test/utils/usertypes/test_enum.py @@ -27,24 +27,32 @@ from qutebrowser.utils.usertypes import enum class EnumTests(TestCase): - """Test simple enums.""" + """Test simple enums. + + Attributes: + enum: The enum we're testing. + """ def setUp(self): self.enum = enum('zero', 'one') def test_values(self): + """Test if enum members resolve to the right values.""" self.assertEqual(self.enum.zero, 0) self.assertEqual(self.enum.one, 1) def test_reverse(self): + """Test reverse mapping.""" self.assertEqual(self.enum[0], 'zero') self.assertEqual(self.enum[1], 'one') def test_unknown(self): + """Test invalid values which should raise an AttributeError.""" with self.assertRaises(AttributeError): _ = self.enum.two def test_unknown_reverse(self): + """Test reverse mapping with invalid value .""" with self.assertRaises(KeyError): _ = self.enum['two'] diff --git a/qutebrowser/test/utils/usertypes/test_fakedict.py b/qutebrowser/test/utils/usertypes/test_fakedict.py index 191779281..7634272bc 100644 --- a/qutebrowser/test/utils/usertypes/test_fakedict.py +++ b/qutebrowser/test/utils/usertypes/test_fakedict.py @@ -27,20 +27,27 @@ from qutebrowser.utils.usertypes import FakeDict class FakeDictTests(TestCase): - """Test the FakeDict usertype.""" + """Test the FakeDict usertype. + + Attributes: + fd: The FakeDict we're testing. + """ def setUp(self): self.fd = FakeDict("foo") - def test_getattr(self): + def test_getitem(self): + """Test getting items of the fakedict.""" self.assertEqual(self.fd["eggs"], "foo") self.assertEqual(self.fd["bacon"], "foo") - def test_setattr(self): + def test_setitem(self): + """Test setting items of the FakeDict which should raise TypeError.""" with self.assertRaises(TypeError): self.fd["eggs"] = "bar" def test_repr(self): + """Test repr() on the FakeDict.""" self.assertEqual(repr(self.fd), "FakeDict('foo')") diff --git a/qutebrowser/test/utils/usertypes/test_neighborlist.py b/qutebrowser/test/utils/usertypes/test_neighborlist.py index b99a86e0c..b5a64464f 100644 --- a/qutebrowser/test/utils/usertypes/test_neighborlist.py +++ b/qutebrowser/test/utils/usertypes/test_neighborlist.py @@ -27,25 +27,34 @@ from qutebrowser.utils.usertypes import NeighborList class InitTests(TestCase): - """Just try to init some neighborlists.""" + """Just try to init some neighborlists. + + Attributes: + nl: The NeighborList we're testing. + """ def test_empty(self): + """Test constructing an empty NeighborList.""" nl = NeighborList() self.assertEqual(nl.items, []) def test_items(self): + """Test constructing an NeighborList with items.""" nl = NeighborList([1, 2, 3]) self.assertEqual(nl.items, [1, 2, 3]) def test_len(self): + """Test len() on NeighborList.""" nl = NeighborList([1, 2, 3]) self.assertEqual(len(nl), 3) def test_repr(self): + """Test repr() on NeighborList.""" nl = NeighborList([1, 2, 3]) self.assertEqual(repr(nl), 'NeighborList([1, 2, 3])') def test_contains(self): + """Test 'in' on NeighborList.""" nl = NeighborList([1, 2, 3]) self.assertIn(2, nl) self.assertNotIn(4, nl) @@ -53,84 +62,110 @@ class InitTests(TestCase): class DefaultTests(TestCase): - """Test the default argument.""" + """Test the default argument. + + Attributes: + nl: The NeighborList we're testing. + """ def test_simple(self): + """Test default with a numeric argument.""" nl = NeighborList([1, 2, 3], default=2) self.assertEqual(nl.idx, 1) def test_none(self): + """Test default 'None'.""" nl = NeighborList([1, 2, None], default=None) self.assertEqual(nl.idx, 2) def test_unset(self): + """Test unset default value.""" nl = NeighborList([1, 2, 3]) self.assertIsNone(nl.idx) class EmptyTests(TestCase): - """Tests with no items.""" + """Tests with no items. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList() def test_curitem(self): + """Test curitem with no item.""" with self.assertRaises(IndexError): self.nl.curitem() def test_firstitem(self): + """Test firstitem with no item.""" with self.assertRaises(IndexError): self.nl.firstitem() def test_lastitem(self): + """Test lastitem with no item.""" with self.assertRaises(IndexError): self.nl.lastitem() def test_getitem(self): + """Test getitem with no item.""" with self.assertRaises(IndexError): self.nl.getitem(1) class ItemTests(TestCase): - """Tests with items.""" + """Tests with items. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([1, 2, 3, 4, 5], default=3) def test_curitem(self): + """Test curitem().""" self.assertEqual(self.nl.idx, 2) self.assertEqual(self.nl.curitem(), 3) self.assertEqual(self.nl.idx, 2) def test_nextitem(self): + """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) def test_previtem(self): + """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) def test_firstitem(self): + """Test firstitem().""" self.assertEqual(self.nl.firstitem(), 1) self.assertEqual(self.nl.idx, 0) def test_lastitem(self): + """Test lastitem().""" self.assertEqual(self.nl.lastitem(), 5) self.assertEqual(self.nl.idx, 4) def test_reset(self): + """Test reset().""" self.nl.nextitem() self.assertEqual(self.nl.idx, 3) self.nl.reset() self.assertEqual(self.nl.idx, 2) def test_getitem(self): + """Test getitem().""" self.assertEqual(self.nl.getitem(2), 5) self.assertEqual(self.nl.idx, 4) self.nl.reset() @@ -140,12 +175,17 @@ class ItemTests(TestCase): class OneTests(TestCase): - """Tests with a list with only one item.""" + """Tests with a list with only one item. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([1], default=1) def test_first_wrap(self): + """Test out of bounds previtem() with mode=wrap.""" self.nl._mode = NeighborList.Modes.wrap self.nl.firstitem() self.assertEqual(self.nl.idx, 0) @@ -153,6 +193,7 @@ class OneTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_first_block(self): + """Test out of bounds previtem() with mode=block.""" self.nl._mode = NeighborList.Modes.block self.nl.firstitem() self.assertEqual(self.nl.idx, 0) @@ -160,6 +201,7 @@ class OneTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_first_raise(self): + """Test out of bounds previtem() with mode=raise.""" self.nl._mode = NeighborList.Modes.exception self.nl.firstitem() self.assertEqual(self.nl.idx, 0) @@ -168,6 +210,7 @@ class OneTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_last_wrap(self): + """Test out of bounds nextitem() with mode=wrap.""" self.nl._mode = NeighborList.Modes.wrap self.nl.lastitem() self.assertEqual(self.nl.idx, 0) @@ -175,6 +218,7 @@ class OneTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_last_block(self): + """Test out of bounds nextitem() with mode=block.""" self.nl._mode = NeighborList.Modes.block self.nl.lastitem() self.assertEqual(self.nl.idx, 0) @@ -182,6 +226,7 @@ class OneTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_last_raise(self): + """Test out of bounds nextitem() with mode=raise.""" self.nl._mode = NeighborList.Modes.exception self.nl.lastitem() self.assertEqual(self.nl.idx, 0) @@ -192,19 +237,25 @@ class OneTests(TestCase): class BlockTests(TestCase): - """Tests with mode=block.""" + """Tests with mode=block. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([1, 2, 3, 4, 5], default=3, mode=NeighborList.Modes.block) def test_first(self): + """Test ouf of bounds previtem().""" self.nl.firstitem() self.assertEqual(self.nl.idx, 0) self.assertEqual(self.nl.previtem(), 1) self.assertEqual(self.nl.idx, 0) def test_last(self): + """Test ouf of bounds nextitem().""" self.nl.lastitem() self.assertEqual(self.nl.idx, 4) self.assertEqual(self.nl.nextitem(), 5) @@ -213,19 +264,25 @@ class BlockTests(TestCase): class WrapTests(TestCase): - """Tests with mode=wrap.""" + """Tests with mode=wrap. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([1, 2, 3, 4, 5], default=3, mode=NeighborList.Modes.wrap) def test_first(self): + """Test ouf of bounds previtem().""" self.nl.firstitem() self.assertEqual(self.nl.idx, 0) self.assertEqual(self.nl.previtem(), 5) self.assertEqual(self.nl.idx, 4) def test_last(self): + """Test ouf of bounds nextitem().""" self.nl.lastitem() self.assertEqual(self.nl.idx, 4) self.assertEqual(self.nl.nextitem(), 1) @@ -234,13 +291,18 @@ class WrapTests(TestCase): class RaiseTests(TestCase): - """Tests with mode=exception.""" + """Tests with mode=exception. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([1, 2, 3, 4, 5], default=3, mode=NeighborList.Modes.exception) def test_first(self): + """Test ouf of bounds previtem().""" self.nl.firstitem() self.assertEqual(self.nl.idx, 0) with self.assertRaises(IndexError): @@ -248,6 +310,7 @@ class RaiseTests(TestCase): self.assertEqual(self.nl.idx, 0) def test_last(self): + """Test ouf of bounds nextitem().""" self.nl.lastitem() self.assertEqual(self.nl.idx, 4) with self.assertRaises(IndexError): @@ -257,12 +320,17 @@ class RaiseTests(TestCase): class SnapInTests(TestCase): - """Tests for the fuzzyval/_snap_in features.""" + """Tests for the fuzzyval/_snap_in features. + + Attributes: + nl: The NeighborList we're testing. + """ def setUp(self): self.nl = NeighborList([20, 9, 1, 5]) def test_bigger(self): + """Test fuzzyval with snapping to a bigger value.""" self.nl.fuzzyval = 7 self.assertEqual(self.nl.nextitem(), 9) self.assertEqual(self.nl.idx, 1) @@ -270,6 +338,7 @@ class SnapInTests(TestCase): self.assertEqual(self.nl.idx, 2) def test_smaller(self): + """Test fuzzyval with snapping to a smaller value.""" self.nl.fuzzyval = 7 self.assertEqual(self.nl.previtem(), 5) self.assertEqual(self.nl.idx, 3) @@ -277,11 +346,13 @@ class SnapInTests(TestCase): self.assertEqual(self.nl.idx, 2) def test_equal_bigger(self): + """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) def test_equal_smaller(self): + """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)