www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Are exceptions caught in unittests?

reply Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
When I tried to catch exceptions in my unit test, I found that 
exceptions were not thrown or caught in the unit test blocks. So, 
I cannot use assertThrown at all. Is this a bug or expected 
behavior that I don't know?

Using LDC 1.36.0 on Windows.

https://github.com/aferust/evalex/blob/main/source/evalex.d#L694
Feb 15
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
This should be working.

I don't know what is going on.

All I can suggest is to use a debugger to see if it is indeed throwing 
and then catching.
Feb 15
parent Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Friday, 16 February 2024 at 07:54:01 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 This should be working.

 I don't know what is going on.

 All I can suggest is to use a debugger to see if it is indeed 
 throwing and then catching.
A test code like this works, but unittest doesn't. This is crazy: ```d import std.stdio; import evalex; void main(){ string text = "2 + * 3"; try { auto evaluator = new Eval!double(text); auto result = evaluator.result; writeln(result); }catch (ParserException e){ writeln(e.msg); } } ```
Feb 15
prev sibling parent reply Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Friday, 16 February 2024 at 07:43:24 UTC, Ferhat Kurtulmuş 
wrote:
 When I tried to catch exceptions in my unit test, I found that 
 exceptions were not thrown or caught in the unit test blocks. 
 So, I cannot use assertThrown at all. Is this a bug or expected 
 behavior that I don't know?

 Using LDC 1.36.0 on Windows.

 https://github.com/aferust/evalex/blob/main/source/evalex.d#L694
Even a test code like this does not work: ```d string division(int a, int b) { string result = ""; try { if( b == 0 ) { throw new Exception("Cannot divide by zero!"); } else { result = format("%s",a/b); } } catch (Exception e) { result = e.msg; } return result; } assertThrown({division(50, 0);}); ```
Feb 16
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, February 16, 2024 1:06:26 AM MST Ferhat Kurtulmuş via Digitalmars-
d-learn wrote:
 On Friday, 16 February 2024 at 07:43:24 UTC, Ferhat Kurtulmuş

 wrote:
 When I tried to catch exceptions in my unit test, I found that
 exceptions were not thrown or caught in the unit test blocks.
 So, I cannot use assertThrown at all. Is this a bug or expected
 behavior that I don't know?

 Using LDC 1.36.0 on Windows.

 https://github.com/aferust/evalex/blob/main/source/evalex.d#L694
Even a test code like this does not work: ```d string division(int a, int b) { string result = ""; try { if( b == 0 ) { throw new Exception("Cannot divide by zero!"); } else { result = format("%s",a/b); } } catch (Exception e) { result = e.msg; } return result; } assertThrown({division(50, 0);}); ```
1. assertThrown does not test whether something somewhere in what you called threw an exception. It asserts that it catches an exception. Your example here is catching the exception and returning so the exception never escapes the division function, and there's nothing for assertThrown to catch. 2. You're just passing a lambda to assertThrown without actually calling it. The first argument to assertThrown is lazy, which means that it creates a delegate from what you pass to it. assertThrown then calls that delegate. However, in your example here, that delegate just contains a lambda declaration, so it would basically be the equivalent of having void foo() { {division(50, 0);}; } which would be like doing void foo() { int i; } in the sense that the function just contains a declaration that does nothing. The normal thing to do here would be to not use a lambda at all, since it just contains a function call. assertThrown(division(50, 0)); but in cases where you actually need a lambda, because you're doing something more complex than simply calling a function, you need to call it when passing it. e.g. assertThrown({division(50, 0);}()); That then would be like declaring void foo() { {division(50, 0);}(); } so when assertThrown calls the delegate, the delegate actually calls the lambda. But regardless, the expression that you pass to assertThrown has to actually throw an Exception if you want it to pass, and division doesn't do that, because it catches the Exception internally. If what you want to test is whether something deeper down the stack threw an Exception that got caught, then you're out of luck. That's the sort of thing where you'd need a debugger or some other tool that tracked what the code was doing. assertThrown is just a simple library function that helps you test that an expression throws an exception - generally with the idea that it allows you to test that a piece of code throws an exception when it's suposed to (e.g. because you gave it bad input). void assertThrown(T : Throwable = Exception, E) (lazy E expression, string msg = null, string file = __FILE__, size_t line = __LINE__) { import core.exception : AssertError; try expression(); catch (T) return; static if (!is(immutable E == immutable noreturn)) throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown" ~ (msg.length == 0 ? "." : ": ") ~ msg, file, line); } - Jonathan M Davis
Feb 16
parent Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Friday, 16 February 2024 at 08:48:08 UTC, Jonathan M Davis 
wrote:
 On Friday, February 16, 2024 1:06:26 AM MST Ferhat Kurtulmuş 
 via Digitalmars- d-learn wrote:
 [...]
1. assertThrown does not test whether something somewhere in what you called threw an exception. It asserts that it catches an exception. Your example here is catching the exception and returning so the exception never escapes the division function, and there's nothing for assertThrown to catch. [...]
Hi Jonathan, thank you for clearly explaining in detail how it works. I added trailing parenthesis to the lambda inside assertThrown, which worked as expected. Ferhat
Feb 16