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