Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

check-match for rackunit #171

Closed
wants to merge 1 commit into from

3 participants

@jpolitz

Thread

http://www.mail-archive.com/dev@racket-lang.org/msg07427.html

Files

check.rkt:
Added the actual check-match macro.

test.rkt:
Just a provide statement

check-test.rkt:
7 additional tests for check-match, and a macro to help create tests for it

check.scrbl:
Documentation and examples for check-match

Notes

  1. I tested with

raco test collects/tests/rackunit

It prints out a lot of stuff because there are existing tests hardcoded to fail in there. But, I wrote seven tests and it claims that 127 tests (rather than 120 before) succeed now, so that seems promising.

  1. I don't know how to get the use of @racket[match] in the docs to link over to the actual match page. I'm a Scribble noob.

  2. I'm also a syntaxy-macros noob, it might be possible to get the useful error information through check-match itself in a more appropriate/less crappy way.

@jpolitz jpolitz Add check-match to rackunit
check.rkt:
  Added the actual check-match macro.

test.rkt:
  Just a provide statement

check-test.rkt:
  7 additional tests for check-match, and a macro to help create tests

check.scrbl:
  Documentation and examples for check-match
023d227
@takikawa

To get match to link, all you should need to do is add (require (for-label racket/match)) in the relevant scrbl file.

@takikawa

Merged now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 20, 2012
  1. @jpolitz

    Add check-match to rackunit

    jpolitz authored
    check.rkt:
      Added the actual check-match macro.
    
    test.rkt:
      Just a provide statement
    
    check-test.rkt:
      7 additional tests for check-match, and a macro to help create tests
    
    check.scrbl:
      Documentation and examples for check-match
This page is out of date. Refresh to see the latest.
View
29 collects/rackunit/private/check.rkt
@@ -1,6 +1,7 @@
#lang racket/base
-(require (for-syntax racket/base
+(require racket/match
+ (for-syntax racket/base
"location.rkt")
"base.rkt"
"check-info.rkt"
@@ -31,6 +32,7 @@
check-not-eq?
check-not-eqv?
check-not-equal?
+ check-match
fail)
;; default-check-handler : any -> any
@@ -274,3 +276,28 @@
(define-simple-check (fail)
#f)
+;; NOTE(jpolitz): This match form isn't eager like the others, hence the
+;; define-syntax and the need to carry around location information
+(define-syntax (check-match stx)
+ (syntax-case stx ()
+ [(_ actual expected pred)
+ (quasisyntax
+ (let ([actual-val actual])
+ (with-check-info*
+ (list (make-check-name 'check-match)
+ (make-check-location
+ (list '(unsyntax (syntax-source stx))
+ '(unsyntax (syntax-line stx))
+ '(unsyntax (syntax-column stx))
+ '(unsyntax (syntax-position stx))
+ '(unsyntax (syntax-span stx))))
+ (make-check-expression '#,(syntax->datum stx))
+ (make-check-actual actual-val)
+ (make-check-expected 'expected))
+ (lambda ()
+ (check-true (match actual-val
+ [expected pred]
+ [_ #f]))))))]
+ [(_ actual expected)
+ (syntax/loc stx (check-match actual expected #t))]))
+
View
1  collects/rackunit/private/test.rkt
@@ -104,6 +104,7 @@
check-not-eqv?
check-not-equal?
check-regexp-match
+ check-match
fail)
(define (void-thunk) (void))
View
44 collects/rackunit/scribblings/check.scrbl
@@ -15,7 +15,8 @@ information detailing the failure.
Although checks are implemented as macros, which is
necessary to grab source location, they are conceptually
-functions. This means, for instance, checks always evaluate
+functions (with the exception of @racket[check-match] below).
+This means, for instance, checks always evaluate
their arguments. You can use checks as first class
functions, though you will lose precision in the reported
source locations if you do so.
@@ -180,6 +181,47 @@ The following check fails:
]
}
+@defform*[((check-match v pattern)
+ (check-match v pattern pred))]{
+
+A check that pattern matches on the test value. Matches the test value
+@racket[v] against @racket[pattern] as a @racket[match] clause. If no
+@racket[pred] is provided, then if the match succeeds, the entire check
+succeeds. For example, this use succeeds:
+
+@interaction[#:eval rackunit-eval
+ (check-match (list 1 2 3) (list _ _ 3))
+]
+
+This check fails to match:
+
+@interaction[#:eval rackunit-eval
+ (check-match (list 1 2 3) (list _ _ 4))
+]
+
+If @racket[pred] is provided, it is evaluated with the bindings from the
+match pattern. If it produces @racket[#t], the entire check succeeds,
+otherwise it fails. For example, this use succeeds, binding @racket[x]
+in the predicate:
+
+@interaction[#:eval rackunit-eval
+ (check-match (list 1 (list 3)) (list x (list _)) (odd? x))
+]
+
+This check fails because the @racket[pred] fails:
+
+@interaction[#:eval rackunit-eval
+ (check-match 6 x (odd? x))
+]
+
+This check fails because of a failure to match:
+
+@interaction[#:eval rackunit-eval
+ (check-match (list 1 2) (list x) (odd? x))
+]
+
+}
+
@defproc[(check (op (-> any any any))
(v1 any)
View
40 collects/tests/rackunit/check-test.rkt
@@ -44,6 +44,18 @@
(lambda ()
(apply pred args)))))
+;; NOTE(jpolitz): Not generalizing make-failure-test above because (at
+;; least) util-test expects it to be present, not exported, and a
+;; 2-argument procedure to test require/expose
+(define-syntax make-failure-test/stx
+ (syntax-rules ()
+ [(_ name pred arg ...)
+ (test-case
+ name
+ (check-exn exn:test:check?
+ (lambda ()
+ (pred arg ...))))]))
+
(define-check (good)
#t)
@@ -92,6 +104,28 @@
(define-simple-check (check-symbol? x)
(symbol? x))
(for-each check-symbol? '(a b c))))
+
+ (test-case "Trivial check-match test"
+ (check-match "dirigible" _))
+
+ (test-case "Simple check-match test"
+ (check-match (list 1 2 3) (list _ _ 3)))
+
+ (test-case "check-match with a nested struct"
+ (let ()
+ (struct data (f1 f2 f3))
+ (check-match (data 1 2 (data 1 2 3))
+ (data _ 2 (data _ _ _)))))
+
+ (test-case "Simple check-match test with a binding pred"
+ (check-match 3 x (odd? x)))
+
+ (test-case "check-match with a nested struct and a binding pred"
+ (let ()
+ (struct data (f1 f2 f3))
+ (check-match (data 1 2 (data 1 2 3))
+ (data _ _ (data x y z))
+ (equal? (+ x y z) 6))))
;; Failures
(make-failure-test "check-equal? failure"
@@ -122,6 +156,12 @@
check-not-false #f)
(make-failure-test "check-= failure"
check-= 1.0 2.0 0.0)
+
+ (make-failure-test/stx "check-match failure pred"
+ check-match 5 x (even? x))
+
+ (make-failure-test/stx "check-match failure match"
+ check-match (list 4 5) (list _))
(test-case "check-= allows differences within epsilon"
(check-= 1.0 1.09 1.1))
Something went wrong with that request. Please try again.