Как модульные тесты могут быть модульными, если они зависят от других модулей?
Я пытаюсь ретроспективно модульное тестирование приложения, которое является довольно сложным, но использует MVC. Я знаю, что ретроспективное применение модульных тестов не идеально, но я все еще верю, что это возможно путем рефакторинга существующего кода. В большинстве случаев невозможно провести модульное тестирование одного модуля, не полагаясь на другие модули, т.е. представление опирается на модель.
Каков наилучший способ модульного тестирования в этом случае? Лучше использовать реальную модель или создать макет модели?
Проблема использования реальной модели в моей ситуации состоит в том, что модель опирается на другие классы ответов, которые получают данные из XML, поэтому существует цепочка уверенности. Эта модель имеет много данных, поэтому ее было бы намного проще использовать, но, возможно, я упускаю суть.
Я предоставил UML приложения для краткости.
**Редактировать ****
Итак, если я прав, лучше ли создавать фиктивные данные внутри фиктивного класса? например, у меня есть фиктивный класс "MockPlaylistPanelModel", который создает данные, необходимые для класса View "PlaylistPanel" для запуска без ошибок:
class MockPlaylistPanelModel extends Mock implements IPlaylistPanelModel
{
/**
* Return all playlist items
* @public
*/
public function get mainPlaylistItems():Vector.<PlaylistData>
{
var playData:Vector.<PlaylistData> = new Vector.<PlaylistData>;
var playlistResp:PlaylistData = new PlaylistData(0, "", "", 0, 0, 0, 0);
playData.push(playlistResp);
return playData;
}
}
3 ответа
Чтобы ретроспективно встроить модульное тестирование в существующее приложение, вам часто нужно изменить код приложения для поддержки модульного тестирования (как вы правильно заметили, вам может потребоваться выполнить некоторый рефакторинг). Однако, конечно, здесь риск состоит в том, что изменения в приложении приводят к ошибкам, от которых невозможно защититься, если не будут проведены некоторые тесты.
Поэтому разумный подход заключается в том, чтобы внедрить некоторые тесты системного уровня, охватывающие некоторые из ваших ключевых вариантов использования. Это действует как своего рода "тестовая среда" вокруг вашего приложения, а это означает, что вы можете более безопасно начать вводить тесты более низкого уровня с уменьшенным риском появления ошибок по мере изменения приложения, чтобы сделать его более тестируемым. После этого вы можете ввести политику, согласно которой разработчики должны писать тесты для любого кода, который они изменяют, прежде чем изменить его - это позволяет вам органично наращивать набор автоматических тестов вокруг приложения.
Я настоятельно рекомендую освоить Эффективную работу с устаревшим кодом - эта превосходная книга охватывает все виды полезных методов для введения тестирования в существующее приложение, в котором мало автоматизированного тестирования.
Что касается вашего вопроса о том, должны ли вы создавать фиктивные данные внутри фиктивного класса для тестирования, это один из подходов, который вы можете использовать при внедрении тестовых версий объектов, но, вероятно, не самый лучший. Используя фальшивый фреймворк, такой как Mockito, вы можете легко создавать фиктивные объекты с четко определенным поведением на лету. В вашем случае вы можете использовать Mockito для создания реализации фиктивной модели, а затем внедрить вашу фиктивную модель в любой объект, который от нее зависит.
Это не юнит-тесты; это интеграционные тесты.
Да, используйте mocks для изоляции классов для модульных тестов.
Модульный тест должен проверять только часть программы. Если вы используете другие части, это становится интеграционным тестом.
Интеграционный тест проверяет, что детали хорошо работают вместе и не делают то, что они должны делать.
Модульный тест проверяет, что деталь делает то, что должна.
В этом разница между двумя тестами.
Для рефакторинга для модульного теста вы можете найти шаблон проектирования Dependency Injection.