jenkins-bot has submitted this change and it was merged. Change subject: [FEAT] Support assertAPIError ......................................................................
[FEAT] Support assertAPIError To assert a specific APIError the base class supports `assertAPIError` which wraps around `assertRaises` and additionally checks if the error is of a specific code and optionally a specific info. Like `assertRaises` it can be used as a context manager when additional checks should be done afterwards. Change-Id: Ib211974ec3acd17fb45c2280e084723257a88650 --- M tests/aspects.py M tests/upload_tests.py M tests/utils.py 3 files changed, 72 insertions(+), 6 deletions(-) Approvals: John Vandenberg: Looks good to me, approved jenkins-bot: Verified diff --git a/tests/aspects.py b/tests/aspects.py index 0503077..2dfcc09 100644 --- a/tests/aspects.py +++ b/tests/aspects.py @@ -56,7 +56,7 @@ from tests import unittest, patch_request, unpatch_request from tests.utils import ( add_metaclass, execute_pwb, DrySite, DryRequest, - WarningSourceSkipContextManager, + WarningSourceSkipContextManager, AssertAPIErrorContextManager, ) OSWIN32 = (sys.platform == 'win32') @@ -263,6 +263,33 @@ assertPagelistTitles = assertPageTitlesEqual + def assertAPIError(self, code, info=None, callable_obj=None, *args, + **kwargs): + """ + Assert that a specific APIError wrapped around L{assertRaises}. + + If no callable object is defined and it returns a context manager, that + context manager will return the underlying context manager used by + L{assertRaises}. So it's possible to access the APIError by using it's + C{exception} attribute. + + @param code: The code of the error which must have happened. + @type code: str + @param info: The info string of the error or None if no it shouldn't be + checked. + @type info: str or None + @param callable_obj: The object that will be tested. If None it returns + a context manager like L{assertRaises}. + @type callable_obj: callable + @param args: The positional arguments forwarded to the callable object. + @param kwargs: The keyword arguments forwared to the callable object. + @return: The context manager if callable_obj is None and None otherwise. + @rtype: None or context manager + """ + msg = kwargs.pop('msg', None) + return AssertAPIErrorContextManager( + code, info, msg, self).handle(callable_obj, args, kwargs) + class TestTimerMixin(TestCaseBase): diff --git a/tests/upload_tests.py b/tests/upload_tests.py index a7987d8..7968f01 100644 --- a/tests/upload_tests.py +++ b/tests/upload_tests.py @@ -15,8 +15,6 @@ import pywikibot -from pywikibot.data.api import APIError - from tests import join_images_path from tests.aspects import unittest, TestCase @@ -103,9 +101,8 @@ self._finish_upload(chunk_size, self.sounds_png) # Check if it's still cached - with self.assertRaises(APIError) as cm: + with self.assertAPIError('siiinvalidsessiondata') as cm: self.site.stash_info(self._file_key) - self.assertEqual(cm.exception.code, 'siiinvalidsessiondata') self.assertTrue(cm.exception.info.startswith('File not found'), 'info ({0}) did not start with ' '"File not found"'.format(cm.exception.info)) diff --git a/tests/utils.py b/tests/utils.py index 7cb96d6..6884cb1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -32,7 +32,7 @@ from pywikibot import config from pywikibot.comms import threadedhttp from pywikibot.site import Namespace -from pywikibot.data.api import CachedRequest +from pywikibot.data.api import CachedRequest, APIError from pywikibot.data.api import Request as _original_Request from pywikibot.tools import ( PYTHON_VERSION, @@ -244,6 +244,48 @@ return log +class AssertAPIErrorContextManager(object): + + """ + Context manager to assert certain APIError exceptions. + + This is build similar to the L{unittest.TestCase.assertError} implementation + which creates an context manager. It then calls L{handle} which either + returns this manager if no executing object given or calls the callable + object. + """ + + def __init__(self, code, info, msg, test_case): + """Create instance expecting the code and info.""" + self.code = code + self.info = info + self.msg = msg + self.test_case = test_case + + def __enter__(self): + """Enter this context manager and the unittest's context manager.""" + self.cm = self.test_case.assertRaises(APIError, msg=self.msg) + self.cm.__enter__() + return self.cm + + def __exit__(self, exc_type, exc_value, tb): + """Exit the context manager and assert code and optionally info.""" + result = self.cm.__exit__(exc_type, exc_value, tb) + assert result is isinstance(exc_value, APIError) + if result: + self.test_case.assertEqual(exc_value.code, self.code) + if self.info: + self.test_case.assertEqual(exc_value.info, self.info) + return result + + def handle(self, callable_obj, args, kwargs): + """Handle the callable object by returning itself or using itself.""" + if callable_obj is None: + return self + with self: + callable_obj(*args, **kwargs) + + class DryParamInfo(dict): """Dummy class to use instead of L{pywikibot.data.api.ParamInfo}.""" -- To view, visit https://gerrit.wikimedia.org/r/239683 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ib211974ec3acd17fb45c2280e084723257a88650 Gerrit-PatchSet: 3 Gerrit-Project: pywikibot/core Gerrit-Branch: master Gerrit-Owner: XZise <commodorefabia...@gmx.de> Gerrit-Reviewer: John Vandenberg <jay...@gmail.com> Gerrit-Reviewer: Ladsgroup <ladsgr...@gmail.com> Gerrit-Reviewer: XZise <commodorefabia...@gmx.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits