None of those things make code untestable. They may make it harder to find edge case bugs but, provided you have fully specified the success criteria for testing (and test-driven development eases this), all you have to do is pass the criteria.
TDD can apply to the behaviour of specific parts as well as the project as a whole, so you can easily test very small components. But, it's meant to test the results, not the means by which those results were obtained.
Provided the tests are passed, you have met the requirements. If there are bugs following that, this is an issue with the tests, not the code being tested (in which case the tests should be modified to catch the previously unforeseen problem).
You should not care (in terms of delivery of functionality) whether there's a while statement in one of your constructors. You should ask yourself what business requirement mandates that? I strongly doubt your client will deliver a list of requirements including "inheritance limited to 4 levels". They may well list "bug-free" as a requirement but you'll have to negotiate them down on that one :-).