Якщо модульні тести охоплюють лише функціональне програмне забезпечення


9

Ми використовуємо StructureMap в новому проекті розробки програмного забезпечення. Один з членів команди здійснив тестовий модуль, який в основному тестує конфігурацію контейнера StructureMap . Це роблять, роблячи наступне;

  • Підраховує кількість екземплярів збірок, налаштованих для класів у нашому просторі імен додатків.
  • Визначає очікувані екземпляри на рівні класу
  • Стверджує, що очікувані екземпляри відповідають загальній кількості знайдених примірників.
  • Стверджує, що очікувані екземпляри відповідають тим, що визначені в тесті

Прикладом цього є;

var repositories = container.GetAllInstances<IEnvironmentRepository>();
Assert.AreEqual(1, repositories .Count());
foundInstances = foundInstances + repositories .Count();

У нас також є «одиничні тести» для наступного класу;

public MyClass(IEnvironmentRepository environmentRepository)
        {

        }

У цих тестах ми знущаємось над IEnvironmentRepository, тому не вводимо його з контейнера, як це відбудеться в живій системі.

Колега проігнорував тест одиниці на конфігурації структури структури з коментарем у рядку "Тест на модуль перевіряє лише власну конфігурацію". Очевидно, це було тестом і, на мою думку, цілком справедливо. Я попросив хлопця, який проігнорував тест, видалити конфігурацію структури структури IEnvironmentRepository(при цьому тест все ще ігнорується) і запустити повний тестовий набір модулів, і всі вони пройшли. Потім ми запустили додаток, і воно перекинулося, оскільки конфігурація контейнера тепер була недійсною. На мою думку, це довело цінність тесту, мій колега все-таки не погодився. Він просто заявив, що ми не повинні тестувати конфігурацію, але вважаю, що це добре в межах компетенції одиничного тесту.

Отже, низка питань;

  • Це дійсний тестовий модуль - ми перевіряємо конфігурацію нашого контейнера, не працює ця структура структури (але я бачу перекриття)
  • Якщо ні, то як можна перевірити конфігурацію, не тестуючи її. Як можна зупинити, щоб хтось випадково видалив потрібний рядок коду та перевірив його?
  • Чи повинен MyClassтест модуля вирішити екземпляр IEnvironmentRepositoryз контейнера і передати його в?

10
9 з 10 розбіжностей у тестах виникають через те, що фреймворки підтримують автоматизовані тести у всіх їхніх формах, і люди хочуть вступити в семантику того, чи є той чи інший автоматизований тест хорошим та правильним одиничним тестом чи ні. Тест, який ви описуєте, звучить як такий, що не дуже-єдиний-тест-тест, який може бути дуже корисним для автоматизації (та запуску на контрольній реєстрації) - просто не називайте це одиничним тестом. Запитайте, чи спав би ваш колега краще вночі, якщо тест жив у власній функції / папці, яка чітко відокремлена.
Jeroen Mostert

2
Це також моя думка, ймовірно, корисна, і хоча це не суворо єдиний тест, він все ж додає цінності, і це було доведено. Його відповідь полягала в тому, що інші тести одиниці підхопили б це, але, на мою думку, якби вони були записані як суворі одиничні тести, ви знущалися б із залежностей і, отже, ніколи не дізнаєтесь, чи була конфігурація дійсною, доки ви її не використали.
ChrisBint

4
У вашого колеги є момент, коли він каже, що не тестувати конфігурацію, оскільки справжня конфігурація, яка насправді може змінюватись в залежності від розгортання, не може / не повинна бути перевірена - хто скаже, що "червоний" помиляється, а "синій" - ні? Тест був би щільно поєднаний з однією установкою. Але конфігурація, прив’язана до артефактів коду, є дещо винятком, оскільки вона не змінюється, і є явні способи помилитися. В ідеалі, ви б створили таку конфігурацію, сформовану під час збирання з метаданих DRY, але там, де це неможливо, тест, подібний цьому, додає значення. Краще, ніж помилка розгортання, яку можна уникнути.
Jeroen Mostert

