There are so many tests you can throw away, so many corner cases you don't need to test anymore. (I'm talking about tests that you can't even write down without getting a compiler error.) Not to mention the assertions within your functions that aren't needed anymore.
And those little type annotations are so much simpler and easier to write down than corresponding tests.
If you really head for 100% testing, not just code coverage, but also all corner cases, you will love the modern static type systems. (However, you should really use an ML type system, because doing the same with Java or C++ is cumbersome and not much fun.)
[1] I did so for my mathematics diploma thesis, starting implementing my formalism in Python, having lots of trouble when refactoring, then moving all code to OCaml and then being able to refactor the code alongside the developing formalism in the thesis.
Meh, test are great in so far as they can help you not break things if you upgrade the framework, or langauge in the future. But other than that I have to agree with Kent Beck's sentiment of "I get paid for code that works, not for tests".
https://istacee.wordpress.com/2013/09/18/kent-beck-i-get-pai...
If I had started out trying to learn Django using TDD as in this tutorial:
http://chimera.labs.oreilly.com/books/1234000000754/index.ht...
I never would have learned Django. I would have given up with the ridiculous slow progress of results and functionality.
Besides, tests cannot find all the bugs a good static type system can find, and vice versa. Tests, even at 100% coverage, are not a complete substitute.
The idea that you could somehow replace the utility of static type checking with a suite of human written tests is laughable. Static typing systems allow you to prove facts about your code which make reasoning about correctness much easier than with dynamic type systems which practically disallow this (unless gradual typing is allowed in your language).