Когда ты разрабатываешь какое то приложение, не важно на сколько сложное, ты же не пишешь его с нуля и до конца полностью (точнее такое бывает но редко, для не сильно больших задач и у этого метода есть недостатки - больше подвержен ошибкам), наоборот, код идеологически разбивается на части или этапы разработки, каждый из которых пишется по очереди, до принципиальной возможности запуска, часто кстати в уже написанные части подставляются заглушки (и/или подсовывается база данных в определенном состоянии) и добавляются отладочные сообщения, чтобы приложение запустилось в нужном состоянии чтобы в принципе была возможность протестировать только что написанную часть.
Под протестировать я подразумеваю любой способ проверить, что получится, как программа отреагирует (например что напишет в логах), и сравнить это с ожидаемым поведением.
Что значит ожидаемое поведение? когда ты делишь задачу на подзадачи, у тебя появляются промежуточные данные и состояния, ну как в анекдоте про чайник и программиста, чтобы заварить чай нужно:
* налить воду в чайник
* поставить на базу/печку и включить
* дождаться готовности/выключить
* налить чай
на каждом этапе нужно проверять состояние, например первый пункт - есть ли вода в чайнике, горячая ли она или холодная, полный ли чайник, есть ли у тебя чайник в руках, и т.п.
Тесты создают на основе данных, являющихся нормальными, ненормальными и граничными для тех алгоритмов, что используются в коде. К примеру нет нужды проверять температуру воды в чайнике отдельно на фиксированные значения 10, 20, 30,.. градусов, если в алгоритме заложены естественные их границы - холодная и горячая, вот вокруг этих констант и приходится гулять.
Вот именно эти проверки и есть тесты, которые необходимо автоматизировать.
Степень полноты тестирования вопрос философский, в конечном счете тесты нужны не только для автоматического тестирования и составления отчетности на изменения кода, но и собственно для разработки, разрабатывая тесты ты делаешь код полнее и точнее (например проверяя температуру воды на первом шаге ты добавишь в код условие - если вода горячая, то пропустить ее нагрев), почитай про test-driven development, TDD
p.s. а еще тесты - это способ исследовать неизвестную библиотеку, дело в том что open source реалии таковы, что документации нет от слова совсем, в лучшем случае перед тобой список методов с типами аргументов и пара примеров, все остальное нужно догадываться по логике наименований, здравому смыслу и ковырянии в исходниках. Тесты тут могут быть исключительно как способ изучения этой библиотеки, но не обязательно такие тесты реализовывать в коде, это все же процесс в ручную происходит, но все же, создавать тесты на ответы от чужой библиотеки полезно для длительной поддержки проекта для того, чтобы у тебя были алерты на необычное поведение ее после обновления)
создание правильных и полных тестов очень сильно повышают стоимость разработки и поддержки проекта, причем чуть ли не на порядок, но дает некоторую защиту от смерти проекта в будущем из-за накапливающихся ошибок, о которых ничего не ясно без тестов.
и еще, создать тесты с нуля на готовый проект почти невозможно.