Модульное тестирование - основная цель? - PullRequest
6 голосов
/ 04 мая 2010

Вчера вечером у меня и моих коллег возникли некоторые разногласия по поводу модульного тестирования в нашем приложении PHP / MySQL. Половина из нас утверждают, что при модульном тестировании функции в классе вы должны высмеивать все, что находится за пределами этого класса и его родителей. Другая половина из нас утверждала, что вы НЕ ДОЛЖНЫ издеваться над чем-либо, что является прямой зависимостью от класса.

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

Таким образом, я предполагаю, что основной вопрос заключается в том, служат ли модульные тесты для проверки работоспособности одного модуля в закрытой среде или показывают последствия изменений для одного модуля в более крупной среде? Если это один из них, как вы достигли другого?

Ответы [ 4 ]

11 голосов
/ 04 мая 2010

Вы и ваши коллеги наткнулись на разницу между юнит-тестами и интеграционными тестами. Дразнить все будет сделано для первого; для последнего не было бы никакой насмешливой зависимости.

Конечно, когда вы рисуете гранулярность, это тоже своего рода субъективно - но при самом высоком уровне детализации для модульного тестирования вам не следует беспокоиться о чем-либо, выходящем за рамки конкретного предмета каждого теста.

5 голосов
/ 04 мая 2010

Модульное тестирование похоже на тестирование одного компонента в электронном устройстве.

Если вы хотите протестировать один транзистор в гитарном усилителе, вы не подключаете гитару, увеличиваете громкость и проверяете издаваемые звуки. Это было бы глупо. Чтобы проверить транзистор, вы подключаете оборудование к выводам этого транзистора и измеряете только его входы и выходы.

В какой-то момент вы все тестируете (гитара издает шум и т. Д.), Но это совсем не то, что тестирование одного транзистора.

1 голос
/ 04 мая 2010

Слова дают некоторые подсказки относительно ответа:

единица означает 1: вы пытаетесь проверить одну вещь. Вы можете смоделировать зависимости, такие как каркас журналирования, когда это не является основной целью ваших тестов. То, как тестируемый модуль взаимодействует с его зависимостями, часто является частью тестового примера, и имитация делает это намного проще.

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

Я бы сказал, что аргумент за отсутствие насмешек над системой журналирования в модульных тестах, чтобы увидеть, ломают ли изменения что-либо, довольно слабый. Если что-то сломано в системе ведения журнала, то это должно быть обнаружено неудачным модульным тестом для системы ведения журнала.

Хорошим практическим правилом является простота, ясность и сфокусированность юнит-тестов. Юу нужна эта основа простоты при расширении объема тестов. Интеграционные тесты могут быстро стать сложными, особенно при использовании их в качестве заменителей отсутствующих модульных тестов - это похоже на «тестирование на расстоянии», и чем дальше вы удаляетесь от компонента, тем сложнее тестировать и диагностировать сбои. Тестирование удаленной зависимости с помощью юнит-теста похоже на человека, пытающегося управлять ТВ-пультом с другой стороны комнаты с помощью удочки.

0 голосов
/ 04 мая 2010

@ Дэвид, я вижу, что юнит-тестирование для вас делает работу, которую он должен делать.

Вы размышляете над дизайном своего программного обеспечения.

Исходя из того, как вы задаете свой вопрос о закрытой и открытой средах, я могу поверить, что вы на пороге необходимости отвечать на вопрос о модульном тестировании на основе состояния или поведения для вашего кода.

Не существует жесткого правила быстрого использования реального объекта или макета для юнит-тестирования. ТОЛЬКО РУКОВОДЯЩИЕ ПРИНЦИПЫ! Проблема модульного тестирования с реальным объектом Logging состоит в том, что тесты для этого объекта будут заключаться не только в модульных тестах для регистратора, но и в модульных тестах для объектов, использующих регистратор.

Таким образом, если у вас есть 20 объектов, которые используют регистратор, и когда вы измените интерфейс регистратора, будет не менее 21 неудачного теста. Это может быть довольно болезненным при рефакторинге. Но, с другой стороны, если вы не используете класс регистратора в модульных тестах из 20 объектов и изменили интерфейс регистратора, у вас есть только один неудачный тест и 20 других модульных тестов, которые становятся зелеными, даже если они потерпят неудачу в производстве.

Единственное понимание, которое я действительно могу вам дать, это то, что у вас нет правильных абстракций. Возможно, вы захотите посмотреть SOLID . Это должны быть руководящие принципы.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...