digitalmars.D.learn - Custom exceptions violate unittest
- Brother Bill (99/100) Nov 30 In book "Programming in D", on page 217.
- Paul Backus (3/6) Nov 30 I just tried building and running your example program with both
- Steven Schveighoffer (15/62) Nov 30 It may throw other exceptions. But those exceptions are *not
In book "Programming in D", on page 217.
My concern is why the assertThrown!UnequalLengths unit test does
not catch the custom Exception of UnequalLengths.
Is this a bug or a feature?
source/app.d
```
import std.stdio : writeln;
import std.exception : assertThrown, assertNotThrown;
void main()
{
}
class UnequalLengths : Exception
{
this(string msg, string file = __FILE__, size_t line = __LINE__)
{
super(msg, file, line);
writeln("Unequal lengths");
}
}
class RangeError : Exception
{
this(string msg, string file = __FILE__, size_t line = __LINE__)
{
super(msg, file, line);
writeln("Unequal lengths");
}
}
void average(int[] a, int[] b)
{
throw new UnequalLengths("Unequal lengths");
}
unittest
{
// Must throw UnequalLengths for uneven slices
assertThrown!UnequalLengths(average([1], [1, 2]));
// Must not throw RangeError for empty slices (it may throw
other types of exceptions)
assertNotThrown!RangeError(average([], []));
}
```
I would expect that both unit tests would pass and that the unit
test not crash, which it does.
Console output:
```
dub test
No source files found in configuration 'library'.
Falling back to default configuration for test runner.
Starting Performing "unittest" build using
C:\D\dmd2\windows\bin64\dmd.exe for x86_64.
Building c42_6b_testing_for_exceptions_custom_exceptions
~master: building configuration [application]
Linking c42_6b_testing_for_exceptions_custom_exceptions
Running c42_6b_testing_for_exceptions_custom_exceptions.exe
Unequal lengths
Unequal lengths
app.UnequalLengths source\app.d(29): Unequal lengths
----------------
0x00007FF74E1E2967 in d_throwc
0x00007FF74E1DF034 in app.average at
C:\temp\c42_p217_6b_testing_for_exceptions_custom_exceptions\source\app.d(29)
0x00007FF74E1DF23D in app.__unittest_L32_C1.__dgliteral_L38_C36
at
C:\temp\c42_p217_6b_testing_for_exceptions_custom_exceptions\source\app.d(38)
0x00007FF74E1E16FB in
std.exception.assertNotThrown!(app.RangeError,
void).assertNotThrown at
C:\D\dmd2\windows\bin64\..\..\src\phobos\std\exception.d(149)
0x00007FF74E1DF107 in app.__unittest_L32_C1 at
C:\temp\c42_p217_6b_testing_for_exceptions_custom_exceptions\source\app.d(38)
0x00007FF74E1E19BD in void app.__modtest()
0x00007FF74E1F072E in int
core.runtime.runModuleUnitTests().__foreachbody_L603_C5(object.ModuleInfo*)
0x00007FF74E1E8827 in int object.ModuleInfo.opApply(scope int
delegate(object.ModuleInfo*)).__lambda_L2467_C13(immutable(object.ModuleInfo*))
0x00007FF74E1EDBC4 in int rt.minfo.moduleinfos_apply(scope int
delegate(immutable(object.ModuleInfo*))).__foreachbody_L582_C5(ref
rt.sections_win64.SectionGroup)
0x00007FF74E1EE39C in int
rt.sections_win64.SectionGroup.opApply(scope int delegate(ref
rt.sections_win64.SectionGroup))
0x00007FF74E1EDB2B in int rt.minfo.moduleinfos_apply(scope int
delegate(immutable(object.ModuleInfo*)))
0x00007FF74E1E87E7 in int object.ModuleInfo.opApply(scope int
delegate(object.ModuleInfo*))
0x00007FF74E1F0550 in runModuleUnitTests
0x00007FF74E1EA975 in void rt.dmain2._d_run_main2(char[][],
ulong, extern (C) int function(char[][])*).runAll()
0x00007FF74E1EA8CF in void rt.dmain2._d_run_main2(char[][],
ulong, extern (C) int function(char[][])*).tryExec(scope void
delegate())
0x00007FF74E1EA69A in d_run_main2
0x00007FF74E1E32C9 in d_run_main
0x00007FF74E1DF282 in app._d_cmain!().main at
C:\D\dmd2\windows\bin64\..\..\src\druntime\import\core\internal\entrypoint.d(29)
0x00007FF74E26652C in __scrt_common_main_seh at
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
0x00007FFA38EFE8D7 in BaseThreadInitThunk
0x00007FFA3A78C53C in RtlUserThreadStart
1/1 modules FAILED unittests
Error Program exited with code 1
```
Nov 30
On Sunday, 30 November 2025 at 14:00:12 UTC, Brother Bill wrote:In book "Programming in D", on page 217. My concern is why the assertThrown!UnequalLengths unit test does not catch the custom Exception of UnequalLengths.I just tried building and running your example program with both DMD 2.110.0 and LDC 1.40.1, and it worked correctly both times.
Nov 30
On Sunday, 30 November 2025 at 14:00:12 UTC, Brother Bill wrote:In book "Programming in D", on page 217. My concern is why the assertThrown!UnequalLengths unit test does not catch the custom Exception of UnequalLengths. Is this a bug or a feature? source/app.d ```d import std.stdio : writeln; import std.exception : assertThrown, assertNotThrown; void main() { } class UnequalLengths : Exception { this(string msg, string file = __FILE__, size_t line = __LINE__) { super(msg, file, line); writeln("Unequal lengths"); } } class RangeError : Exception { this(string msg, string file = __FILE__, size_t line = __LINE__) { super(msg, file, line); writeln("Unequal lengths"); } } void average(int[] a, int[] b) { throw new UnequalLengths("Unequal lengths"); } unittest { // Must throw UnequalLengths for uneven slices assertThrown!UnequalLengths(average([1], [1, 2])); // Must not throw RangeError for empty slices (it may throw other types of exceptions) assertNotThrown!RangeError(average([], [])); } ```It may throw other exceptions. But those exceptions are *not caught* by `assertNotThrown`. From the docs:Asserts that the given expression does not throw the given type of Throwable. If a Throwable of the given type is thrown, it is caught and does not escape assertNotThrown. Rather, an AssertError is thrown. **However, any other Throwables will escape.**I can imagine a scenario where you have an exception that is a derivative of another exception. Let's say I wanted to assert that an `Exception` is thrown, but that it is not an `UnequalLengths` exception. Then you would do: ```d assertThrown!Exception(assertNotThrown!UnequalLengths(...)); ``` But other than that, specifying that a specific exception is not thrown seems to be of very limited value. FWIW, I'd change the message in those two writelns so you can tell which one is written. -Steve
Nov 30









Paul Backus <snarwin gmail.com> 