Если у вас нормальная архитектура (низкая связанность, компонентность), то в случае покрытия тестами компонентов (не классов по отдельности) существует большая вероятность того, что у вас все получится :) В противном случае мне известен только один способ:
1. Покрытие проекта функциональным тестами для фиксации текущего поведения.
2. Жесткий рефакторинг.
У меня создается такое впечатление, что большинство из пишущих комментарии слабо представляет себе, что такое TDD и зачем нужны модульные тесты. Откройте Кента Бека, там черным по белому написано: основная задач тестов ну никак НЕ тестирование кода, а создание хорошего дизайна. Поэтому комментарии типа «на тесты нужно писать тесты», «тесты не дают гарантии работоспособности» и прочие подобные просто показывают полную некомпетенцию их авторов в обсуждаемом вопросе. Я понимаю, что в википедии этого не написано, а блеснуть знаниями очень хочется, но все же.
Для чужого кода есть хорошая практика: необходимо перед рефакторингом зафиксировать его поведение юнит тестами на модули верхнего уровня или тестами черного ящика. И еще есть очень простое (но не совсем очевидное) правило: модифицировать можно либо тест, либо код, но не то и другое одновременно.
Перловые регулярные выражения знаю хорошо, а вот встроенные — не очень, поэтому и пользуюсь. К тому же реализация в перле одна из самых (самая?) мощных.
1. Покрытие проекта функциональным тестами для фиксации текущего поведения.
2. Жесткий рефакторинг.