Как мне разбить это на модульные тесты?
У меня есть метод, который вызывается для объекта, чтобы выполнить некоторую бизнес-логику и добавить его в базу данных.
Объект является Транзакцией, и часть бизнес-логики требует поиска в базах данных связанных учетных записей и элементов истории в учетной записи.
Затем есть ряд сравнений и операций, которые должны вернуть информацию из учетной записи и применить ее к транзакции, прежде чем транзакция затем будет передана другим людям и записана в базу данных.
Единственный способ, которым я могу придумать для тестирования этого в настоящее время, состоит в том, чтобы в рамках теста создать учетную запись и соответствующую информацию истории, затем построить транзакцию для каждого отдельного сценария и захватить информацию, записанную в БД для транзакции, и информацию, передаваемую на Однако это похоже на слишком сильное тестирование в одном тесте. Каждый сценарий будет выполняться в отдельном модульном тесте, при этом конструкция теста будет реорганизована в отдельные методы, но фактический кусок кода, предназначенный для теста, имеет длину более 500 строк.
Я думаю, что этот вопрос больше о рефакторинге, чем модульном тестировании, но в этом случае они идут рука об руку.
Если у кого-нибудь есть совет (хороший или плохой), я буду рад его услышать.
РЕДАКТИРОВАТЬ:
Псевдокод:
Find account for transaction
Do validation on transaction codes and values
Update transaction with info from account
Get related history from account Handle different transaction codes and values (6 different combinations, each with different logic)
Update the transaction again with new account info (resulting from business logic)
Send transaction to clients
4 ответа
Я был бы признателен, если бы у вас был какой-то псевдокод по этому вопросу, но просто следуя ему, я бы:
- Создайте интерфейсы для объектов доступа к данным, которые непосредственно обращаются к базе данных - таким образом, вы можете передать объект, который только притворяется (например, имитирует), что он обращается к базе данных. Затем этот объект будет возвращать результаты в соответствии с результатами, которые будет возвращать ваша база данных, без какого-либо вызова БД. Ваш объект также может имитировать такие сценарии, как откат данных до исходного состояния.
- Извлеките каждый "сценарий" в один метод каждый - это сущность единицы. Если ваш метод имеет длину 500 строк, то там должны быть смежные блоки, которые можно извлечь. Напишите модульный тест для каждого, если это необходимо.
- Если ваш модульный тест слишком много тестирует, это, вероятно, означает, что ваш метод делает слишком много - вы можете извлечь методы, идентифицируя различные тестируемые объекты, а затем помещая их в свои собственные методы. Промойте и повторяйте, пока вам не понадобится только один тест для каждого метода.
- Транзакции, "переданные другим людям", звучат как запах кода - транзакция сама по себе должна быть только одной непрерывной единицей. Если вам нужны разные пользователи для завершения транзакции, вы делаете слишком много; вместо этого следите за состоянием ваших данных в БД, с точки зрения флагов и т. д., а не с точки зрения транзакции с БД.
Отделение модулей от существующего унаследованного кода может быть чрезвычайно сложным и длительным. Проверьте эффективность эффективной работы с устаревшим кодом для ознакомления с разнообразными опробованными и проверенными методами, которые сделают вещи более управляемыми.
Это зависит от того, что вы хотели бы проверить. Вы хотите проверить транзакцию базы данных? Хотите проверить бизнес-транзакцию или что-то еще? Попробуйте использовать макеты для вещей, которые вы не хотели бы тестировать. С макетами вы можете сосредоточиться на определенных целях теста.
Да, вы можете переписать текущий код, чтобы его можно было тестировать модульно в соответствии со всеми рекомендациями и рекомендациями.
Тем не менее, это может быть дорого, и вы должны оценить стоимость и сравнить это с заработком...
Выгода в том, что вы можете обнаружить проблему с кодом, а также, если все сделано правильно, снижение сложности в результате рефакторинга.
Оба фактора могут сэкономить время - в будущем.
Стоимость - это время и усилия, которые вы должны потратить как на рефакторинг вашего кода, на написание тестовых примеров, так и на дополнительное время, которое вам, возможно, придется потратить в будущем на сопровождение тестовых случаев и проверочного кода - и это может быть значительными затратами.,
Вы сравниваете известную стоимость с будущим риском, и я уверен, что многие умные ребята знают, как это сделать, но очевидно, что вы можете потратить бесконечное время на рефакторинг и насмешки, даже не уменьшив риск отказа до нуля (или даже если код и проблема сложны и вы путаетесь во время рефакторинга), вам нужно найти баланс здесь.
В этом случае, поскольку код устарел, может быть нормально быть "неаккуратным" или "прагматичным" и выполнять тестирование "черного ящика" - или тестирование "сверху вниз" и просто тестировать интерфейс (или абстракцию), не беспокоясь о макете базы данных. И да, вы можете утверждать, что это не модульный тест, а системный тест или тест функциональных тестов.
... Но это может дать наилучшую отдачу от ваших денег - или денег ваших работодателей / клиентов - или больше времени с вашим значимым другом (или, по крайней мере, больше времени для просмотра канала обнаружения).
Если у вас старый код, разрешите тестирование черного ящика, разрешите зависимости между тестами и скомпилируйте последовательность тестов, которая устанавливает тестовые данные и манипулирует ими, и, по крайней мере, они автоматически тестируются, хотя и не тестируются на 100%.