The problem with the chicken and the egg.
If it is not possible to write some decent unit tests due to strong coupling, the best approach may be to work from top to bottom .
If you don't already have Integration, System, and GUI tests, this will be a good reason to create them before you start creating unit tests. Once you have them in place, you can start refactoring the code to create decent unit tests and still be confident that your comprehensive tests will understand your most obvious mistakes.
Please note that, in my personal opinion, these test files should be created in such a way that they should not be changed after you are ready to start creating unit tests and refactoring the code.
A must read on this issue. Effectively work with obsolete Michael Persian code .
Conclusion
The strategy outlined by Ive works for a wide variety of changes, but there are some reservations. Sometimes the only decent inflection point you can find for a set of classes is the boundary of the system. In some applications, the system boundary can be quite wide: it includes GUIs, calls to other external libraries, a database, etc. In such cases, the best way to get the invariant is to start by writing what Steve McConnell calls "smoke tests" against the rest of the system
source share