Я только начинаю использовать библиотеку Python mock, чтобы писать более лаконично. и изолированные модульные тесты. Моя ситуация такова, что у меня есть класс, который считывает данные из довольно сложного формата, и я хочу протестировать метод этого класса, который представляет данные в чистом виде. формат.
class holds_data(object):
def __init__(self, path):
"""Pulls complicated data from a file, given by 'path'.
Stores it in a dictionary.
"""
self.data = {}
with open(path) as f:
self.data.update(_parse(f))
def _parse(self, file):
# Some hairy parsing code here
pass
def x_coords(self):
"""The x coordinates from one part of the data
"""
return [point[0] for point in self.data['points']]
Приведенный выше код является упрощением того, что у меня есть. На самом деле _parse
— довольно важный метод, для которого у меня есть тестовое покрытие на функциональном уровне.
Однако я хотел бы иметь возможность протестировать x_coords
на уровне модульного тестирования. Если бы я создал экземпляр этого класса, задав ему путь, это нарушило бы правила модульных тестов, потому что:
Тест не является модульным тестом, если:
- Он затрагивает файловую систему
] Итак, я хотел бы иметь возможность пропатчить метод __init__
для hold_data
, а затем просто заполнить часть self.data
, необходимую для x_координаты
. Что-то вроде:
from mock import patch
with patch('__main__.holds_data.__init__') as init_mock:
init_mock.return_value = None
instance = holds_data()
instance.data = {'points':[(1,1),(2,2),(3,4)]}
assert(instance.x_coords == [1,2,3])
Приведенный выше код работает, но кажется, что он проходит этот тест довольно окольным путем.Есть ли более идиоматический способ исправления конструктора или это правильный способ сделать это? Кроме того, есть ли какой-то запах кода в моем классе или тесте, который мне не хватает?
Редактировать: Чтобы было ясно, моя проблема заключается в том, что во время инициализации мой класс выполняет значительные объемы обработки данных для организации данных, которые будут представлены методом, подобным x_coords
. Я хочу знать, как проще всего исправить все эти шаги, не предоставляя полный пример ввода. Я хочу проверить поведение x_coords
только в ситуации, когда я контролирую данные, которые он использует.
Мой вопрос о том, есть ли здесь запах кода, сводится к следующему:
Я уверен, что было бы проще, если бы я провел рефакторинг, чтобы x_coords
была отдельной функцией, которая принимает содержит_данные
в качестве параметра. Если «легче тестировать == лучший дизайн», это будет правильный путь. Однако для этого потребуется, чтобы функция x_coords
знала больше о внутренностях hold_data
, с которыми мне обычно было бы комфортно. Где я должен сделать обмен? Более чистый код или более чистые тесты?