jenkins-bot has submitted this change and it was merged.
Change subject: Class hierarchy, marking tests not using Site ......................................................................
Class hierarchy, marking tests not using Site
Move alls tests under BaseTestCase, which has subclasses NoSiteTestCase and SiteTestCase to split the test suite into tests that require a valid site and those that do not.
Tests the subclass NoSiteTestCase are prevented from invoking pywikibot.Site, and may be run as a subset of the test suite using:
$ nosetests -a '!site'
Change-Id: I6ee69f5b4e594a111d91bc0bafb59716900b478c --- M tests/api_tests.py M tests/date_tests.py M tests/dry_api_tests.py M tests/dry_site_tests.py M tests/http_tests.py M tests/i18n_tests.py M tests/ipregex_tests.py M tests/pwb_tests.py M tests/utils.py M tests/weblib_tests.py M tests/xmlreader_tests.py M tox.ini 12 files changed, 122 insertions(+), 42 deletions(-)
Approvals: John Vandenberg: Looks good to me, but someone else must approve Merlijn van Deen: Looks good to me, approved jenkins-bot: Verified
diff --git a/tests/api_tests.py b/tests/api_tests.py index ec3a454..8bf9e1a 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -9,12 +9,13 @@ import datetime import pywikibot import pywikibot.data.api as api -from tests.utils import PywikibotTestCase, unittest +from tests.utils import unittest +from tests.utils import SiteTestCase, NoSiteTestCase, CachedTestCase
mysite = pywikibot.Site('en', 'wikipedia')
-class TestApiFunctions(PywikibotTestCase): +class TestApiFunctions(CachedTestCase):
def testObjectCreation(self): """Test that api.Request() creates an object with desired attributes""" @@ -34,7 +35,7 @@ self.assertEqual(len(item), 2, item)
-class TestPageGenerator(PywikibotTestCase): +class TestPageGenerator(CachedTestCase): def setUp(self): super(TestPageGenerator, self).setUp() self.gen = api.PageGenerator(site=mysite, @@ -108,7 +109,7 @@ self.assertEqual(len(results), 4) # total=-1 but 4 expected
-class TestCachedRequest(unittest.TestCase): +class TestCachedRequest(SiteTestCase): def testResults(self): # Run the cached query twice to ensure the # data returned is equal diff --git a/tests/date_tests.py b/tests/date_tests.py index 44b89d9..7d9a81f 100644 --- a/tests/date_tests.py +++ b/tests/date_tests.py @@ -6,7 +6,7 @@ # __version__ = '$Id$'
-from tests.utils import unittest, PywikibotTestCase +from tests.utils import unittest, NoSiteTestCase from pywikibot import date
@@ -49,7 +49,7 @@ return type.__new__(cls, name, bases, dct)
-class TestDate(PywikibotTestCase): +class TestDate(NoSiteTestCase): """Test cases for date library processed by unittest""" __metaclass__ = TestDateMeta
diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py index 1714b59..56b24c1 100644 --- a/tests/dry_api_tests.py +++ b/tests/dry_api_tests.py @@ -11,10 +11,10 @@ import hashlib import pywikibot from pywikibot.data.api import CachedRequest, QueryGenerator -from utils import unittest +from utils import unittest, NoSiteTestCase, SiteTestCase
-class DryCachedRequestTests(unittest.TestCase): +class DryCachedRequestTests(SiteTestCase):
def setUp(self): self.basesite = pywikibot.Site('en', 'wikipedia') @@ -26,6 +26,8 @@ self.expreq = CachedRequest(expiry=0, **self.parms) self.diffreq = CachedRequest(expiry=1, site=self.basesite, action='query', meta='siteinfo') self.diffsite = CachedRequest(expiry=1, site=self.altsite, action='query', meta='userinfo') + + super(DryCachedRequestTests, self).setUp()
def test_expiry_formats(self): self.assertEqual(self.req.expiry, CachedRequest(datetime.timedelta(days=1), **self.parms).expiry) @@ -50,7 +52,7 @@ self.assertNotEqual(self.req._cachefile_path(), self.diffsite._cachefile_path())
-class MockCachedRequestKeyTests(unittest.TestCase): +class MockCachedRequestKeyTests(NoSiteTestCase): def setUp(self): class MockFamily(pywikibot.family.Family):
@@ -90,24 +92,25 @@ def __getattr__(self, attr): raise Exception("Attribute %r not defined" % attr)
- self.site = MockSite() + self.mocksite = MockSite() + super(MockCachedRequestKeyTests, self).setUp()
def test_cachefile_path_different_users(self): - req = CachedRequest(expiry=1, site=self.site, + req = CachedRequest(expiry=1, site=self.mocksite, action='query', meta='siteinfo') anonpath = req._cachefile_path()
- self.site._userinfo = {'name': u'MyUser'} - self.site._loginstatus = 0 - req = CachedRequest(expiry=1, site=self.site, + self.mocksite._userinfo = {'name': u'MyUser'} + self.mocksite._loginstatus = 0 + req = CachedRequest(expiry=1, site=self.mocksite, action='query', meta='siteinfo') userpath = req._cachefile_path()
self.assertNotEqual(anonpath, userpath)
- self.site._userinfo = {'name': u'MySysop'} - self.site._loginstatus = 1 - req = CachedRequest(expiry=1, site=self.site, + self.mocksite._userinfo = {'name': u'MySysop'} + self.mocksite._loginstatus = 1 + req = CachedRequest(expiry=1, site=self.mocksite, action='query', meta='siteinfo') sysoppath = req._cachefile_path()
@@ -115,16 +118,16 @@ self.assertNotEqual(userpath, sysoppath)
def test_unicode(self): - self.site._userinfo = {'name': u'محمد الفلسطيني'} - self.site._loginstatus = 0 + self.mocksite._userinfo = {'name': u'محمد الفلسطيني'} + self.mocksite._loginstatus = 0
- req = CachedRequest(expiry=1, site=self.site, + req = CachedRequest(expiry=1, site=self.mocksite, action='query', meta='siteinfo') en_user_path = req._cachefile_path()
- self.site._namespaces = {2: [u'مستخدم']} + self.mocksite._namespaces = {2: [u'مستخدم']}
- req = CachedRequest(expiry=1, site=self.site, + req = CachedRequest(expiry=1, site=self.mocksite, action='query', meta='siteinfo')
expect = u'MockSite()User(User:محمد الفلسطيني)' + \ @@ -140,9 +143,14 @@ self.assertEqual(en_user_path, ar_user_path)
-class DryQueryGenTests(unittest.TestCase): +class DryQueryGenTests(SiteTestCase):
def test_query_constructor(self): + """Test QueryGenerator constructor. + + QueryGenerator constructor will call pywikibot.Site() + if a site paramter is not provided. + """ qGen1 = QueryGenerator(action="query", meta="siteinfo") qGen2 = QueryGenerator(meta="siteinfo") self.assertEqual(str(qGen1.request), str(qGen2.request)) diff --git a/tests/dry_site_tests.py b/tests/dry_site_tests.py index 573c89e..16f247e 100644 --- a/tests/dry_site_tests.py +++ b/tests/dry_site_tests.py @@ -10,7 +10,7 @@ import pywikibot from pywikibot.site import must_be
-from tests.utils import PywikibotTestCase, unittest +from tests.utils import unittest, NoSiteTestCase
class DrySite(pywikibot.site.APISite): @@ -21,7 +21,7 @@ return self._userinfo
-class TestDrySite(PywikibotTestCase): +class TestDrySite(NoSiteTestCase): def test_logged_in(self): x = DrySite('en', 'wikipedia')
@@ -41,7 +41,7 @@ self.assertFalse(x.logged_in(False))
-class TestMustBe(PywikibotTestCase): +class TestMustBe(NoSiteTestCase): """Test cases for the must_be decorator."""
# Implemented without setUpClass(cls) and global variables as objects diff --git a/tests/http_tests.py b/tests/http_tests.py index 0063774..646c999 100644 --- a/tests/http_tests.py +++ b/tests/http_tests.py @@ -11,10 +11,10 @@
from pywikibot.comms import http, threadedhttp -from tests.utils import unittest +from tests.utils import unittest, NoSiteTestCase
-class HttpTestCase(unittest.TestCase): +class HttpTestCase(NoSiteTestCase):
def test_get(self): r = http.request(site=None, uri='http://www.wikipedia.org/') diff --git a/tests/i18n_tests.py b/tests/i18n_tests.py index 78ddc89..b349bc7 100644 --- a/tests/i18n_tests.py +++ b/tests/i18n_tests.py @@ -8,10 +8,10 @@
from pywikibot import i18n
-from tests.utils import unittest, PywikibotTestCase +from tests.utils import unittest, NoSiteTestCase
-class TestTranslate(PywikibotTestCase): +class TestTranslate(NoSiteTestCase): def setUp(self): self.msg_localized = {'en': u'test-localized EN', 'nl': u'test-localized NL', @@ -70,7 +70,7 @@ u'test-no-english JA')
-class TestTWN(PywikibotTestCase): +class TestTWN(NoSiteTestCase): def setUp(self): self.orig_messages_package_name = i18n.messages_package_name i18n.messages_package_name = 'tests.i18n' diff --git a/tests/ipregex_tests.py b/tests/ipregex_tests.py index 4cc9ea9..01fa79b 100644 --- a/tests/ipregex_tests.py +++ b/tests/ipregex_tests.py @@ -6,11 +6,11 @@ # Distributed under the terms of the MIT license. __version__ = '$Id$'
-from tests.utils import unittest, PywikibotTestCase +from tests.utils import unittest, NoSiteTestCase from pywikibot.page import ip_regexp
-class PyWikiIpRegexCase(PywikibotTestCase): +class PyWikiIpRegexCase(NoSiteTestCase): """Unit test class for ip_regexp"""
def setUp(self): diff --git a/tests/pwb_tests.py b/tests/pwb_tests.py index 6a31c7b..9f36a0c 100644 --- a/tests/pwb_tests.py +++ b/tests/pwb_tests.py @@ -11,7 +11,7 @@ import subprocess import pywikibot
-from tests.utils import unittest +from tests.utils import unittest, SiteTestCase
pypath = sys.executable basepath = os.path.split(os.path.split(__file__)[0])[0] @@ -23,7 +23,14 @@ return subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0]
-class TestPwb(unittest.TestCase): +class TestPwb(SiteTestCase): + + """Test pwb.py functionality. + + This is registered as a Site test because it will not run + without a user-config.py + """ + def setUp(self): self.oldenviron = os.environ.copy() os.environ['PYWIKIBOT2_DIR'] = pywikibot.config.base_dir diff --git a/tests/utils.py b/tests/utils.py index 9d02bba..f767538 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -21,6 +21,8 @@ except ImportError: import unittest
+import pywikibot + # Number of seconds each test may consume before a note is added after the test. test_duration_warning_interval = 10
@@ -35,14 +37,18 @@ from tests import patch_request, unpatch_request
-class PywikibotTestCase(unittest.TestCase): +class BaseTestCase(unittest.TestCase): + + """Base class for all test cases. + + Adds timing info to stdout. + """ + def assertType(self, obj, cls): """Assert that obj is an instance of type cls""" return self.assertTrue(isinstance(obj, cls))
def setUp(self): - patch_request() - self.test_start = time.time()
def tearDown(self): @@ -53,4 +59,57 @@ print(' %0.3fs' % duration, end=' ') sys.stdout.flush()
+ +class NoSiteTestCase(BaseTestCase): + + """Test cases not connected to a Site object. + + Do not use this for mock Site objects. + + Never set a class or instance variable called 'site' + As it will prevent tests from executing when invoked as: + $ nosetests -a '!site' -v + """ + + def setUp(self): + self.old_Site_lookup_method = pywikibot.Site + pywikibot.Site = lambda *args: self.fail('%s: Site() not permitted' + % self.__class__.__name__) + + super(NoSiteTestCase, self).setUp() + + def tearDown(self): + super(NoSiteTestCase, self).tearDown() + + pywikibot.Site = self.old_Site_lookup_method + + +class SiteTestCase(BaseTestCase): + + """Test cases connected to a Site object. + + Do not use this for mock Site objects. + """ + + site = True + + +class CachedTestCase(SiteTestCase): + + """Aggressively cached API test cases. + + Patches pywikibot.data.api to aggressively cache + API responses. + """ + + def setUp(self): + patch_request() + + super(CachedTestCase, self).setUp() + + def tearDown(self): + super(CachedTestCase, self).tearDown() + unpatch_request() + +PywikibotTestCase = CachedTestCase diff --git a/tests/weblib_tests.py b/tests/weblib_tests.py index b5183fc..df43e8e 100644 --- a/tests/weblib_tests.py +++ b/tests/weblib_tests.py @@ -13,10 +13,10 @@ from urllib.parse import urlparse
import pywikibot.weblib as weblib -from tests.utils import unittest, PywikibotTestCase +from tests.utils import unittest, NoSiteTestCase
-class TestArchiveSites(PywikibotTestCase): +class TestArchiveSites(NoSiteTestCase): def testInternetArchiveNewest(self): archivedversion = weblib.getInternetArchiveURL('https://google.com') parsed = urlparse(archivedversion) diff --git a/tests/xmlreader_tests.py b/tests/xmlreader_tests.py index e3ac959..a353fad 100644 --- a/tests/xmlreader_tests.py +++ b/tests/xmlreader_tests.py @@ -12,10 +12,10 @@
import os.path from pywikibot import xmlreader -from tests.utils import unittest, PywikibotTestCase +from tests.utils import unittest, NoSiteTestCase
-class XmlReaderTestCase(PywikibotTestCase): +class XmlReaderTestCase(NoSiteTestCase):
@classmethod def setUpClass(cls): diff --git a/tox.ini b/tox.ini index 5e8d79a..f067bf2 100644 --- a/tox.ini +++ b/tox.ini @@ -17,6 +17,10 @@ commands = flake8 --select=D {posargs} deps = flake8-docstrings
+[testenv:nose] +commands = nosetests -a "!site" +deps = nose + [testenv:venv] commands = {posargs}
@@ -29,3 +33,4 @@ ignore = E122,E127,E241,E502 exclude = .tox,.git,./*.egg,ez_setup.py,externals,user-config.py,./scripts/i18n/*,./pywikibot/date.py max_line_length = 256 +
pywikibot-commits@lists.wikimedia.org