1) Должны ли юнит-тесты использоваться повсеместно, как бы ни была мала и проста эта функция?
Нет. Если в функции нет логики (если while-циклы, добавления и т. Д.), Тестировать нечего.
Это означает, что функция добавления реализована следующим образом:
def add(a, b):
return a + b
У него нет ничего для проверки. Но если вы действительно хотите построить для него тест, то:
assert add(a, b) == a + b # Worst test ever!
- худший тест, который когда-либо мог написать. Основная проблема заключается в том, что проверенная логика НЕ должна воспроизводиться в коде тестирования, поскольку:
Если там есть ошибка, она будет также воспроизведена.
Вы больше не тестируете функцию, но a + b
работает одинаково в двух разных файлах.
Так что было бы больше смысла что-то вроде:
assert add(1, 2) == 3
Но, опять же, это всего лишь пример, и эту add
функцию даже не нужно тестировать.
2) Как справиться с изменением реализаций?
Это зависит от того, какие изменения. Имейте в виду, что:
- Вы тестируете API (грубо говоря, что для данного ввода вы получаете определенный результат / эффект).
- Вы не повторяете рабочий код в своем тестовом коде (как описано выше).
Таким образом, если вы не измените API своего производственного кода, тестовый код не будет затронут каким-либо образом.
3) Что делать, когда тест усложняется по сравнению с кодом, в котором он тестируется?
Кричи на тех, кто написал эти тесты! (И переписать их).
Модульные тесты просты и не содержат никакой логики.
4a) Всегда ли лучше начинать с юнит-тестов или лучше начинать с системных тестов?
Если мы говорим о TDD, то даже не должно быть этой проблемы, потому что даже до написания одной маленькой крошечной функции хороший разработчик TDD написал бы для нее модульные тесты.
Если у вас уже есть работающий код без тестов, я бы сказал, что модульные тесты легче писать.
4b) Что в начале разработки гораздо проще написать?
Модульные тесты! Поскольку у вас даже нет корня вашего кода, как вы можете писать системные тесты?