jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/582299 )
Change subject: [tests] decorate MW version ......................................................................
[tests] decorate MW version
Bug: T130516 Change-Id: Ic3790694f540614828b0c4303de4091bdd613c48 --- M tests/README.rst M tests/api_tests.py M tests/aspects.py M tests/edit_tests.py M tests/site_generators_tests.py 5 files changed, 71 insertions(+), 23 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/tests/README.rst b/tests/README.rst index 7c62773..acc4b21 100644 --- a/tests/README.rst +++ b/tests/README.rst @@ -207,6 +207,17 @@ @require_modules(['important1', 'musthave2']) def test_require_modules(self):
+@tests.aspects.require_version +------------------------------ +Require a given MediaWiki version + +:: + + from tests.aspects import require_version + [......] + @require_version('>=1.27.0') + def test_require_version(self): + @unittest.mock.patch ----------------------- Replaces `target` with object specified in `new`. Refer to mock's documentation. diff --git a/tests/api_tests.py b/tests/api_tests.py index e945abd..560356e 100755 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -18,7 +18,9 @@ from pywikibot.exceptions import APIError, NoUsernameError from pywikibot.throttle import Throttle from pywikibot.tools import suppress_warnings + from tests.aspects import ( + require_version, DefaultDrySiteTestCase, DefaultSiteTestCase, TestCase, @@ -292,13 +294,10 @@
self.assertIn('query+revisions', pi.prefix_map)
+ @require_version('>=1.25wmf4', 'support the new paraminfo api') def test_new_mode(self): """Test the new modules-only mode explicitly.""" site = self.get_site() - if site.mw_version < '1.25wmf4': - self.skipTest( - "version {} doesn't support the new paraminfo api" - .format(site.mw_version)) pi = api.ParamInfo(site, modules_only_mode=True) pi.fetch(['info']) self.assertIn('query+info', pi._paraminfo) diff --git a/tests/aspects.py b/tests/aspects.py index 36709de..60c442d 100644 --- a/tests/aspects.py +++ b/tests/aspects.py @@ -19,6 +19,7 @@ import warnings from collections.abc import Sized from contextlib import contextmanager, suppress +from functools import wraps from http import HTTPStatus from unittest.util import safe_repr
@@ -35,6 +36,7 @@ from pywikibot.family import WikimediaFamily from pywikibot.site import BaseSite from pywikibot.tools import suppress_warnings +from pywikibot.tools import MediaWikiVersion # noqa: F401 (used by f-string) from tests import ( WARN_SITE_CODE, patch_request, @@ -311,6 +313,59 @@ return test_requirement
+def require_version(version_needed: str, reason: str = ''): + """Require minimum MediaWiki version to be queried. + + The version needed for the test; must be given with a preleading rich + comparisons operator like ``<1.27wmf4`` or ``>=1.39``. If the + comparison does not match the test will be skipped. + + This decorator can only be used for TestCase having a single site. + It cannot be used for DrySite tests. In addition version comparison + for other than the current site e.g. for the related data or image + repositoy of the current site is ot possible. + + .. versionadded:: 8.0.0 + + :param version_needed: The version needed + :param reason: A reason for skipping the test. + :raises Exception: Usage validation fails + """ + def test_requirement(method): + """Test the requirement and return an optionally decorated object.""" + @wraps(method) + def wrapper(self, *args, **kwargs): + """Validate environment.""" + if not isinstance(self.site, BaseSite) \ + or isinstance(self.site, DrySite): + raise Exception( + f'{type(self).__name__}.site must be a BaseSite not ' + f'{type(self.site).__name__}.') + + if args or kwargs: + raise Exception( + f'Test method {method.__name__!r} has parameters which is ' + f'not supported with require_version decorator.') + + _, op, version = re.split('([<>]=?)', version_needed) + if not op: + raise Exception(f'There is no valid operator given with ' + f'version {version_needed!r}') + + skip = not eval( + f'self.site.mw_version {op} MediaWikiVersion(version)') + if not skip: + return method(self, *args, **kwargs) + + myreason = ' to ' + reason if reason else '' + raise unittest.SkipTest( + f'MediaWiki {op} v{version} required{myreason}.') + + return wrapper + + return test_requirement + + class DisableSiteMixin(TestCaseBase):
"""Test cases not connected to a Site object. diff --git a/tests/edit_tests.py b/tests/edit_tests.py index 6fb8834..e967087 100755 --- a/tests/edit_tests.py +++ b/tests/edit_tests.py @@ -12,7 +12,7 @@ import pywikibot from pywikibot import config, page_put_queue from pywikibot.exceptions import Error -from tests.aspects import TestCase +from tests.aspects import TestCase, require_version from tests.oauth_tests import OAuthSiteTestCase
@@ -79,17 +79,13 @@ write = True rights = 'mergehistory'
+ @require_version('>=1.27.0wmf.13', 'support the history merge API') def setup_test_pages(self): """Helper function to set up pages that we will use in these tests.""" site = self.get_site() source = pywikibot.Page(site, 'User:Sn1per/MergeTest1') dest = pywikibot.Page(site, 'User:Sn1per/MergeTest2')
- # Make sure the wiki supports action=mergehistory - if site.mw_version < '1.27.0-wmf.13': - self.skipTest('Wiki version must be 1.27.0-wmf.13 or newer to ' - 'support the history merge API.') - if source.exists(): source.delete('Pywikibot merge history unit test') if dest.exists(): diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py index ba0b11c..7f02d86 100644 --- a/tests/site_generators_tests.py +++ b/tests/site_generators_tests.py @@ -110,9 +110,6 @@
def test_page_redirects(self): """Test Site.page_redirects.""" - if self.get_site().mw_version < '1.24': - self.skipTest('site.page_redirects() needs mw 1.24') - redirects_ns_0 = set(self.site.page_redirects( self.mainpage, namespaces=0, @@ -1262,13 +1259,6 @@
login = True
- @classmethod - def setUpClass(cls): - """Skip test if necessary.""" - super().setUpClass() - if cls.site.mw_version < '1.25': - cls.skipTest(cls, 'site.alldeletedrevisions() needs mw 1.25') - def test_basic(self): """Test the site.alldeletedrevisions() method.""" mysite = self.get_site() @@ -1430,9 +1420,6 @@ def test_prefix(self): """Test the site.alldeletedrevisions() method with prefix.""" mysite = self.get_site() - if mysite.mw_version < '1.25': - self.skipTest('site.alldeletedrevisions() needs mw 1.25') - for data in mysite.alldeletedrevisions(prefix='John', total=5): self.assertIsInstance(data, dict) for key in ('title', 'ns', 'revisions'):
pywikibot-commits@lists.wikimedia.org