More specifically, it's quite certain that types are capable of solidly dispatching some kinds of errors and tests a different kind. In other words, they are orthogonally optimized and combine well.
If, for example, I give one of my Haskell functions the type "f: [a] -> a", I know that it a) does not have side effects, and b) must pick some element from the list to hand me back, i.e. it cannot just construct or cast "something" to an 'a' and give me that. (There is a caveat around explicit "unsafeXXX" usage, but that's mostly beside the point.)
Both of those properties constrain behavior and are impossible to prove using unit testing.
Or, for that matter, how can you tell the function doesn't return a completely new 'a' from hardcoded values?
f: forall a . [a] -> a
which would make it more explicit that the function has to work for any given 'a'.[1] ... which I think I should have actually specified. The function type given does not preclude non-termination in Haskell. (You can specify such things in Idris/Coq/Agda, but the effort of implementing f can be much higher if you have to prove totality.)
Type correctness does not mean your program does the right thing.