Що є вирішальною перевагою тестування одиниць проти інтеграційного тестування?
Це помилкова дихотомія.
Тестування блоків та тестування інтеграції виконують дві подібні, але різні цілі. Мета тестування блоку - переконатися, що ваші методи працюють. На практиці, одиничні тести переконуються, що код відповідає договору, визначеному одиничними тестами. Це очевидно в тому, як створені одиничні тести: вони конкретно заявляють, що повинен робити код, і стверджують, що код це робить.
Інтеграційні тести різні. Інтеграційні тести здійснюють взаємодію між компонентами програмного забезпечення. Ви можете мати програмні компоненти, які проходять усі їхні тести та все ще не спрацьовують інтеграційні тести, оскільки вони не працюють належним чином.
Однак, якщо є вирішальна перевага в одиничних тестах, це саме так: одиничні тести налаштовуються набагато простіше і вимагають набагато менше часу та зусиль, ніж тести інтеграції. При правильному використанні одиничні тести заохочують розробку "перевіряемого" коду, а це означає, що кінцевий результат буде надійнішим, легшим для розуміння та простішим у підтримці. Тестовий код має певні характеристики, як-от узгоджений API, поведінку, що повторюється, і він повертає результати, які легко стверджувати.
Інтеграційні тести складніші та дорожчі, тому що вам часто потрібні складні глузування, складні налаштування та складні твердження. На найвищому рівні системної інтеграції уявіть собі спробу імітувати взаємодію людини в інтерфейсі. Цієї програмної системи присвячено такій автоматизації. І це автоматизація, яку ми шукаємо; тестування на людях не повторюється і не має масштабів, як це робить автоматизоване тестування.
Нарешті, тестування інтеграції не дає гарантій щодо покриття коду. Скільки комбінацій циклів, умов та гілок ви перевіряєте за допомогою інтеграційних тестів? Ви справді знаєте? Існують інструменти, які ви можете використовувати з тестовими одиницями та тестовими методами, які підкажуть, скільки у вас є покриття коду та яка цикломатична складність вашого коду. Але вони дійсно добре працюють на рівні методів, де живуть одиничні тести.
Якщо ваші тести змінюються щоразу, коли ви рефактор, це вже інша проблема. Експертні тести повинні стосуватися документування того, що робить ваше програмне забезпечення, доведення того, що він це робить, а потім доведення того, що він робить це знову, коли ви переробляєте основу реалізації. Якщо ваш API змінюється, або вам потрібні ваші методи для зміни відповідно до зміни в дизайні системи, саме це повинно відбутися. Якщо це відбувається багато, подумайте, перш ніж писати код, написати свої тести. Це змусить задуматися про загальну архітектуру та дозволить писати код із уже створеним API.
Якщо ви витрачаєте багато часу на написання одиничних тестів на кшталт тривіального коду
public string SomeProperty { get; set; }
тоді слід переглянути свій підхід. Передбачуване тестування повинно перевіряти поведінку, і в рядку коду вище немає поведінки. Однак ви десь створили залежність у своєму коді, оскільки ця властивість майже напевно буде передана в іншому місці вашого коду. Замість цього слід розглянути методи написання, які приймають необхідну властивість як параметр:
public string SomeMethod(string someProperty);
Тепер ваш метод не має ніяких залежностей від чогось поза собою, і він тепер більш перевірений, оскільки він є повністю самостійним. Зрозуміло, ви не завжди зможете це зробити, але він переміщує ваш код у напрямку, щоб бути більш перевіреним, і на цей раз ви пишете одиничний тест на фактичну поведінку.