mirror of
https://github.com/python/cpython.git
synced 2025-10-23 18:03:48 +00:00

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.
327 lines
11 KiB
Python
327 lines
11 KiB
Python
import unittest
|
|
from warnings import catch_warnings
|
|
|
|
from unittest.test.testmock.support import is_instance
|
|
from unittest.mock import MagicMock, Mock, patch, sentinel, mock_open, call
|
|
|
|
|
|
|
|
something = sentinel.Something
|
|
something_else = sentinel.SomethingElse
|
|
|
|
|
|
class SampleException(Exception): pass
|
|
|
|
|
|
class WithTest(unittest.TestCase):
|
|
|
|
def test_with_statement(self):
|
|
with patch('%s.something' % __name__, sentinel.Something2):
|
|
self.assertEqual(something, sentinel.Something2, "unpatched")
|
|
self.assertEqual(something, sentinel.Something)
|
|
|
|
|
|
def test_with_statement_exception(self):
|
|
with self.assertRaises(SampleException):
|
|
with patch('%s.something' % __name__, sentinel.Something2):
|
|
self.assertEqual(something, sentinel.Something2, "unpatched")
|
|
raise SampleException()
|
|
self.assertEqual(something, sentinel.Something)
|
|
|
|
|
|
def test_with_statement_as(self):
|
|
with patch('%s.something' % __name__) as mock_something:
|
|
self.assertEqual(something, mock_something, "unpatched")
|
|
self.assertTrue(is_instance(mock_something, MagicMock),
|
|
"patching wrong type")
|
|
self.assertEqual(something, sentinel.Something)
|
|
|
|
|
|
def test_patch_object_with_statement(self):
|
|
class Foo(object):
|
|
something = 'foo'
|
|
original = Foo.something
|
|
with patch.object(Foo, 'something'):
|
|
self.assertNotEqual(Foo.something, original, "unpatched")
|
|
self.assertEqual(Foo.something, original)
|
|
|
|
|
|
def test_with_statement_nested(self):
|
|
with catch_warnings(record=True):
|
|
with patch('%s.something' % __name__) as mock_something, patch('%s.something_else' % __name__) as mock_something_else:
|
|
self.assertEqual(something, mock_something, "unpatched")
|
|
self.assertEqual(something_else, mock_something_else,
|
|
"unpatched")
|
|
|
|
self.assertEqual(something, sentinel.Something)
|
|
self.assertEqual(something_else, sentinel.SomethingElse)
|
|
|
|
|
|
def test_with_statement_specified(self):
|
|
with patch('%s.something' % __name__, sentinel.Patched) as mock_something:
|
|
self.assertEqual(something, mock_something, "unpatched")
|
|
self.assertEqual(mock_something, sentinel.Patched, "wrong patch")
|
|
self.assertEqual(something, sentinel.Something)
|
|
|
|
|
|
def testContextManagerMocking(self):
|
|
mock = Mock()
|
|
mock.__enter__ = Mock()
|
|
mock.__exit__ = Mock()
|
|
mock.__exit__.return_value = False
|
|
|
|
with mock as m:
|
|
self.assertEqual(m, mock.__enter__.return_value)
|
|
mock.__enter__.assert_called_with()
|
|
mock.__exit__.assert_called_with(None, None, None)
|
|
|
|
|
|
def test_context_manager_with_magic_mock(self):
|
|
mock = MagicMock()
|
|
|
|
with self.assertRaises(TypeError):
|
|
with mock:
|
|
'foo' + 3
|
|
mock.__enter__.assert_called_with()
|
|
self.assertTrue(mock.__exit__.called)
|
|
|
|
|
|
def test_with_statement_same_attribute(self):
|
|
with patch('%s.something' % __name__, sentinel.Patched) as mock_something:
|
|
self.assertEqual(something, mock_something, "unpatched")
|
|
|
|
with patch('%s.something' % __name__) as mock_again:
|
|
self.assertEqual(something, mock_again, "unpatched")
|
|
|
|
self.assertEqual(something, mock_something,
|
|
"restored with wrong instance")
|
|
|
|
self.assertEqual(something, sentinel.Something, "not restored")
|
|
|
|
|
|
def test_with_statement_imbricated(self):
|
|
with patch('%s.something' % __name__) as mock_something:
|
|
self.assertEqual(something, mock_something, "unpatched")
|
|
|
|
with patch('%s.something_else' % __name__) as mock_something_else:
|
|
self.assertEqual(something_else, mock_something_else,
|
|
"unpatched")
|
|
|
|
self.assertEqual(something, sentinel.Something)
|
|
self.assertEqual(something_else, sentinel.SomethingElse)
|
|
|
|
|
|
def test_dict_context_manager(self):
|
|
foo = {}
|
|
with patch.dict(foo, {'a': 'b'}):
|
|
self.assertEqual(foo, {'a': 'b'})
|
|
self.assertEqual(foo, {})
|
|
|
|
with self.assertRaises(NameError):
|
|
with patch.dict(foo, {'a': 'b'}):
|
|
self.assertEqual(foo, {'a': 'b'})
|
|
raise NameError('Konrad')
|
|
|
|
self.assertEqual(foo, {})
|
|
|
|
def test_double_patch_instance_method(self):
|
|
class C:
|
|
def f(self): pass
|
|
|
|
c = C()
|
|
|
|
with patch.object(c, 'f', autospec=True) as patch1:
|
|
with patch.object(c, 'f', autospec=True) as patch2:
|
|
c.f()
|
|
self.assertEqual(patch2.call_count, 1)
|
|
self.assertEqual(patch1.call_count, 0)
|
|
c.f()
|
|
self.assertEqual(patch1.call_count, 1)
|
|
|
|
|
|
class TestMockOpen(unittest.TestCase):
|
|
|
|
def test_mock_open(self):
|
|
mock = mock_open()
|
|
with patch('%s.open' % __name__, mock, create=True) as patched:
|
|
self.assertIs(patched, mock)
|
|
open('foo')
|
|
|
|
mock.assert_called_once_with('foo')
|
|
|
|
|
|
def test_mock_open_context_manager(self):
|
|
mock = mock_open()
|
|
handle = mock.return_value
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
with open('foo') as f:
|
|
f.read()
|
|
|
|
expected_calls = [call('foo'), call().__enter__(), call().read(),
|
|
call().__exit__(None, None, None)]
|
|
self.assertEqual(mock.mock_calls, expected_calls)
|
|
self.assertIs(f, handle)
|
|
|
|
def test_mock_open_context_manager_multiple_times(self):
|
|
mock = mock_open()
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
with open('foo') as f:
|
|
f.read()
|
|
with open('bar') as f:
|
|
f.read()
|
|
|
|
expected_calls = [
|
|
call('foo'), call().__enter__(), call().read(),
|
|
call().__exit__(None, None, None),
|
|
call('bar'), call().__enter__(), call().read(),
|
|
call().__exit__(None, None, None)]
|
|
self.assertEqual(mock.mock_calls, expected_calls)
|
|
|
|
def test_explicit_mock(self):
|
|
mock = MagicMock()
|
|
mock_open(mock)
|
|
|
|
with patch('%s.open' % __name__, mock, create=True) as patched:
|
|
self.assertIs(patched, mock)
|
|
open('foo')
|
|
|
|
mock.assert_called_once_with('foo')
|
|
|
|
|
|
def test_read_data(self):
|
|
mock = mock_open(read_data='foo')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
result = h.read()
|
|
|
|
self.assertEqual(result, 'foo')
|
|
|
|
|
|
def test_readline_data(self):
|
|
# Check that readline will return all the lines from the fake file
|
|
# And that once fully consumed, readline will return an empty string.
|
|
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
line1 = h.readline()
|
|
line2 = h.readline()
|
|
line3 = h.readline()
|
|
self.assertEqual(line1, 'foo\n')
|
|
self.assertEqual(line2, 'bar\n')
|
|
self.assertEqual(line3, 'baz\n')
|
|
self.assertEqual(h.readline(), '')
|
|
|
|
# Check that we properly emulate a file that doesn't end in a newline
|
|
mock = mock_open(read_data='foo')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
result = h.readline()
|
|
self.assertEqual(result, 'foo')
|
|
self.assertEqual(h.readline(), '')
|
|
|
|
|
|
def test_dunder_iter_data(self):
|
|
# Check that dunder_iter will return all the lines from the fake file.
|
|
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
lines = [l for l in h]
|
|
self.assertEqual(lines[0], 'foo\n')
|
|
self.assertEqual(lines[1], 'bar\n')
|
|
self.assertEqual(lines[2], 'baz\n')
|
|
self.assertEqual(h.readline(), '')
|
|
|
|
|
|
def test_readlines_data(self):
|
|
# Test that emulating a file that ends in a newline character works
|
|
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
result = h.readlines()
|
|
self.assertEqual(result, ['foo\n', 'bar\n', 'baz\n'])
|
|
|
|
# Test that files without a final newline will also be correctly
|
|
# emulated
|
|
mock = mock_open(read_data='foo\nbar\nbaz')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
result = h.readlines()
|
|
|
|
self.assertEqual(result, ['foo\n', 'bar\n', 'baz'])
|
|
|
|
|
|
def test_read_bytes(self):
|
|
mock = mock_open(read_data=b'\xc6')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
with open('abc', 'rb') as f:
|
|
result = f.read()
|
|
self.assertEqual(result, b'\xc6')
|
|
|
|
|
|
def test_readline_bytes(self):
|
|
m = mock_open(read_data=b'abc\ndef\nghi\n')
|
|
with patch('%s.open' % __name__, m, create=True):
|
|
with open('abc', 'rb') as f:
|
|
line1 = f.readline()
|
|
line2 = f.readline()
|
|
line3 = f.readline()
|
|
self.assertEqual(line1, b'abc\n')
|
|
self.assertEqual(line2, b'def\n')
|
|
self.assertEqual(line3, b'ghi\n')
|
|
|
|
|
|
def test_readlines_bytes(self):
|
|
m = mock_open(read_data=b'abc\ndef\nghi\n')
|
|
with patch('%s.open' % __name__, m, create=True):
|
|
with open('abc', 'rb') as f:
|
|
result = f.readlines()
|
|
self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n'])
|
|
|
|
|
|
def test_mock_open_read_with_argument(self):
|
|
# At one point calling read with an argument was broken
|
|
# for mocks returned by mock_open
|
|
some_data = 'foo\nbar\nbaz'
|
|
mock = mock_open(read_data=some_data)
|
|
self.assertEqual(mock().read(10), some_data)
|
|
|
|
|
|
def test_interleaved_reads(self):
|
|
# Test that calling read, readline, and readlines pulls data
|
|
# sequentially from the data we preload with
|
|
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
line1 = h.readline()
|
|
rest = h.readlines()
|
|
self.assertEqual(line1, 'foo\n')
|
|
self.assertEqual(rest, ['bar\n', 'baz\n'])
|
|
|
|
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
|
with patch('%s.open' % __name__, mock, create=True):
|
|
h = open('bar')
|
|
line1 = h.readline()
|
|
rest = h.read()
|
|
self.assertEqual(line1, 'foo\n')
|
|
self.assertEqual(rest, 'bar\nbaz\n')
|
|
|
|
|
|
def test_overriding_return_values(self):
|
|
mock = mock_open(read_data='foo')
|
|
handle = mock()
|
|
|
|
handle.read.return_value = 'bar'
|
|
handle.readline.return_value = 'bar'
|
|
handle.readlines.return_value = ['bar']
|
|
|
|
self.assertEqual(handle.read(), 'bar')
|
|
self.assertEqual(handle.readline(), 'bar')
|
|
self.assertEqual(handle.readlines(), ['bar'])
|
|
|
|
# call repeatedly to check that a StopIteration is not propagated
|
|
self.assertEqual(handle.readline(), 'bar')
|
|
self.assertEqual(handle.readline(), 'bar')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|