Привіт усім, нещодавно я завершив проект з ETL pipeline за участю Python, Azure Event Hub та Tableau, де я отримував дані прогнозу погоди, обробляв їх і візуалізував на панелі управління. Під час створення та тестування конвеєра однією з основних інструментів, що допомогли мені глибше зрозуміти unit testing, став MagicMock з модуля unittest.mock Python.
Я хотів би поділитися своїм досвідом роботи з MagicMock, як я використовував цей інструмент у своєму проекті і чому він є справжнім проривом для тестування Python-додатків.
Що таке MagicMock?
MagicMock є частиною бібліотеки unittest.mock Python. Це потужний інструмент, який дозволяє заміняти частини системи, що тестується, на мок-об’єкти і визначати їх поведінку під час тестування.
Простими словами:
• Він імітує поведінку реальних об’єктів (наприклад, відповіді API, виклики бази даних).
• Дає змогу перевіряти, як був викликаний метод, імітувати відповіді та запобігати реальним викликам API.
• Допомагає зробити тести швидшими, більш ізольованими і надійними.
Як я використовував MagicMock у своєму проекті ETL
Випадок 1: Мокаємо виклик API
У своєму проекті я отримував дані про погоду за допомогою API. Під час тестування я хотів переконатися в наступному:
-
Функція працює правильно, коли API повертає успішну відповідь.
-
Не було здійснено жодних реальних викликів API (щоб заощадити трафік і уникнути залежностей від зовнішніх сервісів).
Ось як я використовував MagicMock для цього:
import unittest
from unittest.mock import patch, MagicMock
from src.fetch_data_api import fetch_data_api, FORECAST_DAYS
class TestWeatherForecastSuccess(unittest.TestCase):
@patch('requests.get')
def test_fetch_data_api(self, mock_get):
# Мокаємо успішну відповідь API
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"days": [{"datetime": "2024–06–01", "temp": 22, "conditions": "Clear"}] * 14
}
mock_get.return_value = mock_response
result = fetch_data_api("Vancouver", FORECAST_DAYS)
# Перевірки
self.assertEqual(len(result), 14)
mock_get.assert_called_once_with(
"https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Vancouver?unitGroup=metric&key=Your_API_Key&contentType=json&include=days"
)
Що я навчився:
- Імітація поведінки API:
mock_get.return_value = mock_response
- За допомогою цього я зміг імітувати відповідь API зі статусом 200 OK і JSON-пакетом.
• Ізольоване тестування: Мені не потрібен був реальний API-ключ або активне підключення до Інтернету.
- Перевірка:
mock_get.assert_called_once_with(…)
Це допомогло переконатися, що API було викликано з правильним URL.
Випадок 2: Мокаємо Azure Event Hub Producer
На іншому етапі я відправляв дані про погоду до Azure Event Hub. Для тестування функціональності передачі даних я замокав клієнта Event Hub, використовуючи MagicMock, щоб переконатися в наступному:
- Дані були правильно відформатовані.
2.
Виробник Event Hub був ініціалізований та викликаний належним чином.
Ось як я використовував MagicMock:
import unittest
from unittest.mock import patch, MagicMock
from src.push_data_eventhub import push_data_eventhub
class TestPushForecastToEventHub(unittest.TestCase):
@patch('src.push_data_eventhub.EventHubProducerClient')
def test_push_data_eventhub_success(self, mock_producer_client):
# Мокаємо виробника Event Hub
mock_producer_instance = MagicMock()
mock_producer_client.from_connection_string.return_value = mock_producer_instance
mock_batch = MagicMock()
mock_producer_instance.create_batch.return_value = mock_batch
sample_forecast_data = {"Vancouver": [{"datetime": "2024–06–01", "temp": 22, "conditions": "Clear"}]}
push_data_eventhub(sample_forecast_data)
# Перевірки
mock_producer_client.from_connection_string.assert_called_once()
print("Тест на відправку до Event Hub пройшов успішно!")
Чому це важливо?
• Мокання реальних клієнтів: Замість того, щоб підключатися до Event Hub, я замокав EventHubProducerClient і його методи.
• Імітація пакетних операцій: Мокаючи createbatch та sendbatch, я зміг перевірити, як мій код взаємодіяв з API Event Hub.
• Покращена надійність: Такий підхід забезпечив, що мої тести не зламаються через зовнішні залежності, такі як проблеми з мережею.
Чому MagicMock такий корисний?
Є кілька причин, чому він так корисний, ось вони:
• Ізоляція: Він розділяє код, що тестується, від зовнішніх систем (наприклад, API, баз даних, хмарних сервісів).
• Контроль: Можна симулювати різні сценарії (наприклад, успіх, помилки, таймаути), не маючи реальних умов.
• Перевірка: Він допомагає перевірити, чи працює ваш код як очікується (наприклад, перевірка правильних API-ендпоінтів, викликів методів тощо).
• Економія часу: Тести виконуються швидше, оскільки не здійснюються реальні зовнішні виклики.
Основні висновки
-
Мокайте зовнішні залежності: Використовуйте MagicMock для симуляції відповідей від API, хмарних клієнтів чи інших зовнішніх систем.
-
Зосередьтеся на поведінці: Тестування за допомогою MagicMock допомагає перевірити, як ваш код поводиться в різних умовах.
-
Практика робить майстерність: Чим більше ви використовуєте моки, тим комфортніше вам буде розробляти надійні, ізольовані тести.
Перекладено з: Mastering MagicMock: Lessons Learned While Building an ETL Pipeline