Як я можу використовувати модульні тести та TDD для тестування програми, яка в основному покладається на операції CRUD бази даних?


22

На роботі один із моїх проектів - це здебільшого питання про отримання даних, переданих від зовнішнього клієнта, та збереження їх у базі даних. Це корпоративне додаток Java, що використовує JPA, і більшість нашої логіки обертається навколо операцій CRUD.

Більшість наших помилок так чи інакше залучають JPA.

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

Часто рішення потребує додавання / видалення / зміни анотації JPA. В інших випадках це стосується зміни логіки DAO.

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

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

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

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


Є ще подібне питання , але якби я дотримувався порад, я би загорнув найстабільнішу частину свого коду (JPA) і протестував би все, крім нього. У контексті мого питання я опинився б у тій же поганій ситуації. Який наступний крок після завершення програми JPA? ІМО, це питання - це (можливо) крок, щоб відповісти на моє запитання, але не відповідь на нього.


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

@randomAправильно, я змінив своє запитання, щоб чітко сказати це. Я не розумію, чому ти рекомендуєш змінити питання. Чи можете ви докладно? Я хочу тримати там тестування, тому що я краще пишу одиничні тести, ніж інтеграційні тести (хоча це я знаю unit testing != TDD)
Даніель Каплан

нічого особливого, хоча просто поставте туди TDD. Якщо у вас там є блок-тест, то багато людей думають, що ви нічого не розумієте тощо. Не добре для вас ..
InformedA


Відповіді:


7

Один із варіантів - використовувати базу даних для тестування в пам'яті, наприклад H2 ; Це, як правило, приблизно в 10 разів швидше, ніж стандартна база даних, що використовує диски, і з меншими часом запуску / спуску.

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

Але якщо ви зможете зробити 10 прогонів з H2 для кожного з повною системою, це може окупитися.


Це гарна думка, але мені все одно доведеться розгорнути сервер додатків, AFAIK. Це багато 3+ хвилин. Але це, безумовно, варто зробити. Але все ще важко уявити собі тестування виконання тестів так часто, як я би виконував одиничні тести, і тому здається, що це неефективно для розвитку TDD.
Даніель Каплан

1
Я думаю, що зазвичай існують такі способи, як навпаки (наприклад, docs.oracle.com/middleware/1212/toplink/TLADG/testingjpa.htm ). Досить високий шанс отримати більше роботи, ніж виправданий; Іншим варіантом було б отримати декілька серверів тестування і запустити паралельно.
сор

1
@tieTYT Мій власний доказ концепції про те, що блок hsqldb перевіряє веб-додаток на github: TestingWithHsqldb - тестові модулі не потребують розгортання програми.

3

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

Це те, що Microsoft говорить про тестування одиниць бази даних . Ви також можете запустити одиничні тести на базі даних, записавши свої тести на Java або C #, встановивши з'єднання з БД, розпочавши транзакцію, записати всі дані, які ви хочете використовувати для тесту, до БД, запустити тести і потім відкат. Немає шкоди для БД, якщо ви використовували один, до якого ви також розгорнулися, і ви отримаєте повністю ізольовані тести.

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


Як я вже сказав, "Більшість наших помилок так чи інакше пов'язані зі спільною програмою". Я думаю, що поради цієї статті пропустять усі ці. Крім того, якщо ви вважаєте, що ті тести Java / C # як і раніше є одиничними тестами, у нас є дуже різні визначення. Я думаю, що це взагалі хороша порада, але все ще здається, що для розгортання та запуску набору знадобиться багато часу, а отже, це не сприяє TDD. Ви не згодні?
Даніель Каплан

Ми використовували тести одиниць БД для нашого SQL, але тоді всі вони були в проростах. У той час як ви можете блок каталог тесту SQL з інших процедур SQL, наша модульне тестування рамки була MSTest тому мав сенс запускати їх звідти (агов, ми отримали зелені галочки в сервері збірки , який був найбільш важливим фактором). Якщо у вас завжди є БД (а ми це робили для внутрішнього тестування), то можна легко завантажити весь sql-код і виконати всі тести на одиничному сервері. Іноді просто потрібно бути прагматичним щодо цих речей.
gbjbaanb

Я не думаю, що ти відповів на моє перше речення.
Даніель Каплан

ну просто використовуйте jpa-unit тоді. Я не можу відповісти, як працює ваш JPA-код (чи ні), просто спробуйте дати вам декілька ідей щодо тестування цього sql в db.
gbjbaanb

3

Інші люди відповіли "Знущайтеся зі свого БД!" - але який сенс глузувати зі свого шару БД, якщо вам потрібно перевірити, як він взаємодіє з вашим кодом?

Що ви шукаєте - це інтеграційні тести та / або автоматизовані тести на інтерфейс користувача. Ви згадали, що проблема виникає, коли:

*If you click the save button twice*

Єдиний спосіб перевірити це - написати автоматизований тест інтерфейсу, щоб двічі натиснути кнопку. Можливо, перевірити Селен.

Можливо, вам також знадобиться БД для тестування блоку, і для ваших тестів вкажіть його на це. Біль за підтримку, але ласкаво просимо до TDD в реальному світі.


це звучить більше як вираз, ніж відповідь
gnat

Я тричі відповів на питання - інтеграційні тести, тести GUI та / або БД тестування блоку. Так, це трохи не скажеш, я зараз відредагую це на деяку подобу розуму.
Rocklan

1
"Єдиний спосіб перевірити це - написати автоматизований тест інтерфейсу, щоб двічі натиснути кнопку. Можливо, перевірити Selenium." У таких ситуаціях бекенд краще запобігти появі цього, інакше користувальницький інтерфейс матиме прямий доступ до бази даних.
Даніель Каплан

0

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

Ви маєте рацію, що TDD може почати руйнуватися, коли вам потрібно виконати тести, які не підходять для одиничного тестування (тобто інтеграції / системні тести) - це спричинило досить багато дискусій у нещодавньому "Є TDD Мертві? " дебати між Кентом Беком, Мартіном Фаулером та Девідом Хайнмейером Хансоном: http://martinfowler.com/articles/is-tdd-dead/

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