|
183 | 183 | "(ns clojure.test.mode |
184 | 184 | (:use [clojure.test :only [file-position *testing-vars* *test-out* |
185 | 185 | join-fixtures *report-counters* do-report |
186 | | - test-var *initial-report-counters*]])) |
| 186 | + test-var *initial-report-counters*]] |
| 187 | + [clojure.pprint :only [pprint]])) |
187 | 188 |
|
188 | 189 | (def #^{:dynamic true} *clojure-test-mode-out* nil) |
| 190 | + (def fail-events #{:fail :error}) |
189 | 191 | (defn report [event] |
190 | 192 | (if-let [current-test (last clojure.test/*testing-vars*)] |
191 | 193 | (alter-meta! current-test |
192 | 194 | assoc :status (conj (:status (meta current-test)) |
193 | | - [(:type event) (:message event) |
194 | | - (str (:expected event)) |
195 | | - (str (:actual event)) |
| 195 | + [(:type event) |
| 196 | + (:message event) |
| 197 | + (when (fail-events (:type event)) |
| 198 | + (str (:expected event))) |
| 199 | + (when (fail-events (:type event)) |
| 200 | + (str (:actual event))) |
| 201 | + (case (:type event) |
| 202 | + :fail (with-out-str (pprint (:actual event))) |
| 203 | + :error (with-out-str |
| 204 | + (clojure.stacktrace/print-cause-trace |
| 205 | + (:actual event))) |
| 206 | + nil) |
196 | 207 | (if (and (= (:major *clojure-version*) 1) |
197 | 208 | (< (:minor *clojure-version*) 2)) |
198 | 209 | ((file-position 2) 1) |
|
245 | 256 | (dolist (is-result (rest result)) |
246 | 257 | (unless (member (aref is-result 0) clojure-test-ignore-results) |
247 | 258 | (incf clojure-test-count) |
248 | | - (destructuring-bind (event msg expected actual line) (coerce is-result 'list) |
| 259 | + (destructuring-bind (event msg expected actual pp-actual line) |
| 260 | + (coerce is-result 'list) |
249 | 261 | (if (equal :fail event) |
250 | 262 | (progn (incf clojure-test-failure-count) |
251 | 263 | (clojure-test-highlight-problem |
252 | | - line event (format "Expected %s, got %s" expected actual))) |
| 264 | + line event (format "Expected %s, got %s" expected actual) |
| 265 | + pp-actual)) |
253 | 266 | (when (equal :error event) |
254 | 267 | (incf clojure-test-error-count) |
255 | | - (clojure-test-highlight-problem line event actual)))))) |
| 268 | + (clojure-test-highlight-problem |
| 269 | + line event actual pp-actual)))))) |
256 | 270 | (clojure-test-echo-results)) |
257 | 271 |
|
258 | 272 | (defun clojure-test-echo-results () |
|
266 | 280 | ((not (= clojure-test-failure-count 0)) 'clojure-test-failure-face) |
267 | 281 | (t 'clojure-test-success-face))))) |
268 | 282 |
|
269 | | -(defun clojure-test-highlight-problem (line event message) |
| 283 | +(defun clojure-test-highlight-problem (line event message pp-actual) |
270 | 284 | (save-excursion |
271 | 285 | (goto-char (point-min)) |
272 | 286 | (forward-line (1- line)) |
|
276 | 290 | (overlay-put overlay 'face (if (equal event :fail) |
277 | 291 | 'clojure-test-failure-face |
278 | 292 | 'clojure-test-error-face)) |
279 | | - (overlay-put overlay 'message message))))) |
| 293 | + (overlay-put overlay 'message message) |
| 294 | + (overlay-put overlay 'actual pp-actual))))) |
280 | 295 |
|
281 | 296 | ;; Problem navigation |
282 | 297 | (defun clojure-test-find-next-problem (here) |
@@ -372,6 +387,68 @@ Clojure src file for the given test namespace.") |
372 | 387 | (message (replace-regexp-in-string "%" "%%" |
373 | 388 | (overlay-get overlay 'message)))))) |
374 | 389 |
|
| 390 | +(defun clojure-test-pprint-result () |
| 391 | + "Show the result of the test under point." |
| 392 | + (interactive) |
| 393 | + (let ((overlay (find-if (lambda (o) (overlay-get o 'message)) |
| 394 | + (overlays-at (point))))) |
| 395 | + (when overlay |
| 396 | + (with-current-buffer (generate-new-buffer " *test-output*") |
| 397 | + (buffer-disable-undo) |
| 398 | + (insert (overlay-get overlay 'actual)) |
| 399 | + (switch-to-buffer-other-window (current-buffer)))))) |
| 400 | + |
| 401 | +;;; ediff results |
| 402 | +(defvar clojure-test-ediff-buffers nil) |
| 403 | + |
| 404 | +(defun clojure-test-ediff-cleanup () |
| 405 | + "A function for ediff-cleanup-hook, to cleanup the temporary ediff buffers" |
| 406 | + (mapc (lambda (b) (when (get-buffer b) (kill-buffer b))) |
| 407 | + clojure-test-ediff-buffers)) |
| 408 | + |
| 409 | +(defun clojure-test-ediff-result () |
| 410 | + "Show the result of the test under point as an ediff" |
| 411 | + (interactive) |
| 412 | + (let ((overlay (find-if (lambda (o) (overlay-get o 'message)) |
| 413 | + (overlays-at (point))))) |
| 414 | + (if overlay |
| 415 | + (let* ((m (overlay-get overlay 'actual))) |
| 416 | + (let ((tmp-buffer (generate-new-buffer " *clojure-test-mode-tmp*")) |
| 417 | + (exp-buffer (generate-new-buffer " *expected*")) |
| 418 | + (act-buffer (generate-new-buffer " *actual*"))) |
| 419 | + (with-current-buffer tmp-buffer |
| 420 | + (insert m) |
| 421 | + (clojure-mode) |
| 422 | + (goto-char (point-min)) |
| 423 | + (forward-char) ; skip a paren |
| 424 | + (paredit-splice-sexp) ; splice |
| 425 | + (lexical-let ((p (point))) ; delete "not" |
| 426 | + (forward-sexp) |
| 427 | + (delete-region p (point))) |
| 428 | + (lexical-let ((p (point))) ; splice next sexp |
| 429 | + (forward-sexp) |
| 430 | + (backward-sexp) |
| 431 | + (forward-char) |
| 432 | + (paredit-splice-sexp)) |
| 433 | + (lexical-let ((p (point))) ; delete operator |
| 434 | + (forward-sexp) |
| 435 | + (delete-region p (point))) |
| 436 | + (lexical-let ((p (point))) ; copy first expr |
| 437 | + (forward-sexp) |
| 438 | + (lexical-let ((p2 (point))) |
| 439 | + (with-current-buffer exp-buffer |
| 440 | + (insert-buffer-substring-as-yank tmp-buffer (+ 1 p) p2)))) |
| 441 | + (lexical-let ((p (point))) ; copy next expr |
| 442 | + (forward-sexp) |
| 443 | + (lexical-let ((p2 (point))) |
| 444 | + (with-current-buffer act-buffer |
| 445 | + (insert-buffer-substring-as-yank tmp-buffer (+ 1 p) p2))))) |
| 446 | + (kill-buffer tmp-buffer) |
| 447 | + (setq clojure-test-ediff-buffers |
| 448 | + (list (buffer-name exp-buffer) (buffer-name act-buffer))) |
| 449 | + (ediff-buffers |
| 450 | + (buffer-name exp-buffer) (buffer-name act-buffer))))))) |
| 451 | + |
375 | 452 | (defun clojure-test-load-current-buffer () |
376 | 453 | (let ((command (format "(clojure.core/load-file \"%s\")\n(in-ns '%s)" |
377 | 454 | (buffer-file-name) |
@@ -418,7 +495,8 @@ Clojure src file for the given test namespace.") |
418 | 495 | (define-key map (kbd "C-c C-,") 'clojure-test-run-tests) |
419 | 496 | (define-key map (kbd "C-c ,") 'clojure-test-run-tests) |
420 | 497 | (define-key map (kbd "C-c M-,") 'clojure-test-run-test) |
421 | | - (define-key map (kbd "C-c C-'") 'clojure-test-show-result) |
| 498 | + (define-key map (kbd "C-c C-'") 'clojure-test-ediff-result) |
| 499 | + (define-key map (kbd "C-c M-'") 'clojure-test-pprint-result) |
422 | 500 | (define-key map (kbd "C-c '") 'clojure-test-show-result) |
423 | 501 | (define-key map (kbd "C-c k") 'clojure-test-clear) |
424 | 502 | (define-key map (kbd "C-c C-t") 'clojure-jump-between-tests-and-code) |
|
0 commit comments