Unit tests are supposed to expose all the errors which you might only find at run-time, but it can also be used to check for errors traditionally checked at compile-time, like type errors. This challenges the usual argument which states that statically-typed languages are better because they catch your errors 'earlier', since tests are usually ran right after the compilation step.
In other words, if your development cycle is "compile: compile fails, fix, compile again: succeeds, test: test fails, fix, compile again...", then the compiler's error messages are not really better than the unit test's errors. (provided that the unit test is designed to catch the type errors)
I think so, yes. UnitTests are what convinced me to switch from Java to Smalltalk. Before reading about XP, I thought that Smalltalk was a neat concept, but I loved the way the Java compiler caught my mistakes for me. Now that the tests have taken over that role, I'm finding that dynamic typing isn't a problem at all. --AdamSpitz
Furthermore, UnitTests allow you to define completely custom rules, whereas compile-time rules can only be extended up to a point.
For instance, as MisterRonJeffries demonstrated:
Though your compiler will catch:
someObj.someMetohd(); // typo: should be someMethodit cannot catch:
a = 377; // typo: should be 3.What can catch both, though, are the UnitTests and your pair partner.
We should of course also ask DoesStaticTypingMakeUnitTestingLessUseful?? I've a strong hunch that the answer to both questions is yes, but that unit testing is better. Someone suggested wrapping all ints in their own type according to usage. In general I've found that that just makes the code harder to read for no significant win, since 90% of the time you don't care what kind of int you have. Imagine coding it first with ints, and getting it working with unit tests. Would you then go back and add individual static types for each kind of usage? I don't think so. The other way around, if you'd coded it all religiously with an individual type wrapping each different kind of usage for each int, would you still want unit tests? Absolutely.
The question is: can you ever prove anything about the completeness of unit testing? Code coverage is not enough, because the same function call might fail or succeed on different input (code coverage across all libraries would probably cover this, as long as there is an underlying selection statement, but it would not cover polymorphic functions I think). With DependentTypes you can instead specify anything in the type system, but it becomes inconvenient to use. --PaoloGiarrusso
See also: DesignByContractAssertionsVsUnitTestsVsTypes, ExtremeProgrammingWithTypes, TheoryOfLanguageEnvironmentSuckage, UnificationOfStaticTypesAndUnitTests