Имитация конструкции класса

Я только начинаю использовать библиотеку 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, с которыми мне обычно было бы комфортно. Где я должен сделать обмен? Более чистый код или более чистые тесты?

11
задан Wilduck 2 April 2012 в 19:31
поделиться