| > So the code containing this typo was never tested? The code absolutely was tested. However, (obviously) not every possible path through the code was tested. Given a long-enough timeline, you will NEVER remember to test every little thing. Given sufficient code complexity, it can be next to impossible to actually exercise every code path with hand-written tests. That's one of the troubles with large projects written scripting languages like Ruby... you have to write an assload of tests to replace what you get for free in languages (even "loosely"-typed languages like Erlang) that have pre-runtime type-checking (whether or not it's provided by a compiler). > Conversely, I often work on projects which are neither large nor long-running - for those, a dynamically-typed scripting language works perfectly well. Oh yeah, for small things such languages are A-OK. I 1000% agree with that. The big problem (that you may never encounter because I bet that you're smarter than the average unending parade of Project Managers) is how often small projects are forced into becoming big projects, and then huge projects as time goes on. |
Which means that IME a huge number of tests in my ruby code were doing things that a type checker does automatically: make sure that passing nil makes it return nil, making sure that passing an array does the right thing vs a string, etc etc etc.
I have very vivid memories of working in a large rails code base and having no idea whether my change would work until I actually exercised the code and realized I was completely messing up the contract that some method expected, so I had to slow down and write tests to validate my assumptions.
Fast forward to now, I work in a large Rust code base, and it seems like 99% of the time, if my code compiles, it works flawlessly the first time. So I concentrate on writing integration/functional tests, which give me a lot more bang for my buck than having to write hundreds of little unit tests. (I still write some unit tests, but the need for it is much less… the vast majority of things you’d write tests for in Ruby are things the type and borrow checkers handle for you in Rust.)