Существует несколько причин, поэтому я могу подумать о следующих:
Модульность
При написании программного обеспечения вы всегда стараетесь сделать свой код модульным и многократно используемым.
Написание функций в целом уже следует этой философии:
Вы можете использовать эту функцию во многих местах кода без написания повторяющегося кода.
Функции модульного тестирования позволяют вам проверить, выполняет ли эта единственная функция ожидаемый от нее контракт, независимо от того, где вы ее используете.
Таким образом, вы можете доверять этой функции, когда вам понадобится использовать ее снова в более поздний момент времени, возможно, с новым набором параметров, которые могут заставить функцию вести себя по-другому. Вы можете эффективно протестировать все возможные логические ветви в этой функции отдельно, даже те, которые вы, возможно, не используете пока . (Спасибо, @JBNizet)
Этот момент становится еще более очевидным, когда вам придется рефакторинг вашего кода.
Точность
Когда ваш API-тест не пройден, вы не знаете, какая часть кода в вашем, возможно, сложном приложении вызывает проблему.
Однако, когда модульный тест для одной функции завершается неудачно (что может также привести к сбою теста API), вы знаете, что код в этой самой функции неверен. Это сэкономит вам много времени.
Сложность
Тесты API экспоненциально сложнее писать, особенно если они должны охватывать все возможности всех функций, вызываемых API.
Это тоже делает их намного медленнее.
(еще раз спасибо, @JBNizet)
В целом, все сводится к парадигме программирования «разделяй и властвуй»: разбивайте любую имеющуюся проблему на наименьшие возможные подзадачи, пока не останутся только тривиальные проблемы (или в данном случае: модульные тесты).