expected / actual interaction with pretty-printing
rfindler opened this issue · comments
Sometimes, rackunit inserts newlines into expected and actual results when using check-equal?
(which is great!) but the indentation has issues. For example, this program:
#lang racket
(require rackunit)
(check-equal?
(make-list 10 'xfdjkalf)
(make-list 11 'xfdjkalf))
produces this output:
--------------------
. FAILURE
name: check-equal?
location: unsaved-editor:3:0
actual: '(xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf)
expected: '(xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf)
--------------------
>
I think that the printer should either detect that there are newlines in the printed result and, in tht case, lead with a newline, or it should set various printing parameters so that everything is indented past the "expected". Probably the former is best! But maybe a hybrid, where you put that first newline in, but then indent everything by one space or something so that the words "expected" and "actual" stand out.
There are two ways we could do this:
- Make everything pretty-printed, and use a pretty version of the
format
function instead offormat
incheck-info->string
. - Try set the
pretty-print-print-line
parameter to print the extra padding after the newline.
Strategy (1) can be accomplished with a function like this:
(require (rename-in racket/pretty [pretty-format pretty-string]))
;; exactly like format, but pretty (*not* the same as pretty-format from racket/pretty)
(define (pretty-format fmt . vs)
(pretty-string (formatted fmt vs)))
(struct formatted (fmt vs)
#:methods gen:custom-write
[(define (write-proc this out mode)
(apply fprintf out (formatted-fmt this) (formatted-vs this)))])
;; using it produces:
actual: '(xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf)
I also attempted strategy (2) with the function below, but the indentation wasn't right for any of the sub-expressions:
(define (call-with-pretty-padding pad thunk)
;; the old and new value of the parameter
(define old-newline (pretty-print-print-line))
(define (new-newline line-num out prev-len dest-cols)
(+ (old-newline line-num out prev-len dest-cols)
(if (zero? line-num)
0
(write-string pad out))))
(parameterize ([pretty-print-print-line new-newline])
(thunk)))
;; using it produces:
actual: '(xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf
xfdjkalf)
I think that you could monitor the output at the port level to see if you see a newline and, if you do, restart the printing (but this time putting a newline after the word "expected:"), perhaps with a modest indentation (one or two characters) on each line.
As for the indenting-not-quite-right issue, I can't recall exactly how that goes either, but I think that I figured it out once before and used it in redex here:
https://github.com/racket/redex/blob/master/redex-lib/redex/private/reduction-semantics.rkt#L3140
maybe that helps?
Or, there's the string-indent
function, already there for nested-info values. That seems simpler than either strategy.
I don't know that function, but shame on me for going directly to the efficient solution before a need for it exists. :)
Thanks!