Использование mocks, mockery и mocking — отличный способ упростить и улучшить модульное тестирование в Python. Тем не менее, высмеивание разных версий Python может показаться, что Python дразнит или смеется над вами в пренебрежительной или презрительной манере. Вот краткое руководство, чтобы избежать некоторых ключевых болевых точек.
Под сводкой я показываю примеры тестирования, которые делают то же самое, но различаются в зависимости от того, какие версии Python вы хотите поддерживать.
Резюме
Питон 3.6+:
- Импорт из
unittest.mock
- Можно использовать
assert_called_with()
- Можно использовать
assert_called_once()
иassert_not_called()
Питон 3.5:
- Импорт из
unittest.mock
- Можно использовать
assert_called_with()
- Невозможно использовать
assert_called_once()
илиassert_not_called()
Питон 3.4:
- Импорт из
unittest.mock
- Можно использовать
assert_called_with()
- Можно использовать
assert_called_once()
, но нетassert_not_called()
🤔
Питон 2:
- Импорт из
mock
- Можно использовать
assert_called_with()
- Невозможно использовать
assert_called_once()
илиassert_not_called()
Пример: насмешка в Python 3.6+
Если вам нужно только поддерживать Python 3.6+ при тестировании, вы можете импортировать из unittest.mock
и использовать удобные методы assert_called_once()
и assert_not_called()
.
В этом фрагменте примера показано тестирование собственной утилиты uhlist.utils.copytree()
, которая добавляет функциональность к версии, найденной в shutil
. Используя mock, мы можем избежать фактического копирования каких-либо файлов в рамках теста.
import pytest import uhlist.utils from unittest.mock import patch @patch('shutil.rmtree', autospec=True) @patch('shutil.copytree', autospec=True) def test_copytree_no_force(mock_copy, mock_rm): """Test that copytree results in correct calls.""" random_src = 'aba51e65-afd2-5020-8117-195f75e64258' random_dst = 'f74d03de-7c1d-596f-83f3-73748f2e238f' uhlist.utils.copytree(random_src, random_dst) mock_copy.assert_called_with(random_src, random_dst) mock_copy.assert_called_once() mock_rm.assert_not_called()
Насмешки в Python 3.5+
Этот фрагмент будет работать на Python 3.5+. Этот код импортирует из unittest.mock
, но не может использовать вспомогательные методы assert_called_once()
и assert_not_called()
.
import pytest import uhlist.utils from unittest.mock import patch @patch('shutil.rmtree', autospec=True) @patch('shutil.copytree', autospec=True) def test_copytree(mock_copy, mock_rm): """Test that copytree results in correct calls.""" random_src = 'aba51e65-afd2-5020-8117-195f75e64258' random_dst = 'f74d03de-7c1d-596f-83f3-73748f2e238f' uhlist.utils.copytree(random_src, random_dst) mock_copy.assert_called_with(random_src, random_dst) assert mock_copy.call_count == 1 assert mock_rm.call_count == 0
Насмешки в Python 3.4+
Этот фрагмент будет работать на Python 3.4+. Этот код импортирует из unittest.mock
и использует удобный метод assert_called_once()
, но не может использовать assert_not_called()
. 🤔
import pytest import uhlist.utils from unittest.mock import patch @patch('shutil.rmtree', autospec=True) @patch('shutil.copytree', autospec=True) def test_copytree(mock_copy, mock_rm): """Test that copytree results in correct calls.""" random_src = 'aba51e65-afd2-5020-8117-195f75e64258' random_dst = 'f74d03de-7c1d-596f-83f3-73748f2e238f' uhlist.utils.copytree(random_src, random_dst) mock_copy.assert_called_with(random_src, random_dst) mock_copy.assert_called_once() assert mock_rm.call_count == 0
Насмешки в Python 2.6+
Если вы хотите, чтобы один и тот же тест работал во всех доступных версиях Python, этот фрагмент кода дает вам представление о том, как это делается.
Примечательно, что в 2.6 и 2.7 импорт происходит из mock
вместо unittest.mock
. Для одновременной поддержки более поздних версий Python нам понадобится файл try/except
. Как и в 3.5, нет ни вспомогательного метода, ни assert_called_once()
, ни assert_not_called()
:
import pytest import uhlist.utils try: from unittest.mock import patch except ImportError: from mock import patch @patch('shutil.rmtree', autospec=True) @patch('shutil.copytree', autospec=True) def test_copytree(mock_copy, mock_rm): """Test that copytree results in correct calls.""" random_src = 'aba51e65-afd2-5020-8117-195f75e64258' random_dst = 'f74d03de-7c1d-596f-83f3-73748f2e238f' uhlist.utils.copytree(random_src, random_dst) mock_copy.assert_called_with(random_src, random_dst) assert mock_copy.call_count == 1 assert mock_rm.call_count == 0