Difference between revisions of "DIP83"

From D Wiki
Jump to: navigation, search
Line 31: Line 31:
 
Failing asserts in unittests currently given no hints about the reason why a test failed. For  
 
Failing asserts in unittests currently given no hints about the reason why a test failed. For  
  
- binary expressions such as '''assert(x == y)''' the developer typically wants to know the values of '''x''' and '''y''' and  
+
* binary expressions such as '''assert(x == y)''' the developer typically wants to know the values of '''x''' and '''y''' and  
- for unary expressions such as '''assert(!x)''' the value of '''x'''.
+
* for unary expressions such as '''assert(!x)''' the value of '''x'''.
  
 
Pretty printing is typically enabled by the developer by changing the D compilation flags ('''DFLAGS''') to calls to rdmd, dub, scons etc upon failure with existing behavior of '''-unittest''' for a specific failing module. This will be more convenient than explicitly adding the prints of the left-hand-side expression '''lhs''' and righ-hand-side expression '''rhs''' of assert expression in the failing unittest.
 
Pretty printing is typically enabled by the developer by changing the D compilation flags ('''DFLAGS''') to calls to rdmd, dub, scons etc upon failure with existing behavior of '''-unittest''' for a specific failing module. This will be more convenient than explicitly adding the prints of the left-hand-side expression '''lhs''' and righ-hand-side expression '''rhs''' of assert expression in the failing unittest.

Revision as of 05:37, 2 October 2015

Title: Configurable Assert Diagnostics
DIP: 83
Version: 1
Status: Draft
Created: 2015-10-01
Last Modified: 2015-10-2
Author: Per Nordlöw
Links:

Abstract

Allow for assert's to do pretty printing of its failing expression when flagged for in call to compiler. Printing is configurable via specific sets of (template) function overloads.

Rationale

Failing asserts in unittests currently given no hints about the reason why a test failed. For

* binary expressions such as assert(x == y) the developer typically wants to know the values of x and y and 
* for unary expressions such as assert(!x) the value of x.

Pretty printing is typically enabled by the developer by changing the D compilation flags (DFLAGS) to calls to rdmd, dub, scons etc upon failure with existing behavior of -unittest for a specific failing module. This will be more convenient than explicitly adding the prints of the left-hand-side expression lhs and righ-hand-side expression rhs of assert expression in the failing unittest.

Description

This DIP proposes to add library-level-configurable diagnostics to failing calls to assert(expr) typically called from within unittest-blocks.

This diagnostics is activated only when DMD is called with a specific command line flag, say -unittest=verbose.

If DMD is called with this flag it will then rewrite assert expression (AssertExpr in dmd source) such as

assert(lhs == rhs)

with

assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)

where

assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)

and similarly for unary expressions.

The default implementation of assertBinOp (preferrably defined somewhere in druntime) would be D code that mimics the current behaviour of assert(expression) by throwing an AssertExpression if cast(bool)expression is false (dont know about the behaviour of nothrow/@nogc discussed above though). The Phobos-developer can then do what he likes with the information he needs in the extra arguments in specific templated overloads of assertBinOp.

This specific behaviour could be extendable by adding (typically templated) overloads of assertBinOp for specific sets of types (concepts).

In this way D would get the extendability we want in testing-frameworks such as std.experimental.testing (https://github.com/D-Programming-Language/phobos/pull/3207) without adding a new assert-overload-set and without sacrifycing default memory usage in DMD/Phobos unittests.

Further, this solution enables the possibility to provide fancy diagnostics behaviour in assertBinOp for failing array/range or aggregate (struct or class) comparisons. This diagnostics could also have different pretty printing backends such as HTML.

For example a failing

assert([1,2,3] == [1,2,4]);

could pretty-print

([1,2,3][2] is 3) != ([1,2,4][2] is 4)

or for aggregates a failing

struct A { int x, y; }
auto a = A(1,2);
auto b = A(1,3);
assert(a == b);

could pretty-print

(a.y is 2) != (b.y is 3)

Parts of the solution list at

https://issues.dlang.org/show_bug.cgi?id=5547#c3

including rewriting/expansion of AssertExpr could probably reused.

Impact

Copyright

This document has been placed in the Public Domain.