jenkins-bot has submitted this change and it was merged. Change subject: Skip tests that use a site which is failing ......................................................................
Skip tests that use a site which is failing Add 'hostname' to TestCase.sites dict, and skip class when failed to receive a useful response for the hosts homepage. Re-enable weblib tests on travis-ci, instead using the new automatic skip functionality to avoid errors due to WebCite serving invalid XML and having an undecodable homepage. Mention hostnames in test method docstring where the hostname is not easily guessed. Bug: T58963 Change-Id: I8fdcdaa0fab3b680d35b81b20a12ff5b786f779d --- M pywikibot/weblib.py M tests/__init__.py M tests/aspects.py M tests/data_ingestion_tests.py M tests/http_tests.py M tests/interwiki_link_tests.py M tests/weblib_tests.py M tests/wikidataquery_tests.py M tests/wikistats_tests.py 9 files changed, 202 insertions(+), 39 deletions(-) Approvals: XZise: Looks good to me, approved jenkins-bot: Verified diff --git a/pywikibot/weblib.py b/pywikibot/weblib.py index f682fec..8f0622d 100644 --- a/pywikibot/weblib.py +++ b/pywikibot/weblib.py @@ -36,7 +36,7 @@ query['timestamp'] = timestamp uri = uri + urlencode(query) - jsontext = http.request(uri=uri, site=None) + jsontext = http.fetch(uri).content if "closest" in jsontext: data = json.loads(jsontext) return data['archived_snapshots']['closest']['url'] @@ -65,7 +65,7 @@ query['date'] = timestamp uri = uri + urlencode(query) - xmltext = http.request(uri=uri, site=None) + xmltext = http.fetch(uri).content if "success" in xmltext: data = ET.fromstring(xmltext) return data.find('.//webcite_url').text diff --git a/tests/__init__.py b/tests/__init__.py index 32eaa93..4edf26a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -94,9 +94,6 @@ 'ui', ] -if os.environ.get('TRAVIS', 'false') == 'true': - disabled_test_modules.append('weblib') - disabled_tests = { 'textlib': [ 'test_interwiki_format', # example; very slow test diff --git a/tests/aspects.py b/tests/aspects.py index 6466018..ab9146c 100644 --- a/tests/aspects.py +++ b/tests/aspects.py @@ -37,9 +37,10 @@ import pywikibot -from pywikibot import config, log, Site +from pywikibot import config, log, ServerError, Site from pywikibot.site import BaseSite from pywikibot.family import WikimediaFamily +from pywikibot.comms import http from pywikibot.data.api import Request as _original_Request import tests @@ -382,6 +383,70 @@ super(CacheInfoMixin, self).tearDown() +class CheckHostnameMixin(TestCaseBase): + + """Check the hostname is online before running tests.""" + + _checked_hostnames = {} + + @classmethod + def setUpClass(cls): + """ + Set up the test class. + + Prevent tests running if the host is down. + """ + super(CheckHostnameMixin, cls).setUpClass() + + if not hasattr(cls, 'sites'): + return + + for key, data in cls.sites.items(): + if 'hostname' not in data: + raise Exception('%s: hostname not defined for %s' + % (cls.__name__, key)) + hostname = data['hostname'] + + if hostname in cls._checked_hostnames: + if isinstance(cls._checked_hostnames[hostname], Exception): + raise unittest.SkipTest( + '%s: hostname %s failed (cached): %s' + % (cls.__name__, hostname, + cls._checked_hostnames[hostname])) + elif cls._checked_hostnames[hostname] is False: + raise unittest.SkipTest('%s: hostname %s failed (cached)' + % (cls.__name__, hostname)) + else: + continue + + e = None + try: + if '://' not in hostname: + hostname = 'http://' + hostname + r = http.fetch(uri=hostname, + default_error_handling=False) + if r.exception: + e = r.exception + else: + if r.status not in [200, 301, 302, 303, 307, 308]: + raise ServerError('HTTP status: %d' % r.status) + r.content # default decode may raise exception + except Exception as e2: + pywikibot.error('%s: accessing %s caused exception:' + % (cls.__name__, hostname)) + pywikibot.exception(e2, tb=True) + e = e2 + pass + + if e: + cls._checked_hostnames[hostname] = e + raise unittest.SkipTest( + '%s: hostname %s failed: %s' + % (cls.__name__, hostname, e)) + + cls._checked_hostnames[hostname] = True + + class SiteWriteMixin(TestCaseBase): """ @@ -591,6 +656,8 @@ if 'cached' in dct and dct['cached']: bases = tuple([ForceCacheMixin] + list(bases)) + bases = tuple([CheckHostnameMixin] + list(bases)) + if 'write' in dct and dct['write']: bases = tuple([SiteWriteMixin] + list(bases)) @@ -665,16 +732,19 @@ interface = DrySite for data in cls.sites.values(): - if 'site' not in data: + if 'site' not in data and 'code' in data and 'family' in data: data['site'] = Site(data['code'], data['family'], interface=interface) + if 'hostname' not in data and 'site' in data: + data['hostname'] = data['site'].hostname() if not hasattr(cls, 'cached') or not cls.cached: pywikibot._sites = orig_sites if len(cls.sites) == 1: key = next(iter(cls.sites.keys())) - cls.site = cls.sites[key]['site'] + if 'site' in cls.sites[key]: + cls.site = cls.sites[key]['site'] @classmethod def get_site(cls, name=None): @@ -830,19 +900,23 @@ """ super(WikibaseTestCase, cls).setUpClass() - for site in cls.sites.values(): - if not site['site'].has_data_repository: + for data in cls.sites.values(): + if 'site' not in data: + continue + + site = data['site'] + if not site.has_data_repository: raise unittest.SkipTest( u'%s: %r does not have data repository' - % (cls.__name__, site['site'])) + % (cls.__name__, site)) if (hasattr(cls, 'repo') and - cls.repo != site['site'].data_repository()): + cls.repo != site.data_repository()): raise Exception( '%s: sites do not all have the same data repository' % cls.__name__) - cls.repo = site['site'].data_repository() + cls.repo = site.data_repository() @classmethod def get_repo(cls): diff --git a/tests/data_ingestion_tests.py b/tests/data_ingestion_tests.py index deec8a1..312bea0 100644 --- a/tests/data_ingestion_tests.py +++ b/tests/data_ingestion_tests.py @@ -14,7 +14,15 @@ """Test Photo class.""" - net = True + sites = { + 'wm-upload': { + 'hostname': 'upload.wikimedia.org', + }, + 'commons': { + 'family': 'commons', + 'code': 'commons', + }, + } def setUp(self): super(TestPhoto, self).setUp() @@ -28,11 +36,14 @@ ) def test_downloadPhoto(self): + """Test download from http://upload.wikimedia.org/.""" with open(os.path.join(_data_dir, 'MP_sounds.png'), 'rb') as f: self.assertEqual(f.read(), self.obj.downloadPhoto().read()) def test_findDuplicateImages(self): - duplicates = self.obj.findDuplicateImages() + """Test finding duplicates on Wikimedia Commons.""" + duplicates = self.obj.findDuplicateImages( + site=self.get_site('commons')) self.assertIn('MP sounds.png', [dup.replace("_", " ") for dup in duplicates]) def test_getTitle(self): diff --git a/tests/http_tests.py b/tests/http_tests.py index 0263d62..9e9a3c7 100644 --- a/tests/http_tests.py +++ b/tests/http_tests.py @@ -27,10 +27,17 @@ """Tests for http module.""" - net = True + sites = { + 'www-wp': { + 'hostname': 'www.wikipedia.org', + }, + 'www-wq': { + 'hostname': 'www.wikiquote.org', + }, + } def test_async(self): - """Test http request_async function.""" + """Test http._enqueue using http://www.wikipedia.org/.""" r = http._enqueue('http://www.wikipedia.org/') self.assertIsInstance(r, threadedhttp.HttpRequest) self.assertEqual(r.status, 200) @@ -39,7 +46,7 @@ self.assertIsInstance(r.raw, bytes) def test_fetch(self): - """Test http fetch function.""" + """Test http.fetch using http://www.wikipedia.org/.""" r = http.fetch('http://www.wikipedia.org/') self.assertIsInstance(r, threadedhttp.HttpRequest) self.assertEqual(r.status, 200) @@ -48,19 +55,49 @@ self.assertIsInstance(r.raw, bytes) def test_http(self): - """Test http request function.""" + """Test http.request using http://www.wikipedia.org/.""" r = http.request(site=None, uri='http://www.wikipedia.org/') self.assertIsInstance(r, unicode) self.assertIn('<html lang="mul"', r) def test_https(self): - """Test http request function using https.""" + """Test http.request using https://www.wikiquote.org/.""" r = http.request(site=None, uri='https://www.wikiquote.org/') self.assertIsInstance(r, unicode) self.assertIn('<html lang="mul"', r) + +class HttpServerProblemTestCase(TestCase): + + """Test HTTP status 502 causes this test class to be skipped.""" + + sites = { + '502': { + 'hostname': 'http://getstatuscode.com/502', + } + } + + def test_502(self): + """Test a HTTP 502 response using http://getstatuscode.com/502.""" + self.fail('The test framework should skip this test.') + pass + + +class HttpsCertificateTestCase(TestCase): + + """HTTPS certificate test.""" + + sites = { + 'omegawiki': { + 'hostname': 'www.omegawiki.org', + }, + 'vikidia': { + 'hostname': 'en.vikidia.org', + }, + } + def test_https_cert_error(self): - """Test http request function fails on ssl bad certificate.""" + """Test http.request fails on invalid omegawiki SSL certificate.""" self.assertRaises(pywikibot.FatalServerError, http.request, site=None, @@ -68,7 +105,7 @@ @expectedFailureIf(sys.version_info[0] > 2) # bug 72236 def test_https_ignore_cert_error(self): - """Test http request function ignoring ssl bad certificate.""" + """Test http.request ignoring invalid vikidia SSL certificate.""" # As the connection is cached, the above test will cause # subsequent requests to go to the existing, broken, connection. # So, this uses a different host, which hopefully hasnt been @@ -80,7 +117,7 @@ self.assertIn('<title>Vikidia</title>', r) def test_https_cert_invalid(self): - """Verify certificate is bad.""" + """Verify vikidia SSL certificate is invalid.""" try: from pyasn1_modules import pem, rfc2459 from pyasn1.codec.der import decoder @@ -113,9 +150,17 @@ """Tests for threadedhttp module Http class.""" - net = True + sites = { + 'www-wp': { + 'hostname': 'www.wikipedia.org', + }, + 'wikidata': { + 'hostname': 'test.wikidata.org', + }, + } def test_http(self): + """Test threadedhttp.Http.request using http://www.wikipedia.org/.""" o = threadedhttp.Http() r = o.request('http://www.wikipedia.org/') self.assertIsInstance(r, tuple) @@ -130,6 +175,7 @@ self.assertEqual(int(r[0]['content-length']), len(r[1])) def test_https(self): + """Test threadedhttp.Http.request using https://www.wikipedia.org/.""" o = threadedhttp.Http() r = o.request('https://www.wikipedia.org/') self.assertIsInstance(r, tuple) @@ -144,6 +190,7 @@ self.assertEqual(int(r[0]['content-length']), len(r[1])) def test_gzip(self): + """Test threadedhttp.Http encodes using gzip.""" o = threadedhttp.Http() r = o.request('http://www.wikipedia.org/') self.assertIsInstance(r, tuple) @@ -159,11 +206,15 @@ self.assertEqual(r[0]['-content-encoding'], 'gzip') -class ThreadedHttpRequestTestCase(TestCase): +class ThreadedHttpRequestQueueTestCase(TestCase): """Tests for threadedhttp module threaded HttpRequest.""" - net = True + sites = { + 'www-wp': { + 'hostname': 'www.wikipedia.org', + }, + } def test_threading(self): queue = Queue.Queue() diff --git a/tests/interwiki_link_tests.py b/tests/interwiki_link_tests.py index 61e8ae4..ea7ec08 100644 --- a/tests/interwiki_link_tests.py +++ b/tests/interwiki_link_tests.py @@ -66,6 +66,7 @@ } def test_direct_non_local(self): + """Test translatewiki:Main Page on English Wikipedia.""" link = Link('translatewiki:Main Page', self.get_site('wp')) link.parse() self.assertEqual(link.site, self.get_site('tw')) @@ -73,6 +74,7 @@ self.assertEqual(link.namespace, 0) def test_indirect_non_local(self): + """Test en:translatewiki:Main Page on English Wikipedia.""" link = Link('en:translatewiki:Main Page', self.get_site('wp')) link.parse() self.assertEqual(link.site, self.get_site('tw')) @@ -80,6 +82,7 @@ self.assertEqual(link.namespace, 0) def test_via_local_non_local(self): + """Test de:translatewiki:Main Page on English Wikipedia.""" link = Link('de:translatewiki:Main Page', self.get_site('wp')) self.assertRaisesRegex( InvalidTitle, diff --git a/tests/weblib_tests.py b/tests/weblib_tests.py index f4916e7..84f445f 100644 --- a/tests/weblib_tests.py +++ b/tests/weblib_tests.py @@ -7,7 +7,6 @@ # __version__ = '$Id$' -import os import sys if sys.version_info[0] > 2: from urllib.parse import urlparse @@ -18,17 +17,15 @@ from tests.aspects import unittest, TestCase -class TestArchiveSites(TestCase): +class TestInternetArchive(TestCase): - """Test weblib methods to access archive websites.""" + """Test weblib methods to access Internet Archive.""" - net = True - - @classmethod - def setUpClass(cls): - if os.environ.get('TRAVIS', 'false') == 'true': - raise unittest.SkipTest('Weblib tests are disabled on Travis-CI') - super(TestArchiveSites, cls).setUpClass() + sites = { + 'archive.org': { + 'hostname': 'web.archive.org', + }, + } def testInternetArchiveNewest(self): archivedversion = weblib.getInternetArchiveURL('https://google.com') @@ -45,10 +42,23 @@ self.assertTrue(parsed.path.strip('/').endswith('www.google.com'), parsed.path) self.assertIn('200606', parsed.path) + +class TestWebCite(TestCase): + + """Test weblib methods to access WebCite.""" + + sites = { + 'webcite': { + 'hostname': 'www.webcitation.org', + } + } + + @unittest.expectedFailure def testWebCiteOlder(self): archivedversion = weblib.getWebCitationURL('https://google.com', '20130101') self.assertEqual(archivedversion, 'http://www.webcitation.org/6DHSeh2L0') + if __name__ == '__main__': try: unittest.main() diff --git a/tests/wikidataquery_tests.py b/tests/wikidataquery_tests.py index 4c3b018..07822f0 100644 --- a/tests/wikidataquery_tests.py +++ b/tests/wikidataquery_tests.py @@ -19,9 +19,11 @@ import time -class TestApiFunctions(WikidataTestCase): +class TestDryApiFunctions(TestCase): """Test WikiDataQuery API functions.""" + + net = False def testQueries(self): """ @@ -89,6 +91,13 @@ q = query.HasClaim(99, query.Tree(1, [2, 5], [3, 90])) self.assertEqual(str(q), "claim[99:(tree[1][2,5][3,90])]") + + +class TestLiveApiFunctions(WikidataTestCase): + + """Test WikiDataQuery API functions.""" + + cached = True def testQueriesWDStructures(self): """Test queries using Wikibase page structures like ItemPage.""" @@ -217,7 +226,11 @@ """Test slow WikiDataQuery API functions.""" - net = True + sites = { + 'wdq': { + 'hostname': 'wdq.wmflabs.org', + }, + } def testQueryApiGetter(self): """Test that we can actually retreive data and that caching works.""" diff --git a/tests/wikistats_tests.py b/tests/wikistats_tests.py index c9e8532..deda834 100644 --- a/tests/wikistats_tests.py +++ b/tests/wikistats_tests.py @@ -22,7 +22,11 @@ """Test WikiStats dump.""" - net = True + sites = { + 'wikistats': { + 'hostname': 'wikistats.wmflabs.org', + }, + } def test_sort(self): ws = WikiStats() -- To view, visit https://gerrit.wikimedia.org/r/177985 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I8fdcdaa0fab3b680d35b81b20a12ff5b786f779d Gerrit-PatchSet: 10 Gerrit-Project: pywikibot/core Gerrit-Branch: master Gerrit-Owner: John Vandenberg <jay...@gmail.com> Gerrit-Reviewer: John Vandenberg <jay...@gmail.com> Gerrit-Reviewer: Ladsgroup <ladsgr...@gmail.com> Gerrit-Reviewer: Merlijn van Deen <valhall...@arctus.nl> Gerrit-Reviewer: XZise <commodorefabia...@gmx.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ Pywikibot-commits mailing list Pywikibot-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/pywikibot-commits