Первоначально TDD происходил из гибкого движения, где тестирование было написано заранее, чтобы гарантировать, что то, что вы закодировали, остается правильным, учитывая спецификацию, которая теперь была четко определена в тестовом коде. Это также показалось очень важным аспектом рефакторинга: когда вы модифицировали свой код, вы могли полагаться на тесты, чтобы доказать, что вы не изменили поведение кода.
Затем пришли инструменты и подумали, что они знают информацию о вашем коде, а затем могут создать тестовые заглушки, чтобы помочь вам в написании модульных тестов, и я думаю, что именно здесь все пошло не так.
Тестовые заглушки создаются компьютером, который не имеет ни малейшего представления о том, что вы делаете, он просто бездумно создает заглушку для каждого метода, потому что это то, что ему говорят делать. Это означает, что у вас есть тестовый пример для каждого метода, независимо от сложности этого метода или от того, подходит ли он для тестирования в изоляции.
Это происходит при тестировании с неправильного конца методологии TDD. В TDD вы должны выяснить, что должен делать код, а затем создать код, который достигает этого. Это самореализуется тем, что вы заканчиваете тем, что пишете тесты, которые доказывают, что код выполняет то, что делает код, а не то, что он должен делать. В сочетании с автоматическим созданием основанных на методах тестовых заглушек вы в значительной степени тратите свое время на проверку каждого крошечного аспекта кода, который может легко оказаться неверным, когда все маленькие кусочки собраны воедино.
Когда Фаулер описал тестирование в своей книге, он сослался на тестирование каждого класса своим основным методом. Он улучшил это, но концепция все та же - вы тестируете весь класс, чтобы он работал в целом, все ваши тесты объединяются, чтобы доказать взаимодействие всех этих методов, чтобы класс можно было повторно использовать с определенными ожиданиями.
Я думаю, что тестовые наборы инструментов оказали нам плохую услугу, привели нас на путь мышления, что набор инструментов является единственным способом сделать что-то, когда на самом деле вам нужно больше думать о себе, чтобы получить лучший результат из своего кода. Слепое помещение тестового кода в тестовые заглушки для крошечных кусочков просто означает, что вы все равно должны повторить свою работу в интеграционном тесте (и если вы собираетесь это сделать, почему бы не пропустить этап избыточного модульного тестирования, который теперь является излишним). Это также означает, что люди тратят много времени, пытаясь получить 100% тестовое покрытие, и много времени, создавая большие объемы макета кода и данных, которые были бы лучше потрачены на упрощение кода для интеграционного тестирования (т. Е. Если у вас так много зависимости от данных, модульное тестирование может быть не лучшим вариантом)
Наконец, хрупкость модульных тестов на основе методов только показывает проблему. Рефакторинг предназначен для использования с юнит-тестами, если ваши тесты все время ломаются из-за того, что вы выполняете рефакторинг, тогда что-то пошло не так со всем подходом. Рефакторинг любит создавать и удалять методы, поэтому очевидно, что слепой подход, основанный на методах, не соответствует первоначальному.
Я не сомневаюсь, что многие методы получат тесты, написанные для них, все общедоступные методы класса должны быть протестированы, но вы не можете уйти от концепции их совместного тестирования как части одного теста. Например, если у меня есть метод set и get, я могу написать тесты, которые помещают данные и проверяют, установлены ли внутренние члены в порядке, или я могу использовать каждый из них, чтобы поместить некоторые данные, а затем получить их снова, чтобы увидеть, все тот же и не искаженный. Это тестирование класса, а не каждого метода в отдельности. Если установщик полагается на вспомогательный закрытый метод, то это нормально - вам не нужно издеваться над закрытым методом, чтобы убедиться, что установщик работает, а не если вы тестируете весь класс.
Я думаю, что религия проникает в эту тему, поэтому вы видите раскол в так называемой «управляемой поведением» и «управляемой тестами» разработке - оригинальная концепция модульного тестирования была для разработки, основанной на поведении.
Как следует из названия, вы тестируете атомный предмет в каждом тесте. Такой предмет - обычно единственный метод. Множество тестов могут тестировать один и тот же метод, чтобы охватить удачный путь, возможные ошибки и т. Д. Вы тестируете поведение, а не внутреннюю механику. Таким образом, модульное тестирование - это тестирование открытого интерфейса класса, то есть конкретного метода.
В модульном тестировании метод должен тестироваться изолированно, то есть путем заглушения / насмешек / подделки любых зависимостей. В противном случае тестирование модуля с «реальными» зависимостями делает его интеграционным тестом. Есть время и место для обоих типов тестов. Модульные тесты гарантируют, что один объект работает как положено, автономно. Интеграционные тесты гарантируют, что «реальные» предметы работают вместе правильно.
источник
Мое эмпирическое правило: самая маленькая единица кода, которая все еще достаточно сложна, чтобы содержать ошибки.
Является ли это методом, классом или подсистемой, зависит от конкретного кода, общее правило не может быть дано.
Например, он не предоставляет никакого значения для тестирования простых методов получения / установки в отдельности или методов-оболочек, которые вызывают только другой метод. Даже целый класс может быть слишком простым для тестирования, если этот класс является только тонкой оболочкой или адаптером. Если единственное, что нужно проверить, - это вызвать ли метод на макете, то тестируемый код - тонкий.
В других случаях один метод может выполнять некоторые сложные вычисления, которые полезно тестировать отдельно.
Во многих случаях сложные части - это не отдельные классы, а скорее интеграция между классами. Таким образом, вы тестируете два или более классов одновременно. Некоторые скажут, что это не модульные тесты, а интеграционные тесты, но не обращайте внимания на терминологию: вы должны проверить, где сложность, и эти тесты должны быть частью набора тестов.
источник