Yes, and I've said that I agree with that in general. I know that this isn't hypothetical; that's exactly why I keep saying that throwing an error doesn't help you find this bug early at all.
Even the silent weirdness can be caught by the most basic of tests checking output against input, but only if your function works the same way on every invocation.
Whether making a giant fuss (as you'd prefer) or making the best of it (as it actually does), the setMonth
method always works the same way. My code always works the same way. The setDate
suggestion makes the code always work the same way.
Code that always works the same way is easy to test.
If the day of the month is constant and incompatible with setMonth
, whether there's a thrown error or just an unwanted return value, a simple test will reveal that on every test run. If the day of the month is constant and always compatible with setMonth
, the test will pass appropriately on every test run.
The bug in the code you originally presented comes from working differently over time. That's why, most days, tests won't identify the problem, even with a fussy, noisy API. Most testing days, the date will just happen to be compatible, and even the fussiest, noisiest API will carry on without any mention of the problem.
The reason the original code works differently over time has nothing to do with the silent, unexpected behaviour of setMonth
. It's entirely down to calling Date()
without arguments, the entire point of which is to give different values over time. That call effectively introduces state that is not controlled by the function. And not bringing it under control is the real source of the bug.
Yes, absolutely, JavaScript sucks. Make F# the only supported web scripting language! But JavaScript's suckiness is not the cause of this particular bug. JavaScript's suckiness is not the reason this bug is hard to catch. The real problem lies in code that functions differently over time when it should (and could easily) be consistent. That's what actually makes it hard to test.
Plenty of other languages and API design choices still allow code that functions that work differently over time, which is why, as justifiable as the complaints are in general, those factors are irrelevant for this particular bug. Write code that always works the same way and the problem goes away. That's the real core of the issue.
Obviously, that's easier said than done, and it's irritating that neither loud errors nor most testing will help you in this regard, but that's the way it is.
But that isn't what it does. From the original post:
That is a function which is meant to take a number (presumably 1 to 12) and return a localized name for it. This is essentially an array lookup and should return the same output for a given input (and locale) every time it is called. If the intent is to return a value relative to the current date, it is even more wrong, since it should gather the month from the current date, not the function paramenter. This claim of intent, not present in the original post, is an example of you changing your story over time.
No, it wouldn't. As I have said before, testing for unexpected return values is just as effective as testing for errors, that is, not very with the function originally presented under sensible assumptions. If the function actually did look like the intent you claim, the tests would be different, necessarily replacing
Date
for consistent runs, but would be equally likely to catch the problem whether failing on value or error. And if you are eschewing testing and relying on runtime crashes, you have bigger problems.Given that I have agreed and commiserated, and neither of us can change JavaScript, there is nothing to be gained from pursuing this complaint. In contrast, what I have tried to say, if followed, would give you an approach that leads to more reliable code, even in the face of undesirable APIs.
I had thought that worth pursuing, and had thought you worth investing my considerable time. Alas, I can only lead you to the water...