Очень философский вопрос.
Наверное, стоит начать с того, чтобы определить для себя, что считать багом в коде. Это не вполне тривиальная задача и в общем случае такое определение можно делать после того, как вы сделали постановку задачи и зафиксировали требования, которым код должен удовлетворять. Затем можно уже думать, как эти требования а) разбить на более атомарные если такое приемлемо, б) как требования из получившегося списка тестировать.
Как правило, этого может быть недостаточно, поскольку такое разбиение вряд ли на 100% покроет все детали реализации (хотя позволит вывести метрики качества продукта). Детали реализации можно и нужно проверять юнит тестами (например, использовать TDD, если он вообще подходит).
Ну и не забывать про закон Галла в процессе кодирования.
Больше тестов - меньше багов.
Писать коротко. Писать только методом копипасты. Перепроверять накопипащенное. Давать проверить и потом перепроверить кому-либо еще.Прежде чем поставить статус "я написал" протестировать всеми доступными способами, тихонько исправить вылезшее.
Вот так может и получится "писать без багов"...