2
Те, що ви описуєте, не перевіряє пристрій, воно перевіряє конфігурацію сторонніх програм. Фантастично корисно мати тести, які перевіряють ці речі, але вони є інтеграційними тестами, а не одиничними тестами, і відключення може бути корінь розбіжності.
Phoshi

3
@ChrisBint Доброта благодатна ні, я написав купу контейнерних тестів сам. Вони мають велику цінність, вони просто не є одиничними тестами. Це добре, інтеграційні тести надзвичайно цінні, тому що ловити речі не можуть .
Phoshi

Відповіді:


13

Це абсолютно правильний автоматизований тест. Я називаю їх «тестами на архітектуру», оскільки вони перевіряють надійність скелетних компонентів бази вашого коду.

Чи вміє контейнер IoC вирішувати та складати всі дерева об'єктів у додатку? Чи може автоматичний Mapper відображати між усіма зареєстрованими об’єктами без відмови? Чи центральний шар в архітектурі Onion не посилається на щось зовнішнє?

Ці тести можуть заощадити багато часу, коли пробігає помилка конфігурації, вказуючи на точного винуватця. Хороші рамки дадуть вам дуже точні повідомлення про помилки про те, що трапилося, і ви отримаєте їх, як тільки ви запустите тести (в ідеалі, безперервно) замість того, щоб закопати глибокий вниз слід стека виконання, якщо вам пощастить.

Будь то одиничні тести ... напевно, ні, але вони все ще працюють в пам'яті здебільшого і працюють досить швидко. Знову ж таки, я не знаю, це не так, як було загальновизнане визначення одиничного тесту.


За іронією долі, це майже так, як я пояснив це своєму колезі, і навіть під час перевірки (видаліть один із екземплярів контейнера та запустіть програму) він все ще не бачив жодної цінності. Я розумію, у кожного своя думка, і я озвучив свою;) Я люблю термін "тест на архітектуру", я збираюся це вкрасти!
ChrisBint

6

Проблема з таким тестом, який тестує внутрішні програми програми, а не вимоги до неї. Хіба що тест може вийти з ладу, навіть якщо програма працює як потрібно.

У вашому випадку, коли ви змінюєте налаштування контейнера, можливо, у вас з’являється нова залежність, яку потрібно вводити, ви зламаєте тест.

Крім того, якщо ви додаєте додаткову вимогу залежності, але забудьте додати її до контейнера та змінити тест контейнера. все пройде, але ваша програма вийде з ладу.

Кращим автоматизованим тестом було б запустити програму і побачити, чи не виходить з ладу.

Ви повинні вловлювати ці типи помилок при інтеграції або тестуванні інтерфейсу, навіть якщо вони потрапляють через одиничні тести.

Сказавши це, зростаюча складність установки контейнерів - це біль у дупі. Можливо, якісь «погані» тести варті того.


1

Код тестування одиничних тестів. Все, що знаходиться поза цим, - це "інше" автоматизоване тестування - називайте його, що вам зручно. Здається, ви тут тестуєте конфігурацію. Якщо конфігурація могла змінюватися залежно від середовища, вона не належить до одиничного тесту. Розгляньте можливість додавання атрибута тесту, щоб вказати, що тест відрізняється від інших тестів.


Конфігурація статична, вона не керується середовищем, всі класи, які існують у конфігурації, будуть використовуватися у всіх середовищах однаково. Так, кількість екземплярів, які можуть бути в конфігурації, повинна відповідати кількості екземплярів у налаштуваннях, що є частиною тесту. Як показав мій приклад, видалення IEnvironmentRepository дозволило пройти тести інших одиниць. Тест на конкретний контейнер не вдався б до двох записів; 1 - Загальна кількість можливих оголошень екземплярів не збігалася, а 2 - конкретна кількість екземплярів IEnvironmentRepository не відповідала б.
ChrisBint

1
Правильність контейнера визначається кодером. Той факт, що і код, що перевіряється, і сам тест повинні змінюватись для кожної модифікації, негайно встановлює дзвінок сигналу тривоги. DI - це засіб для досягнення мети, а не самоціль. Цілком можна писати код у стилі "DI" без структури-карти ergo, на мій погляд, це не сумлінний тест. Контейнер, звичайно, повинен бути доведений, але ефективність цього за допомогою автоматизованих тестів, здається, дещо суперечить обмеженій інформації, наданій тут.
Роббі Ді

