В чём была ситуация. После приделывания к своим скриптам по скачиванию дайари штуки, показывающей комментарии, я понял, что мне действительно нужна система автоматического/полуавтоматического тестирования. Потому что это ещё не всё, что я хотел запилить, а после каждого запиливания мне нужна уверенность, что всё правильно.
Что я делал раньше? Я прогонял все скрипты, а потом сравнивал выходную папку с файлами и "эталонную", полученную с предыдущей версией скриптов. Сравнением занимался WinMerge. Если я видел разницу, я начинал выяснение -- должна была эта разница появиться или это ошибка.
Такой подход довольно затратен.
Исключением был модуль по работе с БД, db.py. Хотя у него и не было "юнит-тестирования", но у него был "генеральный прогон", вызывавший все функции модуля по очереди с тестовыми данными. Данные не проверялись, просто результаты выводились на экран. Я сэкономил немало сил и времени постоянно запуская этот прогон после модификаций. Он быстрее ловил ошибки в SQL и в питон-синтаксисе, чем если бы я каждый раз проводил полное преобразование дневника.
Тестирования модуля БД было мало. Мне была нужна уверенность в конечном результате. Тем не менее, я решил начать именно с модуля БД, превратив "генеральный прогон" в серию тестов. Я написал несколько первых тестов для py.test, разобрался что к чему, а потом понял, что у меня есть философские вопросы о том, как же следует делать тесты. И практические вопросы -- как делать принято?
В интернете есть достаточное количество статей о юнит-тестировании для начинающих. Их об'единяет общая проблема. Они показывают тестирование на примере функции сложения двух чисел. Как же приложить такое тестирование к более сложной системе?
За ответами на этот вопрос я обратился к данной книжке и не ошибся.
Книжка короткая, всего 300 страниц. Информации в ней мало, и она довольно простая. Но подана она систематически. Всего десяток тезисов, каждому из которых дано подробное обоснование, и приведены примеры -- сложнее, чем сложение двух чисел. После чтения у меня в голове образовался каркас знаний по теме. И я могу его применять.
Настолько вменяемых книжек существует совсем немного.
Кроме того, я нашёл в книжке подтверждение догадок, которые у меня появились, когда я пытался написать тесты. А ещё я нашёл ответы на все мои вопросы, которые у меня возникли до чтения.
И главный вопрос у меня был такой: почему для модуля БД тесты написались практически сами собой, а для остальных модулей я даже понять не могу, как к этому подступиться? Почему я не понимаю, куда приложить тесты к коду в проектах по работе?
А ответ такой. Чтобы тесты писались, код должен быть разделён на логику и на работу с внешними зависимостями ("коллабораторами", как называет автор). Наши рабочие проекты производят реальные замеры реальных значений, и выдают выходные значения сразу на железо. Это "переусложнённый код", который требует кардинальной переработки. В принципе, разделить логику и работу с внешними устройствами у нас можно, хотя придётся потратить на это довольно много усилий. Но вот можно ли симулировать серии из десятков тысяч входных значений? Как потом анализировать десятки тысяч выходных, не вглядываясь вдумчиво в графики? Это нужно пилить отдельный фреймворк для работы с фальшивыми значениями. И, возможно, этим стоит заняться.
Скрипты по скачиванию дайари проще. Но они всё равно по классификации автора относятся к "переусложнённому коду". Моя 500-строчная функция download() из download.py делает всё. А должна делать только одно действие. Модуль БД, напротив, содержит десятки мелких функций, каждая из которых делает простую вещь. Поэтому-то этот модуль так легко тестируется.
В общем, юнит-тестирование во многом завязано на архитектуру. И архитектурным вопросам автор посвятил, наверное, треть книги.
И, возможно, эта треть важнее, чем сами тесты и тестирование вообще.