def fail(self, message, path=None): from _pytest.outcomes import Failed __tracebackhide__ = True self.success = self.FAIL log.error(message) raise Failed(message) from None
def warns(warningcls, **kwargs): '''Like raises but tests that warnings are emitted. >>> from sympy.utilities.pytest import warns >>> import warnings >>> with warns(UserWarning): ... warnings.warn('deprecated', UserWarning) >>> with warns(UserWarning): ... pass Traceback (most recent call last): ... Failed: DID NOT WARN. No warnings of type UserWarning\ was emitted. The list of emitted warnings is: []. ''' match = kwargs.pop('match', '') if kwargs: raise TypeError('Invalid keyword arguments: %s' % kwargs) # Absorbs all warnings in warnrec with warnings.catch_warnings(record=True) as warnrec: # Hide all warnings but make sure that our warning is emitted warnings.simplefilter("ignore") warnings.filterwarnings("always", match, warningcls) # Now run the test yield # Raise if expected warning not found if not any(issubclass(w.category, warningcls) for w in warnrec): msg = ('Failed: DID NOT WARN.' ' No warnings of type %s was emitted.' ' The list of emitted warnings is: %s.' ) % (warningcls, [w.message for w in warnrec]) raise Failed(msg)
def fail(self, message, path=None): from _pytest.outcomes import Failed __tracebackhide__ = True self.success = self.FAIL if path: message += " at " + format_path(path) log.error(message) raise Failed(message) from None
def runner(fspath, context: dict = None): __tracebackhide__ = True fspath = request.fspath.dirpath(fspath) for item in get_request_items(fspath, parent=request.node, context=context): try: item.runtest() except Exception as err: msg = "File: {}\nFail: {.name}{}".format(fspath, item, err) raise Failed(msg=msg, pytrace=False)
def raises(expectedException, code=None): """ Tests that ``code`` raises the exception ``expectedException``. ``code`` may be a callable, such as a lambda expression or function name. If ``code`` is not given or None, ``raises`` will return a context manager for use in ``with`` statements; the code to execute then comes from the scope of the ``with``. ``raises()`` does nothing if the callable raises the expected exception, otherwise it raises an AssertionError. Examples ======== >>> from sympy.utilities.pytest import raises >>> raises(ZeroDivisionError, lambda: 1/0) >>> raises(ZeroDivisionError, lambda: 1/2) Traceback (most recent call last): ... Failed: DID NOT RAISE >>> with raises(ZeroDivisionError): ... n = 1/0 >>> with raises(ZeroDivisionError): ... n = 1/2 Traceback (most recent call last): ... Failed: DID NOT RAISE Note that you cannot test multiple statements via ``with raises``: >>> with raises(ZeroDivisionError): ... n = 1/0 # will execute and raise, aborting the ``with`` ... n = 9999/0 # never executed This is just what ``with`` is supposed to do: abort the contained statement sequence at the first exception and let the context manager deal with the exception. To test multiple statements, you'll need a separate ``with`` for each: >>> with raises(ZeroDivisionError): ... n = 1/0 # will execute and raise >>> with raises(ZeroDivisionError): ... n = 9999/0 # will also execute and raise """ if code is None: return RaisesContext(expectedException) elif callable(code): try: code() except expectedException: return raise Failed("DID NOT RAISE") elif isinstance(code, str): raise TypeError( '\'raises(xxx, "code")\' has been phased out; ' 'change \'raises(xxx, "expression")\' ' 'to \'raises(xxx, lambda: expression)\', ' '\'raises(xxx, "statement")\' ' 'to \'with raises(xxx): statement\'') else: raise TypeError( 'raises() expects a callable for the 2nd argument.')
def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: raise Failed("DID NOT RAISE") return issubclass(exc_type, self.expectedException)
def warns(warningcls, *, match='', test_stacklevel=True): ''' Like raises but tests that warnings are emitted. >>> from sympy.testing.pytest import warns >>> import warnings >>> with warns(UserWarning): ... warnings.warn('deprecated', UserWarning, stacklevel=2) >>> with warns(UserWarning): ... pass Traceback (most recent call last): ... Failed: DID NOT WARN. No warnings of type UserWarning\ was emitted. The list of emitted warnings is: []. ``test_stacklevel`` makes it check that the ``stacklevel`` parameter to ``warn()`` is set so that the warning shows the user line of code (the code under the warns() context manager). Set this to False if this is ambiguous or if the context manager does not test the direct user code that emits the warning. If the warning is a ``SymPyDeprecationWarning``, this additionally tests that the ``active_deprecations_target`` is a real target in the ``active-deprecations.md`` file. ''' # Absorbs all warnings in warnrec with warnings.catch_warnings(record=True) as warnrec: # Any warning other than the one we are looking for is an error warnings.simplefilter("error") warnings.filterwarnings("always", category=warningcls) # Now run the test yield warnrec # Raise if expected warning not found if not any(issubclass(w.category, warningcls) for w in warnrec): msg = ('Failed: DID NOT WARN.' ' No warnings of type %s was emitted.' ' The list of emitted warnings is: %s.') % ( warningcls, [w.message for w in warnrec]) raise Failed(msg) # We don't include the match in the filter above because it would then # fall to the error filter, so we instead manually check that it matches # here for w in warnrec: # Should always be true due to the filters above assert issubclass(w.category, warningcls) if not re.compile(match, re.I).match(str(w.message)): raise Failed( f"Failed: WRONG MESSAGE. A warning with of the correct category ({warningcls.__name__}) was issued, but it did not match the given match regex ({match!r})" ) if test_stacklevel: for f in inspect.stack(): thisfile = f.filename file = os.path.split(thisfile)[1] if file.startswith('test_'): break elif file == 'doctest.py': # skip the stacklevel testing in the doctests of this # function return else: raise RuntimeError( "Could not find the file for the given warning to test the stacklevel" ) for w in warnrec: if w.filename != thisfile: msg = f'''\ Failed: Warning has the wrong stacklevel. The warning stacklevel needs to be set so that the line of code shown in the warning message is user code that calls the deprecated code (the current stacklevel is showing code from {w.filename} (line {w.lineno}), expected {thisfile})'''.replace('\n', ' ') raise Failed(msg) if warningcls == SymPyDeprecationWarning: this_file = pathlib.Path(__file__) active_deprecations_file = (this_file.parent.parent.parent / 'doc' / 'src' / 'explanation' / 'active-deprecations.md') if not active_deprecations_file.exists(): # We can only test that the active_deprecations_target works if we are # in the git repo. return targets = [] for w in warnrec: targets.append(w.message.active_deprecations_target) with open(active_deprecations_file) as f: text = f.read() for target in targets: if f'({target})=' not in text: raise Failed( f"The active deprecations target {target!r} does not appear to be a valid target in the active-deprecations.md file ({active_deprecations_file})." )
def verify(self, provider_url, provider_setup): try: self.interaction.verify_with_callable_setup(provider_url, provider_setup) except (Failed, AssertionError) as e: raise Failed(str(e)) from None