XZise has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/239757

Change subject: [WIP][IMPROV] tests: Hostname check as decorator
......................................................................

[WIP][IMPROV] tests: Hostname check as decorator

This implements the hostname checks as a decorator so it's not necessary to
subclass from `CheckHostnameMixin` implicitly.

Change-Id: I6401e11601bd1c714a4c5b038bb2c9de18371241
---
M tests/aspects.py
M tests/wikistats_tests.py
2 files changed, 76 insertions(+), 29 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/57/239757/1

diff --git a/tests/aspects.py b/tests/aspects.py
index fa0e486..7ef6a6d 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -274,23 +274,51 @@
         super(TestTimerMixin, self).tearDown()
 
 
-def require_modules(*required_modules):
-    """Require that the given list of modules can be imported."""
-    def test_requirement(obj):
+class RequirementDecorator(object):
+
+    """Utility class to write decorators which require something."""
+
+    @classmethod
+    def decorator(cls, *args, **kwargs):
+        """Create new instance and return decorate method."""
+        return cls(*args, **kwargs).decorate
+
+    def decorate(self, obj):
         """Test the requirement and return an optionally decorated object."""
+        reason = self.test_requirement()
+        if reason:
+            return unittest.skip(reason)(obj)
+        else:
+            return obj
+
+    def test_requirement(self):
+        """Test whether the requirement is met and return the reason if not."""
+        raise NotImplementedError()
+
+
+class CheckModules(RequirementDecorator):
+
+    """Require that the given list of modules can be imported."""
+
+    def __init__(self, *modules):
+        """Create new decorator instance requiring the given modules."""
+        self.required_modules = modules
+
+    def test_requirement(self):
+        """Test that the required modules can be imported."""
         missing = []
-        for required_module in required_modules:
+        for required_module in self.required_modules:
             try:
                 __import__(required_module, globals(), locals(), [], 0)
             except ImportError:
                 missing += [required_module]
         if missing:
-            return unittest.skip('{0} not installed'.format(
-                ', '.join(missing)))(obj)
+            return '{0} not installed'.format(', '.join(missing))
         else:
-            return obj
+            return None
 
-    return test_requirement
+
+require_modules = CheckModules.decorator
 
 
 class DisableSiteMixin(TestCaseBase):
@@ -417,8 +445,6 @@
 
     """Check the hostname is online before running tests."""
 
-    _checked_hostnames = {}
-
     @classmethod
     def setUpClass(cls):
         """
@@ -431,21 +457,38 @@
         if not hasattr(cls, 'sites'):
             return
 
+        hostnames = []
         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']
+            hostnames += [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))
+        reason = CheckHostname(*hostnames).test_requirement()
+        if reason is not None:
+            raise unittest.SkipTest('{0}: {1}'.format(cls.__name__, reason))
+
+
+class CheckHostname(RequirementDecorator):
+
+    """Require that the given list of hostnames can be accessed."""
+
+    _checked_hostnames = {}
+
+    def __init__(self, *hostnames):
+        """Create new instance with the given hostnames."""
+        self.hostnames = hostnames
+
+    def test_requirement(self):
+        """Iterate over each hostname and test their availability."""
+        for hostname in self.hostnames:
+
+            if hostname in self._checked_hostnames:
+                if isinstance(self._checked_hostnames[hostname], Exception):
+                    return 'hostname {0} failed (cached): {1}'.format(
+                        hostname, self._checked_hostnames[hostname])
+                elif self._checked_hostnames[hostname] is False:
+                    return 'hostname {0} failed (cached)'.format(hostname)
                 else:
                     continue
 
@@ -462,19 +505,22 @@
                     if r.status not in [200, 301, 302, 303, 307, 308]:
                         raise ServerError('HTTP status: %d' % r.status)
             except Exception as e2:
-                pywikibot.error('%s: accessing %s caused exception:'
-                                % (cls.__name__, hostname))
+                pywikibot.error(
+                    'accessing {0} caused exception:'.format(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))
+                self._checked_hostnames[hostname] = e
+                return 'hostname {0} failed: {1}'.format(hostname, e)
 
-            cls._checked_hostnames[hostname] = True
+            self._checked_hostnames[hostname] = True
+
+        return None
+
+
+check_hostnames = CheckHostname.decorator
 
 
 class SiteWriteMixin(TestCaseBase):
diff --git a/tests/wikistats_tests.py b/tests/wikistats_tests.py
index 883c146..c603c7c 100644
--- a/tests/wikistats_tests.py
+++ b/tests/wikistats_tests.py
@@ -14,17 +14,18 @@
 
 from pywikibot.data.wikistats import WikiStats, csv
 
-from tests.aspects import unittest, TestCase
+from tests.aspects import unittest, check_hostnames, TestCase
 
 if sys.version_info[0] == 3:
     basestring = (str, )
 
 
+@check_hostnames('https://wikistats.wmflabs.org/api.php')
 class WikiStatsTestCase(TestCase):
 
     """Test WikiStats dump."""
 
-    hostname = 'https://wikistats.wmflabs.org/api.php'
+    net = True
 
     def test_sort(self):
         """Test sorted results."""

-- 
To view, visit https://gerrit.wikimedia.org/r/239757
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6401e11601bd1c714a4c5b038bb2c9de18371241
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <commodorefabia...@gmx.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to