You're not going to cover all of the correct behavior in any nontrivial software with unit tests unless you plan to spend 99% of your time writing unit tests. Static typing gives a good baseline of correctness.
> Static typing gives a good baseline of correctness.
Not really. Lets say you have an `add(a, b)` function. Static typing can guarantee that the function returns a number, but not that it returns the correct number. So you need unit tests anyway.
A unit test `assert_equal(4, add(2, 2))` actually tells you something about the correctness about the function, and it implicitly also verifies that it returns a number. So static typing does not save you anything.
Static typing does have advantages, for example for documentation and for automated refactoring. But it doesn't replace any unit tests.
Sure, in this trivial example there may not be clear benefit, but with more complicated code, operations on complicated structures, with potential state changes, etc. there are many benefits. Even in your trivial example you don't cover the correctness or correct usage of your function - since it's dynamically typed it could be called with non-integer arguments - what's the expected behaviour in those cases?
Static typing certainly have many benefits, just as it has a number of drawbacks. But I'm not making a general argument about static versus dynamic typing, I'm just rejecting the specific argument that static typing saves you from writing any unit tests.
Nobody made the argument that static typing removes the need for unit tests. It does check for many conditions that would have to be unit tested otherwise, such as calling functions with the wrong types.
I'm saying static type checking does not replace any unit tests, because you wouldn't write tests which only checks for "the wrong types" in the first place. You should check for valid behavior - i.e. is the output correct, not just of the expected type. Types are just an implementation detail. But if the tests verify that the output is correct, then it implicitly follows that the types are correct, so you get type checking for free.
No, as I've pointed out - even in your trivial example you're not testing for all correct behaviour. What's the correct behaviour when the function is called with invalid argument types?
> But if the tests verify that the output is correct, then it implicitly follows that the types are correct, so you get type checking for free.
Your unit test checks the correct behaviour for one out of infinite possible inputs. You don't 'get type checking for free' , what you get is no type checking at all.
This kind of thing is really what contract-based programming is meant for; it shouldn't properly be a test, except that we have to resort to that for the lack of language support for DbC.
I really disagree with this. I use static types as a quick correctness check.
I've added types to large python projects to reduce the complexity of reasoning about the code base, and the typing does not make it run faster (actually, the opposite).
I've got lots of experience in developing with both static and dynamically typed languages, I know the differences and it has very little to do with anything you are talking about.
Dynamically typed languages tend to be simpler and easier to use. This means on the whole they have less bugs than their static typed counter parts.
The real issue with dynamically typed languages is that their performance sucks.
(That and according to this thread people not having a clue on how they are properly used. You can't just use the same development techniques as you use in a statically typed language. It's different.)
> I've got lots of experience in developing with both static and dynamically typed languages
And yet your comments demonstrate the opposite.
> Dynamically typed languages tend to be simpler and easier to use.
Very debatable.
> This means on the whole they have less bugs than their static typed counter parts.
Not at all.
> The real issue with dynamically typed languages is that their performance sucks
Every time you say something like this it just makes it obvious you have no idea what you're talking about. You can write almost completely typeless, highly performant, c and assembly code, while high level languages with advanced type systems are generally not the most performant.
You seen to be confused about interpreted/jit/compiled languages and static/dynamic typing - which are not the same thing.
Not really. Lets say you have an `add(a, b)` function. Static typing can guarantee that the function returns a number, but not that it returns the correct number. So you need unit tests anyway.
A unit test `assert_equal(4, add(2, 2))` actually tells you something about the correctness about the function, and it implicitly also verifies that it returns a number. So static typing does not save you anything.
Static typing does have advantages, for example for documentation and for automated refactoring. But it doesn't replace any unit tests.