2
Випробування підрозділу зайняли 10 хвилин, щоб збити. Розгортання може зайняти більше години.
ChrisBint

1
Враховуючи, що частина тесту одиниці конкретно підтверджує наявність одного конфігурації, не впевнений, як це не могло бути більш відокремленим. Загальний підрахунок, з яким я міг би погодитися.
ChrisBint

1
Тоді у них може бути якийсь пробіг - вирок дійсно для вас. Але їх слід відокремлювати фізично або через якийсь атрибут.
Роббі Ді

0

Відповідальність контейнера для нагнітання залежностей полягає в склеюванні різних модулів в одному робочому застосуванні .

Якщо ви пишете автоматизовані тести для вашої програми - у вас повинно бути декілька "інтеграційних (або прийнятних) тестів, які виконують тести" від кінця до кінця ", які перевірять весь конвеєр вашої програми, щоб усі модулі, що беруть участь у конкретному тестовому випадку, склеєні разом правильно .

Таким чином, ці тести інтеграції не зможуть, якщо контейнер для ін'єкцій залежності не був правильно налаштований. Що робить тести одиниць для контейнера самими марними, оскільки тест інтеграції повинен показувати можливі помилки в конфігурації контейнера.

Вам не потрібно охоплювати всі можливі тестові випадки в інтеграційних тестах, лише один тестовий випадок на кожну функцію, який повністю охоплює інтерфейс користувача до бази даних.

Якщо тестові випадки інтеграції не охоплюють примірника якоїсь конкретної залежності - ви просто додаєте таку.

За допомогою тестів на інтеграцію ви можете вільно змінювати контейнери без перезапису одиничних тестів для їх конфігурації.


0

ІМО, відповіді такі:

  1. Це дійсний тестовий модуль - ми перевіряємо конфігурацію нашого контейнера, не працює ця структура структури (але я бачу перекриття)

    • Це дійсний одиничний тест для структурованої карти , а не для вашого проекту, оскільки унітарна перевірка перевіряє певний код, при необхідності глузуючи з усіх залежностей, щоб перевірити реалізовану логіку. Логіка конфігурації реалізована в структурі карти, тому ця бібліотека повинна бути добре перевірена і повинна містити одиничні тести, як цей, який ви згадали, і багато іншого: вона повинна містити сотні таких тестів, як це, динамічно знущаючись з декількох конфігурацій під час виконання та тестуючи, щоб побачити, чи контейнер поводиться як слід.
  2. Якщо ні, то як можна перевірити конфігурацію, не тестуючи її. Як можна зупинити, щоб хтось випадково видалив потрібний рядок коду та перевірив його?

    • Ви можете протестувати конфігурацію вручну в необхідному середовищі, а також можете створити автоматику для цього (автоматизований тест), який тестує для конкретної конфігурації, яка вам потрібна (не потрібно знущатися над елементами під час виконання).
  3. Чи повинен тест модуля MyClass вирішити екземпляр IEnvironmentRepository з контейнера і передати це в?

    • Ні, це ідеальний одиничний тест, оскільки ви знущаєтесь над залежністю та випробовуєте логіку MyClass ізольовано.

-1

UnitTest перевірити бажану поведінку підрозділу при розділенні .

Це означає, що будь-яка конфігурація не входить до сфери UnitTests .

Тим не менш, у вас повинні бути автоматизовані тести для вашої конфігурації, але це не UnitTests ...


Де ви отримуєте визначення одиниць?
ChrisBint

Мені подобається роя Роше Ошерово в " The Art Of Unittestte : A Unit" - це будь-який фрагмент (виробничого) коду, який має ті самі причини, що потрібно змінити. Я, мій світ, зазвичай коливається від одного класу до трьох-п’яти ...
Тімоті Віклер

Це виробничий код, який тестується.
ChrisBint

Просто хотів відволікти анітропиків , не очікуючи, що це теж навпаки ...; o)
Тімоті Вірле,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.