Як TDD, щоб повернути правильні результати


12

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

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

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

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

Я думав, я можу передати діапазон дат у програму GetValidPOs і дозволити йому використовувати ці значення для повернення дійсних PO. Але що робити, якщо ми додамо ще одну вимогу до того, що вважається дійсним ПЗ?

І як я тестую це і переконуюсь, чи він працює? Ми не використовуємо ORM, і це навряд чи станеться. І я не можу викликати БД у своєму тесті.

Я застряг.

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

Це має сенс? Або є кращий спосіб?

ОНОВЛЕННЯ: Я можу використовувати EF, здавалося б. Тепер мені просто потрібно розібратися, як ним користуватися, і зробити його перевіряючим, все ще будучи спроможним покластися на збережені процедури та труднощі розсипання даних по декількох базах даних.


З цікавості, чому ви не можете вибрати лише дійсні PO-адреси звичайним оператором SQL? (Це запитання чи відповідь не передбачає рішення.)
scfridge

Відповіді:


7

Це є головним недоліком збережених процедур у віці TDD. У них є реальні переваги навіть зараз, але за визначенням, будь-який тест, який здійснює збережену процедуру, не є одиничним тестом; це інтеграційний тест у кращому випадку.

Звичайним рішенням, якщо припустити, що архітектура не може змінитись на використання ORM замість цього, є не ставити ці тести в набір тестових одиниць; замість цього помістіть тести в інтеграційний набір. Ви все ще можете запускати тест коли завгодно, щоб переконатися, що він працює, але тому, що вартість, притаманна налаштуванню тесту (ініціалізація БД з належними тестовими даними), є високою, і вона торкається ресурсів модуля тестування блоку для складання-бота. мати доступ до цього, він не повинен бути в наборі тестових пакетів.

Ви все ще можете перевірити одиничний код, який вимагає даних, абстрагуючи те, що ви не можете тестувати з одиничними тестами (класи ADO.NET), на клас DAO, з якого потім можна знущатися. Потім ви можете переконатися, що очікувані дзвінки здійснюються за допомогою споживання коду та відтворення поведінки в реальному світі (наприклад, не знайдених результатів), що дозволяє тестувати різні випадки використання. Однак фактичне налаштування SqlCommand для виклику збереженого протоколу є майже останньою справою, яку ви можете провести тестуванням, відриваючи створення команд від виконання команд та глузуючи з виконавця команд. Якщо це звучить як багато розділення проблем, це може бути; пам’ятайте, «не існує жодної проблеми, яка не може бути вирішена іншим шаром непрямості, за винятком занадто великої кількості шарів непрямості». У якийсь момент ви повинні сказати "достатньо; я просто не можу перевірити це, ми"

Інші варіанти:

  • Перевірте збережену програму, використовуючи "короткочасний" екземпляр СУБД, як SQLite. Зазвичай це простіше зробити при використанні ORM, але тест потім можна зробити "в пам'яті" (або заздалегідь встановленим файлом бази даних, включеним до тестового набору). Це все ще не одиничне тестування, але його можна запускати з високим ступенем ізоляції (СУБД є частиною запущеного процесу, а не те, що ви віддалено підключаєте, що може опинитися посеред чужої суперечливої ​​набір тестів). Мінус полягає в тому, що зміни у збереженій програмі можуть відбуватися у виробництві без тесту, що відображає зміни, тому вам доведеться бути дисциплінованими щодо того, щоб переконатися, що зміни вперше зроблені в тестовому середовищі.

  • Розгляньте можливість оновлення до ORM. ORM з постачальником постачальників Linq (практично всі спільні користувачі мають його) дозволить вам визначити запит як оператор Linq; потім цей випадок може бути наданий схожему сховищу, який має в пам'яті колекцію тестових даних, до яких його можна застосувати. Таким чином, ви можете перевірити правильність запиту, навіть не торкаючись БД (ви все одно повинні запустити запит в середовищі інтеграції, щоб перевірити, чи може постачальник Linq правильно перетравити запит).


2
-1 тому TDD! = Одиничне тестування. Ідеально добре включати тести рівня інтеграції під час виконання TDD.
Стівен А. Лоу

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

1
Я все це розумію, ви обоє. Де я сказав, що це тест на інтеграцію означав, що ви не можете його TDD? Моя думка полягала в тому, що збережена процедура не може бути протестована ізольовано, що ви хочете зробити для більшої частини вашої кодової бази. Натомість тестування SP вимагає більш складних, триваліших інтеграційних тестів; хоча вони все ще краще, ніж тестування вручну, складний тестовий набір може зайняти кілька годин і може згубно вплинути на зусилля CI.
КітС

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

Збережені процедури можна перевірити ізольовано. Як інакше вони були б підтверджені? Для Transact SQL є tSQLt ( tsqlt.org )
Кевін Клайн

4

Моя порада - розділитись і перемогти . Забудьте про базу даних та збереження на даний момент часу і зосередиться на тестуванні фальшивих реалізацій ваших сховищ або об’єктів доступу до даних.

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

Я б знущався над сховищем, яке повертає замовлення на купівлю. Створіть макет із двадцяти непарних замовлень на купівлю.

Я думав, я можу передати діапазон дат у програму GetValidPOs і дозволити йому використовувати ці значення для повернення дійсних PO. Але що робити, якщо ми додамо ще одну вимогу до того, що вважається дійсним ПЗ?

Заглушіть виклик GetValidPOs, щоб він викликав ваш макет, а не процедуру бази даних.

І як я тестую це і переконуюсь, чи він працює? Ми не використовуємо ORM, і це навряд чи станеться. І я не можу викликати БД у своєму тесті.

Вам потрібен блок-тест, щоб переконатися, що правильні дані повертаються з макету.

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

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

Як я вже говорив, вам потрібен макет, який повертає хоча б деякі дані, які ви можете запитувати.

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


Це те, що я намагаюся зробити. Просто виникають труднощі з написанням реальної реалізації, яка буде працювати так само, як і макет, оскільки наш доступ до даних не сприяє використанню ORM. Більшість потрібних мені даних є в декількох системах, і до них слід отримати доступ через веб-сервіси ... навіть під час оновлення.
CaffGeek

0

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

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

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

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

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