Я только начинаю использовать библиотеку 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__
для holds_data
, а затем просто заполнить частьself.data
необходимо для x_coords
.Примерно так:
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
была автономной функцией, которая принимает holds_data
в качестве параметра.Если «легче тестировать == лучший дизайн», это будет путь.Тем не менее, потребуется x_coords
функция, чтобы узнать больше о внутренностях holds_data
, с которыми мне обычно было бы удобно.Где я должен сделать компромисс?Чистый код или чистые тесты?