@andre has joined the channel
Does anyone know the parameter that sets the limit on width for printed messages (like from #R in the debug module)?
Probably error-print-width
: http://docs.racket-lang.org/reference/exns.html#%28def._%28%28quote._~23~25kernel%29._error-print-width%29%29
Thanks! Now trying it…
Oops, that’ll have to wait. We’re now in the middle of a change that’s causing lots of unit tests to fire.
But that leads to another question: How do you tell which unit test failed? I’m seeing a big list of errors but no line numbers.
@bkovitz this has line numbers for me:
#lang racket
(require rackunit)
(check-equal? 1 2)
I think the line numbers are missing when something throws an exception. Here’s what I see: ERROR
set-add: contract violation: expected: set? given: ’#hash() argument position: 1st other arguments…: x: (set ’(b in) ’(a out))
What would really help is a stack trace. How can you get ‘raco test’ to print stack traces for errors?
it prints one for me when I try it
I found the line that fails by grepping the source code for ‘set-add’. But I’d still like to know an efficient way to do this.
Are you running the file in DrRacket?
@samth Hmm, over here it’s printing one stack trace at the very end, after 13 errors.
No, I’m running ‘raco test’.
@bkovitz can you say more about what kind of test you’re writing? That isn’t the behavior I get for tests with errors like this: #lang racket
(module+ test
(require rackunit)
(check-equal? 1 (set-add 1 2))
(check-equal? 1 (- 'a 'b)))
Sure, it’
It’s in a large program, but let’s see if I can find a useful tiny excerpt.
Here’s the test: (test-case ":edge" (let ([g (make-graph ’(:edge ((:node letter a) out) ((:node letter b) in)))]) (check-equal? (all-edges g) (set (set ’(a out) ’(b in)))))) (How do you get the ‘code’ font?)
The failure happens here, because we’re in the middle of changing edges from a set to a hash:
(define (add-edge g edge) ; edge is ’((node1 port-label1) (node2 port-label2)) (match-define `(,port1 ,port2) edge) (define edges (graph-edges g)) (let* ([p->nps (graph-ht-port->neighboring-ports g)] [p->nps (hash-update p->nps port1 (λ (st) (set-add st port2)) (set))] [p->nps (hash-update p->nps port2 (λ (st) (set-add st port1)) (set))]) (struct-copy graph g [edges (set-add edges (set port1 port2))] [ht-port->neighboring-ports p->nps] )))
(Third line from the bottom.)
Well, this might be fruitful: I just tried running the program inside DrRacket, and it shows me only the one error message, not the 13 messages for the 13 failing unit tests. But no line number.
If I click the stack-trace button, though, it does show the line that failed and the rest of the stack. (This usually hasn’t happened when I’ve tried that button with other errors.)
Ok, great
ah, the issue seems to be something weird that happens when the “pre” code in a test case fails with an error
Ah, I see that the first failure occurred outside of a unit test, in some top-level code that created a graph.
@bkovitz I saw an error message without the context too, but rackunit
printed the test name, :edge
So probably DrRacket never ran any of the unit tests. ‘raco test’ went ahead and ran them (which is fine).
*but
DrRacket by default will run the test
submodule. This is configured from Language > Choose Language > Submodules to Run
It looks like DrRacket gave up before running the test submodule. That makes sense: the parent module had an error right away.
@samth That’s definitely it: the error occurred in the call to make-graph, before it could get to check-equal?
Looks like rackunit
does suppress the context https://github.com/racket/rackunit/blob/master/rackunit-lib/rackunit/private/format.rkt#L138
@shu—hung Ah, that explains it. Is there an easy way to change that?
can’t think of an easy way for that :disappointed:
perhaps temporary avoid the use of test-case
cc @jeapostrophe
@jeapostrophe has joined the channel
Oh… So test-case does it? Yeah, I can lose those for now, maybe by redefining test-case as begin. All I really need is the line number.
Hmm, still not working even if using check-equal?
directly. The context is not very helpful
Say, is there a way to get ‘raco test’ to print the line numbers in the stack trace? (DrRacket shows the stack trace when I click the xxx button.)
All I saw was (submod "<FILE>.rkt" test): [running body]
DrRacket has errortrace
turned on by default, which will instrument the program to obtain more precise backtrace information
@shu—hung Sorry, I pulled the test case from a moderately large program. Is there a way I could make the context more helpful?
Ah, I was wondering if I should incorporate errortrace
into the code. I’ll try that…
I don’t know either. Sometimes what I do is to run the test submodule manually like: $ racket -lle racket/init errortrace '(require (submod "<FILE>.rkt" test))'
this is definitely inconvenient though
That worked! Thanks!
I can probably make it reasonably convenient via ‘make’.
@bkovitz Not to overwhelm you or digress, but: Using check-equal?
to compare to a set or hash literal is fragile. The order of items isn’t guaranteed. It actually changed a couple versions ago, of Racket. (I know because it broke a few tests I had.)
I only mention this in case you’re going to be reviewing/changing all these tests, anyway. You might want to define something like check-hash-equal?
that does an order-independent compare.
Actually that would be a handy thing to add to rackunit
.
It would also be totally reasonable to say, to heck with that you have enough on your plate already, and you’ll deal with that someday if/ever it breaks. But just FYI ¯_(ツ)_/¯
@shu—hung I just tried #lang debug at-exp errortrace racket
and got the above message in DrRacket.
@greg Thanks! This is just the kind of pointer I need.
Well one problem at a time. :slightly_smiling_face:
ah
@bkovitz thanks, I think that’s a different thing to fix
@greg I thought I set up the test so that the order of elements wouldn’t make a difference. Will what I posted above not do it?
@shu—hung The #lang errortrace racket
trick does work to make raco test
print out full stack traces, though. :slightly_smiling_face:
yay!
re your first question, on Slack you can use triple backticks — markdown “fenced code block” style — to insert blocks of code your code here
derp
@greg Thanks. I’ll try the triple backticks on the next occasion. :slightly_smiling_face:
re your other question, I saw (check-equal? (all-edges g) (set (set '(a out) '(b in)))
and just didn’t see where all-edges
sorts it some guaranteed way but maybe I’m mistaken
@greg all-edges
returns a set, so I think it’s kosher after all. But now I know to watch out in tests where hashe tables are involved.
@bkovitz If you do write your own check-hash-equal?
macro, then — speaking of good srcloc for test failures — maybe see this little blog post I wrote awhile back https://www.greghendershott.com/2014/01/using-syntax-loc-and-unit-test-macros.html
@greg Thanks. I’ll check it out. We’re updating code and unit tests right now, so the occasion may come soon.
BTW, regarding stack traces, I’ve noticed in DrRacket that many stack traces point to a big block containing the line that threw the error rather than the exact line or (better yet) function call. I don’t have an example handy right now, but the big block is usually a let
or a function definition. Is there any way to force the instrumentation to track the stack at a finer grain?
We just breezed through the rest of the places in the code that needed to be changed, thanks to the improved stack traces from #lang errortrace. Thanks for the help, folks!
using errortrace is that mechanism
@samth Ah, good. Indeed the raco test
stack traces since adding #lang errortrace
have been showing each function call specifically.