Как избежать дублирования кода в моих тестах и ​​избежать насмешек над собой? - PullRequest
1 голос
/ 22 октября 2008

В моем вопросе Как практикующий TDD «mockist», я должен высмеивать другие методы в том же классе, что и тестируемый метод? сам по себе почти всегда пахнет кодом. Он тестирует реализацию, а не поведение ". Он может быть прав, но часто я не могу различить реализацию и поведение.

У меня есть другой пример (в псевдокоде в стиле Python), который может привести к полезным ответам:

class Consumer:

    def spec_dirpath:
        client = VCS.get_connection(self.vcs_client_name)
        client.sync()
        return client.dirpath()

    def spec_filepath:
        filepath = os.path.join(spec_dirpath(), self.spec_filename)
        if not os.path.exists(filepath):
            raise ConsumerException
        return filepath

    def get_components:
        return Components.get_components_from_spec_file(self.spec_filepath())

Идея заключается в том, что метод get_components вызывает метод spec_filepath, чтобы получить путь к файлу, из которого метод класса компонентов get_components_from_spec_file будет читать список компонентов. В свою очередь, метод spec_filepath вызывает spec_dirpath, который синхронизирует каталог, содержащий файл спецификации, из системы VCS и возвращает путь к этому каталогу. (Постарайтесь не искать ошибок в этом коде - это все-таки псевдокод.)

Я ищу совет о том, как проверить эти методы ...

Тестирование spec_dirpath должно быть довольно простым. Я могу смоделировать класс VCS и заставить его вернуть фиктивный объект и подтвердить, что были вызваны соответствующие методы (и что метод spec_dirpath возвращает то, что возвращает метод dirpath макета).

Но если я не высмеиваю spec_dirpath при тестировании spec_filepath, как мне избежать дублирования того же тестового кода из кода spec_dirpath в тесте spec_filepath? И если я не высмеиваю spec_filepath во время тестирования get_components, как мне избежать дублирования тестового кода из обоих spec_filepath и spec_dirpath?

Ответы [ 2 ]

1 голос
/ 22 октября 2008

Модульное тестирование работает лучше с некоторой формой внедрения зависимостей. В этом случае, поскольку вы создаете клиента в коде, вы создаете зависимость в своем тесте, которая требует некоторой формы динамического макета, чтобы справиться с ней. (В этом случае мы использовали бы частичную имитацию, чтобы смоделировать наши вызовы, которые создают зависимости, чтобы избежать необходимости также проверять эти зависимости).

Если вы вводите зависимость при запуске (то есть, передаете клиентский объект), то вы можете легко смоделировать его и не испытывать особых трудностей при тестировании только одного класса.

Таким образом, для достижения этих целей вам понадобится либо частичная имитация, либо решение для внедрения зависимостей.

1 голос
/ 22 октября 2008

Обычно в модульном тестировании поведение относится к внешне наблюдаемому поведению.

На вашем примере наблюдаемым поведением будет список компонентов, которые вы получите от get. Тот факт, что они исходят из файла, является реализацией, поэтому я бы посоветовал строить ваши тесты из списка компонентов, которые вы возвращаете, без насмешек при извлечении файла, поскольку он является внутренним по отношению к классу, с установочным кодом для предоставления соответствующего файла.

Альтернативой может быть создание файла, компоненты которого были загружены, из зависимости для класса, например сделайте это параметром конструктора или параметром метода, чтобы позволить файлу быть указанным снаружи классу. В этом случае он будет внешним, и поэтому я посмеюсь над ним, чтобы убедиться, что вы получили от него согласованное поведение, чтобы убедиться, что ваш класс использовал его правильно.

...