На работе один из моих проектов в основном связан с передачей данных от внешнего клиента и сохранением их в базе данных. Это корпоративное Java-приложение, использующее JPA, и большая часть нашей логики вращается вокруг операций CRUD.
Большинство наших ошибок так или иначе связаны с JPA.
- Пример 1. Если вы дважды нажмете кнопку сохранения, JPA может попытаться вставить один и тот же объект в базу данных еще раз, что приведет к нарушению первичного ключа.
- Пример 2. Вы извлекаете объект из базы данных, редактируете его и пытаетесь обновить его данные. JPA может попытаться создать новый экземпляр вместо обновления старого.
Часто решение нуждается в добавлении / удалении / изменении аннотации JPA. В других случаях это связано с изменением логики DAO.
Я не могу понять, как получить уверенность в нашем коде, используя модульные тесты и TDD. Я не уверен, что это потому, что юнит-тесты и TDD плохо подходят, или я неправильно подхожу к проблеме.
Модульные тесты кажутся неподходящими, потому что я могу обнаружить эти проблемы только во время выполнения, и мне нужно развернуть их на сервере приложений, чтобы воспроизвести проблемы. Обычно необходимо задействовать базу данных, которая, как я считаю, выходит за рамки определения модульного теста: это интеграционные тесты.
TDD кажется неподходящим, потому что цикл обратной связи deploy + test настолько медленный, что делает меня очень непродуктивным. Цикл обратной связи deploy + test занимает более 3 минут, и это только в том случае, если я запускаю тесты специально для кода, который пишу. Для запуска всех интеграционных тестов требуется более 30 минут.
За пределами этой формы есть код, и я всегда тестирую его по мере возможности. Но большинство наших ошибок и самые большие временные погрешности всегда связаны с JPA или базой данных.
Есть еще один похожий вопрос , но если бы я следовал совету, я бы обернул самую нестабильную часть своего кода (JPA) и протестировал все, кроме него. В контексте моего вопроса я был бы в такой же плохой ситуации. Какой следующий шаг после упаковки JPA? ИМО этот вопрос (возможно) является шагом к ответу на мой вопрос, но не является ответом на него.
источник
unit testing != TDD
)Ответы:
Одним из вариантов является использование базы данных тестирования в памяти, такой как H2 ; как правило, примерно в 10 раз быстрее, чем стандартная база данных, использующая диск, и с меньшим временем запуска / демонтажа.
Поможет ли это, во многом зависит от того, являются ли проблемы JPA, которые у вас возникли, достаточно общими, чтобы они по-прежнему терпели неудачу в другой базе данных. Не так много смысла проводить тесты быстрее, если они пропустят большую часть проблем.
Но если вы можете сделать 10 прогонов с H2 для каждого с полной системой, это может окупиться.
источник
Базы данных могут быть очень просты для модульного тестирования - вам нужны хранимые процедуры и транзакции.
Это то, что Microsoft говорит о модульном тестировании базы данных . Вы также можете запускать модульные тесты для базы данных, писать свои тесты на Java или C #, устанавливая соединение с БД, начинать транзакцию, записывать любые данные, которые вы хотите использовать для теста, в БД, запускать тесты и затем выполнять откат. Никаких повреждений БД, если вы использовали тот, на котором вы также развернули и получили полностью изолированные тесты.
Надеюсь, что это может дать вам некоторое представление о том, как это сделать в вашей структуре.
источник
Другие люди ответили: «Смейся!» - но какой смысл в том, чтобы макетировать слой вашей БД, если вам действительно нужно проверить, как он взаимодействует с вашим кодом?
То, что вы ищете, это интеграционные тесты и / или автоматизированные тесты пользовательского интерфейса. Вы упомянули, что проблема возникает, когда:
Единственный способ проверить это - написать автоматический тест пользовательского интерфейса, дважды нажав на кнопку. Может быть, проверить Селен.
Возможно, вам также понадобится БД для модульного тестирования, и ваши тесты указывают на это. Боль поддерживать, но добро пожаловать в TDD в реальном мире.
источник
В примере, который вы приводите в своем вопросе, вы не можете провести модульное тестирование / TDD, если дважды нажмите кнопку, чтобы очень легко вызвать ошибку. Но то, что вы можете выполнить модульное тестирование, это то, что в коде, который вызывается при нажатии кнопки, если вы получаете исключение из уровня персистентности, вы обрабатываете его соответствующим образом (либо путем макетирования уровня персистентности, либо с использованием базы данных в памяти как было предложено в других ответах) - либо перебрасыванием, либо отображением ошибки или чем-то еще.
Вы правы в том, что TDD может начать выходить из строя, когда вам нужно выполнить тесты, которые не подходят для модульного теста (например, интеграционные / системные тесты) - это сформировало довольно много дискуссий в недавнем "Is TDD" Мертв?" дебаты между Кентом Беком, Мартином Фаулером и Дэвидом Хейнемайером Ханссоном: http://martinfowler.com/articles/is-tdd-dead/
источник