Я тестирую интеграционную систему, используя только общедоступные API. У меня есть тест, который выглядит примерно так:
def testAllTheThings():
email = create_random_email()
password = create_random_password()
ok = account_signup(email, password)
assert ok
url = wait_for_confirmation_email()
assert url
ok = account_verify(url)
assert ok
token = get_auth_token(email, password)
a = do_A(token)
assert a
b = do_B(token, a)
assert b
c = do_C(token, b)
# ...and so on...
По сути, я пытаюсь проверить весь «поток» одной транзакции. Каждый шаг в потоке зависит от предыдущего успешного шага. Поскольку я ограничиваю себя внешним API, я не могу просто заносить значения в базу данных.
Итак, у меня есть один действительно длинный метод тестирования, который выполняет `A; утверждают; B; утверждают; C; assert ... ", или я делю его на отдельные методы тестирования, где каждому методу теста нужны результаты предыдущего теста, прежде чем он сможет выполнить свою задачу:
def testAccountSignup():
# etc.
return email, password
def testAuthToken():
email, password = testAccountSignup()
token = get_auth_token(email, password)
assert token
return token
def testA():
token = testAuthToken()
a = do_A(token)
# etc.
Я думаю, что это пахнет. Есть ли лучший способ написать эти тесты?
Я бы отделил тестовый код от кода установки. Может быть:
Помните, что вся генерируемая случайная информация должна быть включена в утверждение в случае, если оно не выполнено, иначе ваш тест может оказаться невоспроизводимым. Я мог бы даже записать случайное использованное семя. Кроме того, каждый раз, когда случайный случай терпит неудачу, добавьте этот конкретный ввод в качестве жестко закодированного теста, чтобы предотвратить регрессию.
источник
Не намного лучше, но вы можете по крайней мере отделить код установки от утверждения кода. Напишите отдельный метод, который будет рассказывать всю историю шаг за шагом, и выберите параметр, управляющий тем, сколько шагов нужно сделать. Тогда каждый тест может сказать что-то вроде
simulate 4
или,simulate 10
а затем утверждать, что он тестирует.источник
Ну, я мог бы не получить синтаксис Python прямо здесь, используя «кодирование по воздуху», но я думаю, вы поняли идею: вы можете реализовать общую функцию, подобную этой:
что позволит вам написать ваши тесты так:
Конечно, это спорно, если потеря читаемости этого подхода стоит использовать его, но это уменьшает шаблонный код немного.
источник