[racket] Testing "impossible" branches in the code
Hi, Matthias!
Thank you for your response, it made me think about my problem from another perspective.
I was trying to protect the application for some future ill-conceived changes that might cause a calling function to fail from illegal return values. Therefore I had "catch-all" branches in conditionals in order to throw exceptions in case of illegal values. The original problem was how to test these branches (in order to have 100% test coverage). I tried introducing some test parameterizations, but that introduced additional unwelcome complexity to the code, although it solved my original problem (kudos to Matthew Butterick for pointing out this possibility!).
However, as I dissected the code it became clear to me that my implementation had been far from clean. One of the problems was that the responsibility for checking return values was not in the function returning the value, but in the calling function.
The main thing seems to be that I need to check return values for type and also for range. After some refactorings I have transferred the responsibility for checking these values so that testing became easier. Also, It starts to look like typed Racket would be an appropriate solution for making the code more robust.
Once again, thanks for your help, it is really nice to know that there is a community of true experts willing to help if one stumbles on the long road to becoming an expert Racketeer :)
Best regards,
-Mikko
Matthias Felleisen <matthias at ccs.neu.edu> kirjoitti 11.4.2014 kello 12.44:
>
> On Apr 3, 2014, at 8:53 PM, Mikko Tiihonen wrote:
>
>> Hi,
>>
>> I've spent some time on the following problem, and would like to ask for your help:
>>
>> I'm writing a critical piece of an application, and would like to ascertain in a "belt and suspenders" kind of way that I get a customized exception if something goes wrong.
>>
>> The approach I have used is based on independent checks (conditionals) that might trigger the exception. The problem is that I have not found an elegant way to test this code, since there should not be such combinations of parameters that could lead to this branch in the conditional. One way would be to extract these pieces of code to auxiliary functions and call these from the tests with those "impossible" parameters that would trigger the exception. However, this would split the code into ugly, detached pieces.
>>
>> Simplified example:
>>
>> (let ((a 2)(b 2))
>> (if (= (+ a b) 4)
>> #t
>> (error "impossible!")))
>>
>> Is there some practical way to access the variable bindings inside a function from tests (similarly to the "set! <var>" pop-up menu in the debugger window) in order to inject faults to trigger these exceptions?
>
> Mikko, I do not understand why you would want to write the code as above. If you specify
> lexical variables and their initial values you don't need to test them and you can prove
> to yourself that (= (+ a b) 4) will always hold. Perhaps you want to construct an example
> that is closer to what you really want.
>
> You could pre-process the code with a debugger-like strategy so that third-party code can
> inspect lexically bound variables. But the same pre-processing would expose lexical variables
> for manipulation, defeating a belt-and-suspender approach.
>
> -- Matthias
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 455 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.racket-lang.org/users/archive/attachments/20140415/4fe18e18/attachment.sig>