Ключевое отличие для меня заключается в том, что интеграционные тесты выявляют, работает ли функция или не работает, поскольку они нагружают код в сценарии, близком к реальности. Они вызывают один или несколько программных методов или функций и проверяют, работают ли они должным образом.
Напротив, модульное тестирование одного метода основывается на (часто ошибочном) предположении, что остальная часть программного обеспечения работает правильно, поскольку он явно имитирует каждую зависимость.
Следовательно, когда модульный тест для метода, реализующего некоторую функцию, имеет зеленый цвет, это не означает, что функция работает.
Скажем, у вас есть такой метод:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
Log.TrackTheFactYouDidYourJob();
return someResults;
}
DoSomething
очень важен для вашего клиента: это единственное, что имеет значение. Вот почему вы обычно пишете спецификацию Cucumber, утверждая это: вы хотите проверить и сообщить, работает ли функция или нет.
Feature: To be able to do something
In order to do something
As someone
I want the system to do this thing
Scenario: A sample one
Given this situation
When I do something
Then what I get is what I was expecting for
Несомненно: если тест пройден, вы можете утверждать, что предоставляете работающую функцию. Это то, что вы можете назвать ценностью для бизнеса.
Если вы хотите написать модульный тест для DoSomething
, вы должны притвориться (используя некоторые макеты), что остальные классы и методы работают (то есть: все зависимости, которые использует метод, работают правильно) и подтвердить, что ваш метод работает .
На практике вы делаете что-то вроде:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
return someResults;
}
Вы можете сделать это с помощью внедрения зависимостей, или какого-нибудь фабричного метода, или любой Mock Framework, или просто расширив тестируемый класс.
Допустим, в Log.DoSomething()
есть ошибка. К счастью, спецификация Gherkin найдет это, и ваши сквозные тесты не пройдут.
Эта функция не будет работать, потому что Log
не работает, а не потому, что [Do your job with someInput]
не выполняет свою работу. И, кстати, [Do your job with someInput]
несет полную ответственность за этот метод.
Также предположим, что Log
используется в 100 других функциях, в 100 других методах 100 других классов.
Да, 100 функций не будут работать. Но, к счастью, 100 сквозных тестов также не дали результатов и выявили проблему. И да: они говорят правду.
Это очень полезная информация: я знаю, что у меня неисправный продукт. Это также очень запутанная информация: она ничего не говорит мне о том, в чем проблема. Он сообщает мне симптом, а не основную причину.
Тем не менее, юнит-тест DoSomething
имеет зеленый цвет, потому что он использует поддельный Log
, созданный, чтобы никогда не ломаться. И да: это явно вранье. Он сообщает, что неработающая функция работает. Чем это может быть полезно?
(Если юнит-тест DoSomething()
завершится неудачно, убедитесь: [Do your job with someInput]
содержит ошибки.)
Предположим, это система с неработающим классом: ![Система с неработающим классом](https://i.stack.imgur.com/611ZY.jpg)
Одна ошибка нарушит работу нескольких функций, а несколько интеграционных тестов не пройдут.
![Одна ошибка нарушит работу нескольких функций, а несколько интеграционных тестов не пройдут](https://i.stack.imgur.com/rKhSr.jpg)
С другой стороны, та же ошибка нарушит только один модульный тест.
![Эта же ошибка нарушит только один модульный тест](https://i.stack.imgur.com/M64Vb.jpg)
Теперь сравните два сценария.
Эта же ошибка нарушит работу только одного модульного теста.
- Все ваши функции, использующие сломанный
Log
, красные
- Все ваши модульные тесты зеленые, только модульный тест для
Log
красный
Фактически, модульные тесты для всех модулей, использующих неработающую функцию, отмечены зеленым цветом, потому что, используя имитацию, они удаляли зависимости. Другими словами, они живут в идеальном, полностью вымышленном мире. И это единственный способ изолировать ошибки и искать их. Модульное тестирование - это издевательство. Если вы не издеваетесь, значит, вы не тестируете модуль.
Различия
Интеграционные тесты показывают, что не работает. Но они бесполезны для предположений, где может быть проблема.
Модульные тесты - это единственные тесты, которые говорят вам, где именно ошибка. Чтобы получить эту информацию, они должны запустить метод в имитируемой среде, где все остальные зависимости должны работать правильно.
Вот почему я думаю, что ваше предложение «Или это просто модульный тест, охватывающий 2 класса» как-то смещено. Модульный тест никогда не должен охватывать 2 класса.
Этот ответ в основном является резюме того, что я написал здесь: Модульные тесты врут, поэтому я их люблю.
person
Community
schedule
24.10.2011