Протестируйте свой код, как тот, кто будет его использовать после прочтения документации. Не проверяйте ничего, основываясь на своих знаниях, потому что вы написали или прочитали код. Вы хотите убедиться, что ваш код ведет себя как ожидалось.
В лучшем случае вы сможете использовать свои тесты в качестве примеров. Док-тесты в Python являются хорошим примером для этого.
Если вы следуете этим рекомендациям, изменение реализации не должно быть проблемой.
Также, по моему опыту, рекомендуется проверять каждый «слой» вашего приложения. У вас будут атомарные юниты, которые сами по себе не имеют зависимостей, и у вас будут юниты, которые зависят от других юнитов, пока вы в конечном итоге не доберетесь до приложения, которое само по себе является юнитом.
Вам следует тестировать каждый слой, не полагайтесь на тот факт, что, тестируя блок A, вы также тестируете блок B, от которого зависит блок A (правило также распространяется и на наследование.) Это также следует рассматривать как реализацию детали, даже если вы чувствуете, что повторяетесь.
Имейте в виду, что однажды написанные тесты вряд ли изменятся, а код, который они тестируют, изменится почти наверняка.
На практике также существует проблема ввода-вывода и внешнего мира, поэтому вы хотите использовать интерфейсы, чтобы при необходимости создавать макеты.
В более динамичных языках это не такая уж большая проблема, здесь вы можете использовать утиную типизацию, множественное наследование и миксины для составления тестовых случаев. Если вы вообще не любите наследование, вы, вероятно, делаете это правильно.