Як ви пишете тести на код, який залежить від конкретних зовнішніх реалізацій, над якими не можна глузувати?


17

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

Проблема, однак, полягає в тому, що модуль покладається на незамінні зовнішні фактори, а саме PDF-файли та XSL. В основному я читаю XML з бази даних і застосовую до неї перетворення XSL, а потім конвертую її в PDF за допомогою бібліотеки під назвою ABCPDF. Потім цей PDF об'єднується з іншим PDF на основі статичного шаблону. Я знаю, що я можу перевірити XML і переконатися, що значення є правильними, але багато потенційних помилок і проблем пов'язані з фактичним відображенням готового документа - наприклад, деталі, як, наскільки довгі текстові рядки загорнуті, де певні області HTML розташовані відносно документа тощо. Чи можливо навіть тестувати ці речі (я розумію, що це, мабуть, тести інтеграції чи .. третій вид тесту, ім'я якого я забуваю [не тести прийняття, інший вид], а не одиниця тести), оскільки, наскільки мені відомо, я не можу легко змайструвати PDF-файл, не створюючи його, потім прочитати його назад або створити HTML-рядок (тобто перетворений XML) та розібрати її вручну, щоб перевірити наявність певних комірок таблиці в відношення до інших комірок таблиці.

У такій ситуації, чи варто просто зосередитись на одиничних тестах, щоб переконатися, що інформація є правильною, і що я можу створити PDF, або об'єднати їх, або будь-яку іншу, і вдатися до тестування вручну для актуальних проблем із відображенням?


6
"зовнішні фактори, що не підлягають неможливості" - це натяк на те, що ви в першу чергу не робите одиничні тести. Це означає інтеграційне тестування. Що ти хочеш зробити? Одиничне тестування вашого коду чи інтеграційне тестування цієї складної речі? Будь ласка, виберіть те чи інше, тому що важко говорити про те й інше одночасно.
С.Лотт

2
Я не купую "незнімних". Я прийму "що я не знаю, як знущатися", що означає, що ваше справжнє питання "як я знущаюся над цим?".
Рейн Генріхс

Можливо :) Я знайомий з глузуванням з використовуваного XML, але не з того, як знущатися над фактичним PDF чи HTML-документом, коли форматування має значення.
Уейн Моліна

1
Я думаю, ви маєте на увазі тести "функціональні" (додаток від кінця до кінця) або "системні" (кілька додатків від кінця до кінця)
Gary Rowe

@Gary - Так, функціональним було слово. Я їх зараз пам'ятаю з вивчення Rails: Моделі тестових модулів, Контролери функціональних тестів, Інтеграційні тести все
Уейн Моліна

Відповіді:


13

Тестуйте функцію, а не пристрій

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

Майбутні тести, що використовують одні й ті ж введення xml, можуть зіставити бінарний файл із посиланням.

Якщо порівняння на рівні файлів є незадовільним, покажіть PDF в кінці тесту і зробіть знімки екрана, а потім автоматичне тестування порівняйте з еталонними знімками екрана.


+1, тому що вас цікавить лише кінцевий результат на цьому рівні. Якщо ви змінили реалізацію способу отримання PDF-документа, вам не доведеться змінювати функціональний тест.
Гері Роу

2
+1 за гарну пораду. Це те, що ми робимо в нашому поточному проекті. Ми створили спеціальний набір інструментів для порівняння PDF, який дозволяє нам опускати зміни деталей у документах, таких як часові позначки. Caveat: перехід на інший (версію) PDF-рендерінга може спричинити тонкі зміни в макеті, спричиняючи пряме бінарне порівняння з набором сигналів помилкових позитивних результатів.
Péter Török

5

Зазвичай у такому випадку ви абстрагуєте все, що не можете перевірити за реалізацією, яку ви можете використовувати з інтерфейсом. Я просто зроблю щось нерозумно, як PDF builder, тому що це здається розумним.

public class PdfBuilder : IPdfBuilder
{
  public byte[] BuildPdf(...)
  {
    // actual untestable code here
  }
}

public interface IPdfBuilder
{
  byte[] BuildPdf(...);
}

Потім ви можете знущатися над IPdfBuilder у своїх тестах, щоб робити все, що завгодно. Це часто означає, що потрібно починати використовувати контейнер IoC ( /programming/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code та /programming/21288/which-net-dependency-injection-frameworks-are-worth-looking-into як місце для початку), якщо ви його зараз не використовуєте.

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

Повідомте мене, якщо це не зовсім зрозуміло.


+1 для приховування нестійкого коду. Потім ви можете робити тести вручну, поки не розберете, що потрібно перетнути через цей інтерфейс, щоб отримати правильний результат, і тест одиниці для того, щоб генеруватися належним чином, щоб отримати тести регресійних одиниць.
Етел Еванс

1

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

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


Це дуже щільно поєднано, але це сфера, яку я не можу виправити, оскільки немає жодної плати, щоб зробити її вільно пов'язаною і жодних ресурсів не присвячено рефакторингу (але це зовсім інший набір питань).
Уейн Моліна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.