Skip to content

Commit adbf178

Browse files
authored
Mock 100% coverage (GH-13045)
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.
1 parent b7378d7 commit adbf178

File tree

9 files changed

+263
-317
lines changed

9 files changed

+263
-317
lines changed

Lib/unittest/mock.py

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ def _get_signature_object(func, as_instance, eat_self):
6363
"""
6464
if isinstance(func, type) and not as_instance:
6565
# If it's a type and should be modelled as a type, use __init__.
66-
try:
67-
func = func.__init__
68-
except AttributeError:
69-
return None
66+
func = func.__init__
7067
# Skip the `self` argument in __init__
7168
eat_self = True
7269
elif not isinstance(func, FunctionTypes):
@@ -147,8 +144,6 @@ def _set_signature(mock, original, instance=False):
147144
# creates a function with signature (*args, **kwargs) that delegates to a
148145
# mock. It still does signature checking by calling a lambda with the same
149146
# signature as the original.
150-
if not _callable(original):
151-
return
152147

153148
skipfirst = isinstance(original, type)
154149
result = _get_signature_object(original, instance, skipfirst)
@@ -175,10 +170,6 @@ def checksig(*args, **kwargs):
175170
def _setup_func(funcopy, mock, sig):
176171
funcopy.mock = mock
177172

178-
# can't use isinstance with mocks
179-
if not _is_instance_mock(mock):
180-
return
181-
182173
def assert_called_with(*args, **kwargs):
183174
return mock.assert_called_with(*args, **kwargs)
184175
def assert_called(*args, **kwargs):
@@ -263,12 +254,6 @@ def __reduce__(self):
263254
_deleted = sentinel.DELETED
264255

265256

266-
def _copy(value):
267-
if type(value) in (dict, list, tuple, set):
268-
return type(value)(value)
269-
return value
270-
271-
272257
_allowed_names = {
273258
'return_value', '_mock_return_value', 'side_effect',
274259
'_mock_side_effect', '_mock_parent', '_mock_new_parent',
@@ -351,8 +336,6 @@ def _check_and_set_parent(parent, value, name, new_name):
351336
class _MockIter(object):
352337
def __init__(self, obj):
353338
self.obj = iter(obj)
354-
def __iter__(self):
355-
return self
356339
def __next__(self):
357340
return next(self.obj)
358341

@@ -452,7 +435,7 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False,
452435
if isinstance(spec, type):
453436
_spec_class = spec
454437
else:
455-
_spec_class = _get_class(spec)
438+
_spec_class = type(spec)
456439
res = _get_signature_object(spec,
457440
_spec_as_instance, _eat_self)
458441
_spec_signature = res and res[1]
@@ -624,7 +607,7 @@ def _extract_mock_name(self):
624607
dot = '.'
625608
if _name_list == ['()']:
626609
dot = ''
627-
seen = set()
610+
628611
while _parent is not None:
629612
last = _parent
630613

@@ -635,11 +618,6 @@ def _extract_mock_name(self):
635618

636619
_parent = _parent._mock_new_parent
637620

638-
# use ids here so as not to call __hash__ on the mocks
639-
if id(_parent) in seen:
640-
break
641-
seen.add(id(_parent))
642-
643621
_name_list = list(reversed(_name_list))
644622
_first = last._mock_name or 'mock'
645623
if len(_name_list) > 1:
@@ -753,8 +731,6 @@ def _format_mock_failure_message(self, args, kwargs):
753731
message = 'expected call not found.\nExpected: %s\nActual: %s'
754732
expected_string = self._format_mock_call_signature(args, kwargs)
755733
call_args = self.call_args
756-
if len(call_args) == 3:
757-
call_args = call_args[1:]
758734
actual_string = self._format_mock_call_signature(*call_args)
759735
return message % (expected_string, actual_string)
760736

@@ -992,8 +968,6 @@ def _mock_call(_mock_self, *args, **kwargs):
992968
self.call_args = _call
993969
self.call_args_list.append(_call)
994970

995-
seen = set()
996-
997971
# initial stuff for method_calls:
998972
do_method_calls = self._mock_parent is not None
999973
method_call_name = self._mock_name
@@ -1029,13 +1003,6 @@ def _mock_call(_mock_self, *args, **kwargs):
10291003
# follow the parental chain:
10301004
_new_parent = _new_parent._mock_new_parent
10311005

1032-
# check we're not in an infinite loop:
1033-
# ( use ids here so as not to call __hash__ on the mocks)
1034-
_new_parent_id = id(_new_parent)
1035-
if _new_parent_id in seen:
1036-
break
1037-
seen.add(_new_parent_id)
1038-
10391006
effect = self.side_effect
10401007
if effect is not None:
10411008
if _is_exception(effect):
@@ -1858,12 +1825,7 @@ def _set_return_value(mock, method, name):
18581825

18591826
return_calulator = _calculate_return_value.get(name)
18601827
if return_calulator is not None:
1861-
try:
1862-
return_value = return_calulator(mock)
1863-
except AttributeError:
1864-
# XXXX why do we return AttributeError here?
1865-
# set it as a side_effect instead?
1866-
return_value = AttributeError(name)
1828+
return_value = return_calulator(mock)
18671829
method.return_value = return_value
18681830
return
18691831

@@ -1943,10 +1905,6 @@ def __init__(self, name, parent):
19431905
self.name = name
19441906
self.parent = parent
19451907

1946-
def __call__(self, *args, **kwargs):
1947-
m = self.create_mock()
1948-
return m(*args, **kwargs)
1949-
19501908
def create_mock(self):
19511909
entry = self.name
19521910
parent = self.parent
@@ -2330,19 +2288,10 @@ def _must_skip(spec, entry, is_type):
23302288
else:
23312289
return False
23322290

2333-
# shouldn't get here unless function is a dynamically provided attribute
2334-
# XXXX untested behaviour
2291+
# function is a dynamically provided attribute
23352292
return is_type
23362293

23372294

2338-
def _get_class(obj):
2339-
try:
2340-
return obj.__class__
2341-
except AttributeError:
2342-
# it is possible for objects to have no __class__
2343-
return type(obj)
2344-
2345-
23462295
class _SpecState(object):
23472296

23482297
def __init__(self, spec, spec_set=False, parent=None,

Lib/unittest/test/testmock/support.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ def is_instance(obj, klass):
99
class SomeClass(object):
1010
class_attribute = None
1111

12-
def wibble(self):
13-
pass
12+
def wibble(self): pass
1413

1514

1615
class X(object):

Lib/unittest/test/testmock/testcallable.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ def test_patch_spec_set_instance(self):
9898

9999
def test_patch_spec_callable_class(self):
100100
class CallableX(X):
101-
def __call__(self):
102-
pass
101+
def __call__(self): pass
103102

104103
class Sub(CallableX):
105104
pass

0 commit comments

Comments
 (0)