My feeling is that this is correct, but with a caveat big enough to drive a truck through: for often very different definitions of "working".
In a language with a strong type system, I can usually get something working (correctly!) fairly quickly with very few (and sometimes no) unit tests at all. In a dynamically-typed language, or one with a weak type system, unit tests quickly become essential to avoid simple errors that end up causing abnormal execution termination.
> without having to wrestle a type system for things you don't care about (e.g. malformed input leading to crashes when parsing machine-generated, standardised inputs, as is the case for three of the test programs
I've found that it's quite often that someone thinks a particular condition can't be triggered, when in fact it can be. Data gets corrupted, through coding errors, bad data entry, and many other things. And when you really do know that something can't ever happen (or have decided that the right thing to do is to terminate in that case anyway), most statically-typed languages have escape hatches, like `Option.unwrap()` in Rust.
> keeping in mind that, in Python, a crash due to a type error produces an orderly, if surprising, program exit rather than, for example, memory corruption
Most statically-typed languages out there will also abort cleanly if you do manage to trigger a type error. Languages like C & C++ are the exception here, not the rule. (Not to mention a type error is much much much less likely in a statically-typed language, so this is kinda a weird comparison.)
In the past year I've seen at least half a dozen posts here on HN making this exact claim. Now I kind of wish I'd saved a few.
and the reference:
[3] J. Spolsky and B. Eckel, “Strong Typing vs. Strong Testing,” in The Best Software Writing I. Apress, pp. 67–77, 2005.
I do agree that development time is an important factor and one that I didn't address simply because that would require a different type experiment. I hope that researchers look into that. I do also think that in addition to development time that overall maintenance time is considered. For example its plausible that dynamic languages are faster to develop, but take longer to make changes due to it being harder to understand, and changes aren't guided by the type system. It is also possible that dynamic languages are both faster and have lower TCO. To be clear I have no idea which is faster, and which has a lower TCO. I'd love to see some scientific evidence on development time and TCO.
In my experience, development time is much less of an important factor than management would like to think it is. I've seen companies burn customer goodwill by releasing a quickly-built, bug-ridden product too early, because they wanted to be first to market or whatever.
And I've also found that the companies that push for faster releases (without reducing scope, of course) end up shipping late anyway. If they'd accepted a later deadline in the first place, fewer coding mistakes would end up getting made along the way. (Stressed-out developers rushing toward an unachievable deadline make more mistakes than those whose time estimates are listened to.)
I know I don't represent all developers, but I do much better when I write in a "slower" language when that language's compiler verifies more things before we get to the point of running the code. The end product is more stable and more correct than what it'd be otherwise, and I don't think I deliver slower in a way that's significant to the business.
"If your unit tests provide good code coverage, don't feel too paranoid about giving up compile-time type checking." (pp 69)
"The only guarantee of correctness [...] is whether it passes all tests which define the correctness of your program." (pp 75)
"To claim that static type checking constraints in C++, Java, or C# will prevent you from writing broken programs is clearly an illusion" (pp 76)
The closest I could find to your quote was at the end: "a dynamically typed language could be much more productive but create programs that are just as robust as those written in statically typed languages." (pp 77) In the context of the article (see previous quote), this is presumably referring to the goal of "defining the correctness of your program", and the article in fact makes the point which I made reference to, which is that incorrect inputs and API usage could well be out of scope for this goal (and perhaps were in the programs you tested). Or, to put it another way, it doesn't make sense to talk about robustness unless you also give a context.
The worst I could say about the article is that it is kind of tautological, because it's easy to no-true-Scotsman the concept of "sufficiently good" unit tests. But to be honest this also happens with type systems.
I realise there's a lot of ... let's say "enthusiasm" in this particular area, but I found the article quite a bit more measured than what was implied by the blog post.
I have seen literally that exact claim, word-for-word, from people who it seems reasonable to characterize as (rather zealous) "proponents of dynamically typed programming languages". It might be a weak man[0][1], but it's definitely not a straw man.
0: https://slatestarcodex.com/2014/11/03/all-in-all-another-bri...
1: https://slatestarcodex.com/2014/05/12/weak-men-are-superweap...
That's an interesting question for any program or app in the move-fast-break-things domain. But perhaps a suboptimal, and potentially inaccurate, one for high-assurance systems that can't break without losing substantial financial value or lives, and/or for which system-wide refactoring may be necessary as the system evolves. Know your domain, choose your tools and methodologies appropriately.