patch, patch.object and create_autospec silently ignore misspelled
arguments such as autospect, auto_spec and set_spec. This can lead
to tests failing to check what they are supposed to check.
This change adds a check causing a RuntimeError if the above
functions get any of the above misspellings as arguments. It also
adds a new argument, "unsafe", which can be set to True to disable
this check.
Also add "!r" to format specifiers in added error messages.
This is a follow-up to
4662fa9bfe.
That original commit expanded guards against misspelling assertions on
mocks. This follow-up updates the documentation and improves the error
message by pointing out the potential cause and solution.
Automerge-Triggered-By: GH:gpshead
Currently, a Mock object which is not unsafe will raise an
AttributeError if an attribute with the prefix assert or assret is
accessed on it. This protects against misspellings of real assert
method calls, which lead to tests passing silently even if the tested
code does not satisfy the intended assertion.
Recently a check was done in a large code base (Google) and three
more frequent ways of misspelling assert were found causing harm:
asert, aseert, assrt. These are now added to the existing check.
unittest.TestCase.assertWarns no longer raises a RuntimeException
when accessing a module's ``__warningregistry__`` causes importation of a new
module, or when a new module is imported in another thread.
Patch by Kernc.
* use the `: pass` and `: yield` patterns for code that isn't expected to ever be executed.
* The _Call items passed to _AnyComparer are only ever of length two, so assert instead of if/else
* fix typo
* Fix bug, where stop-without-start patching dict blows up with `TypeError: 'NoneType' object is not iterable`, highlighted by lack of coverage of an except branch.
* The fix for bpo-37972 means _Call.count and _Call.index are no longer needed.
* add coverage for calling next() on a mock_open with readline.return_value set.
* __aiter__ is defined on the Mock so the one on _AsyncIterator is never called.
Replace check for whether something is a method in the mock module. The
previous version fails on PyPy, because there no method wrappers exist
(everything looks like a regular Python-defined function). Thus the
isinstance(getattr(result, '__get__', None), MethodWrapperTypes) check
returns True for any descriptor, not just methods.
This condition could also return erroneously True in CPython for
C-defined descriptors.
Instead to decide whether something is a method, just check directly
whether it's a function defined on the class. This passes all tests on
CPython and fixes the bug on PyPy.
- The gc.collect is needed for other implementations, such as pypy
- Using context managers over multiple lines will only catch the warning from the first line in the context!
- remove a skip for a test that no longer fails on pypy
As the function was not registering in the active patches, the mocks
started by `mock.patch.dict` were not being stopped when
`mock.patch.stopall` was being called.
* Add test for nested async decorator patch.
* Add test for side_effect and wraps with a function.
* Add test for side_effect with an exception in the iterable.
Capturing exceptions into names can lead to reference cycles though the __traceback__ attribute of the exceptions in some obscure cases that have been reported previously and fixed individually. As these variables are not used anyway, we can remove the binding to reduce the chances of creating reference cycles.
See for example GH-13135
The fix in PR 13261 handled the underlying issue about the spec for specific methods not being applied correctly, but it didn't fix the issue that was causing the misleading error message.
The code currently grabs a list of responses from _call_matcher (which may include exceptions). But it doesn't reach inside the list when checking if the result is an exception. This results in a misleading error message when one of the provided calls does not match the spec.
https://bugs.python.org/issue36871
Automerge-Triggered-By: @gpshead
In the format string for assert_called the evaluation order is incorrect and hence for mock's without name, 'None' is printed whereas it should be 'mock' like for other messages. The error message is ("Expected '%s' to have been called." % self._mock_name or 'mock').
* Flip equality to use mock calls' __eq__
* bpo-37555: Regression test demonstrating assert_has_calls not working with ANY and spec_set
Co-authored-by: Neal Finne <neal@nealfinne.com>
* Revert "Flip equality to use mock calls' __eq__"
This reverts commit 94ddf54c5a.
* bpo-37555: Add regression tests for mock ANY ordering issues
Add regression tests for whether __eq__ is order agnostic on _Call and _CallList, which is useful for comparisons involving ANY, especially if the ANY comparison is to a class not defaulting __eq__ to NotImplemented.
Co-authored-by: Neal Finne <neal@nealfinne.com>
* bpo-37555: Fix _CallList and _Call order sensitivity
_Call and _CallList depend on ordering to correctly process that an object being compared to ANY with __eq__ should return True. This fix updates the comparison to check both a == b and b == a and return True if either condition is met, fixing situations from the tests in the previous two commits where assertEqual would not be commutative if checking _Call or _CallList objects. This seems like a reasonable fix considering that the Python data model specifies that if an object doesn't know how to compare itself to another object it should return NotImplemented, and that on getting NotImplemented from a == b, it should try b == a, implying that good behavior for __eq__ is commutative. This also flips the order of comparison in _CallList's __contains__ method, guaranteeing ANY will be on the left and have it's __eq__ called for equality checking, fixing the interaction between assert_has_calls and ANY.
Co-author: Neal Finne <neal@neal.finne.com>
* bpo-37555: Ensure _call_matcher returns _Call object
* Adding ACK and news entry
* bpo-37555: Replacing __eq__ with == to sidestep NotImplemented
bool(NotImplemented) returns True, so it's necessary to use ==
instead of __eq__ in this comparison.
* bpo-37555: cleaning up changes unnecessary to the final product
* bpo-37555: Fixed call on bound arguments to respect args and kwargs
* Revert "bpo-37555: Add regression tests for mock ANY ordering issues"
This reverts commit 49c5310ad4.
* Revert "bpo-37555: cleaning up changes unnecessary to the final product"
This reverts commit 18e964ba01.
* Revert "bpo-37555: Replacing __eq__ with == to sidestep NotImplemented"
This reverts commit f295eaca5b.
* Revert "bpo-37555: Fix _CallList and _Call order sensitivity"
This reverts commit 874fb697b8.
* Updated NEWS.d
* bpo-37555: Add tests checking every function using _call_matcher both with and without spec
* bpo-37555: Ensure all assert methods using _call_matcher are actually passing calls
* Remove AnyCompare and use call objects everywhere.
* Revert "Remove AnyCompare and use call objects everywhere."
This reverts commit 24973c0b32.
* Check for exception in assert_any_await
* bpo-37972: unittest.mock._Call now passes on __getitem__ to the __getattr__ chaining so that call() can be subscriptable
* 📜🤖 Added by blurb_it.
* Update 2019-08-28-21-40-12.bpo-37972.kP-n4L.rst
added name of the contributor
* bpo-37972: made all dunder methods chainable for _Call
* bpo-37972: delegate only attributes of tuple instead to __getattr__
* Fix call_matcher for mock when using methods
* Add NEWS entry
* Use None check and convert doctest to unittest
* Use better name for mock in tests. Handle _SpecState when the attribute was not accessed and add tests.
* Use reset_mock instead of reinitialization. Change inner class constructor signature for check
* Reword comment regarding call object lookup logic
* Clear name and parent of mock in autospecced objects used with attach_mock
* Add NEWS entry
* Fix reversed order of comparison
* Test child and standalone function calls
* Use a helper function extracting mock to avoid code duplication and refactor tests.
Add explicit `asyncSetUp` and `asyncTearDown` methods.
The rest is the same as for #13228
`AsyncTestCase` create a loop instance for every test for the sake of test isolation.
Sometimes a loop shared between all tests can speed up tests execution time a lot but it requires control of closed resources after every test finish. Basically, it requires nested supervisors support that was discussed with @1st1 many times. Sorry, asyncio supervisors have no chance to land on Python 3.8.
The PR intentionally does not provide API for changing the used event loop or getting the test loop: use `asyncio.set_event_loop_policy()` and `asyncio.get_event_loop()` instead.
The PR adds four overridable methods to base `unittest.TestCase` class:
```
def _callSetUp(self):
self.setUp()
def _callTestMethod(self, method):
method()
def _callTearDown(self):
self.tearDown()
def _callCleanup(self, function, /, *args, **kwargs):
function(*args, **kwargs)
```
It allows using asyncio facilities with minimal influence on the unittest code.
The last but not least: the PR respects contextvars. The context variable installed by `asyncSetUp` is available on test, `tearDown` and a coroutine scheduled by `addCleanup`.
https://bugs.python.org/issue32972
* Fix the implicit string concatenation in `assert_has_awaits` error message.
* Use "await" instead of "call" in `assert_awaited_with` error message.
https://bugs.python.org/issue37075
Return a coroutine while patching async functions with a decorator.
Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
https://bugs.python.org/issue36996
This was achieved by:
* moving many pass statements in tests onto their own lines, so they pass line coverage and can match an easy ignore pattern if branch coverage is added later.
* removing code that cannot be reached.
* removing long-disabled tests.
* removing unused code.
* adding tests for uncovered code
It turned out that removing `if __name__ == '__main__'` blocks that run unittest.main() at the bottom of test files was surprisingly contentious, so they remain and can be filtered out with an appropriate .coveragerc.
When an attribute is deleted from a Mock, a sentinel is added rather
than just deleting the attribute. This commit checks for such sentinels
when returning the child mocks in the __dir__ method as users won't
expect deleted attributes to appear when performing dir(mock).
In Python having a trace function in effect while mock is imported causes isinstance to be wrong for MagicMocks. This is due to the usage of super() in some class methods, as this sets the __class__ attribute. To avoid this, as a workaround, alias the usage of super .
Deprecated passing the following arguments as keyword arguments:
- "func" in functools.partialmethod(), weakref.finalize(),
profile.Profile.runcall(), cProfile.Profile.runcall(),
bdb.Bdb.runcall(), trace.Trace.runfunc() and
curses.wrapper().
- "function" in unittest.addModuleCleanup() and
unittest.TestCase.addCleanup().
- "fn" in the submit() method of concurrent.futures.ThreadPoolExecutor
and concurrent.futures.ProcessPoolExecutor.
- "callback" in contextlib.ExitStack.callback(),
contextlib.AsyncExitStack.callback() and
contextlib.AsyncExitStack.push_async_callback().
- "c" and "typeid" in the create() method of multiprocessing.managers.Server
and multiprocessing.managers.SharedMemoryServer.
- "obj" in weakref.finalize().
Also allowed to pass arbitrary keyword arguments (even "self" and "func")
if the above arguments are passed as positional argument.
Return None after calling unittest.mock.patch.object.stop() regardless of whether the object was started. This makes the method idempotent.
https://bugs.python.org/issue36366
* Resolve string target to patch.dict during function call
* Add NEWS entry
* Remove unneeded call
* Restore original value for support.target and refactor assertions
* Add extra assertion to verify unpatched dict
TextTestRunner of unittest.runner now uses time.perf_counter() rather
than time.time() to measure the execution time of a test: time.time()
can go backwards, whereas time.perf_counter() is monotonic.
Similar change made in libregrtest, pprint and random.
* Fix partial and partial method signatures in mock
* Add more calls
* Add NEWS entry
* Use assertEquals and fix markup in NEWS
* Refactor branching and add markup reference for functools
* Revert partial object related changes and fix pr comments
* tests: Further validate `wraps` functionality in `unittest.mock.Mock`
Add more tests to validate how `wraps` interacts with other features of
mocks.
* Don't call the wrapped object if `side_effect` is set
When a object is wrapped using `Mock(wraps=...)`, if an user sets a
`side_effect` in one of their methods, return the value of `side_effect`
and don't call the original object.
* Refactor what to be called on `mock_call`
When a `Mock` is called, it should return looking up in the following
order: `side_effect`, `return_value`, `wraps`. If any of the first two
return `mock.DEFAULT`, lookup in the next option.
It makes no sense to check for `wraps` returning default, as it is
supposed to be the original implementation and there is nothing to
fallback to.
Two kind of mistakes:
1. Missed space. After concatenating there is no space between words.
2. Missed comma. Causes unintentional concatenating in a list of strings.
The MagicMock class supports many magic methods, but not __fspath__. To ease
testing with modules such as os.path, this function is now supported by default.
Only make sure that the result is in unittest.signals._results, don't
check the full content of unittest.signals._results.
support._run_suite() uses TextTestRunner in verbose mode, but
TextTestRunner.run() calls registerResult(result) which made the test
fail with "odd object in result set".
Call also removeResult() to restore unittest.signals._results to
avoid test side effect.
* Fix multiple typos in code comments
* Add spacing in comments (test_logging.py, test_math.py)
* Fix spaces at the beginning of comments in test_logging.py
Rather than supporting dev mode directly in the warnings module, this
instead adjusts the initialisation code to add an extra 'default'
entry to sys.warnoptions when dev mode is enabled.
This ensures that dev mode behaves *exactly* as if `-Wdefault` had
been passed on the command line, including in the way it interacts
with `sys.warnoptions`, and with other command line flags like `-bb`.
Fix also bpo-20361: have -b & -bb options take precedence over any
other warnings options.
Patch written by Nick Coghlan, with minor modifications of Victor Stinner.
The new method allows the developer to control when to stop the
feature of mocks that automagically creates new mocks when accessing
an attribute that was not declared before
Signed-off-by: Mario Corchero <mariocj89@gmail.com>
Cython will, in the right circumstances, offer a MethodType instance
where im_func is a builtin function. Any instance of MethodType is
automatically assumed to be a Python-defined function (more
specifically, a function that has an inspectable signature), but
_set_signature was still conservative in its assumptions. As a result
_set_signature would return early with None instead of a mock since
the im_func had no inspectable signature. This causes problems
deeper inside mock, as _set_signature is assumed to _always_
return a mock, and nothing checked its return value.
In similar corner cases, autospec will simply not check the spec of the
function, so _set_signature is amended to now return early with the
original, not-wrapped mock object.
Patch by Aaron Gallagher.
bpo-11798, bpo-16662, bpo-16935, bpo-30813: Skip
test_discover_with_module_that_raises_SkipTest_on_import() and
test_discover_with_init_module_that_raises_SkipTest_on_import() of
test_unittest when hunting reference leaks using regrtest.
* #30190 / unittest / assertAlmostEqual(delta=...) / error msg: show the difference between the 2 numbers in case of failure
* safe_repr() diff
* also show difference when passing 'places' argument
* refactoring
* update Misc/NEWS