added test-* shortcuts to docs, other edits

This commit is contained in:
Ryan Culpepper 2010-09-01 09:54:38 -06:00
parent 962ceb6b63
commit c5e6580f02
4 changed files with 145 additions and 61 deletions

View File

@ -26,10 +26,10 @@ can create your own checks using @racket[define-check].
[(check-equal? (v1 any) (v2 any) (message string? "")) void?] [(check-equal? (v1 any) (v2 any) (message string? "")) void?]
[(check-not-equal? (v1 any) (v2 any) (message string? "")) void?])]{ [(check-not-equal? (v1 any) (v2 any) (message string? "")) void?])]{
Checks that @racket[v1] is (not) @racket[eq?], Checks that @racket[v1] is equal (or not equal) to @racket[v2], using
@racket[eqv?], or @racket[equal?] to @racket[v2]. The @racket[eq?], @racket[eqv?], or @racket[equal?], respectively. The
optional @racket[message] is included in the output if the optional @racket[message] is included in the output if the check
check fails.} fails.
For example, the following checks all fail: For example, the following checks all fail:
@ -41,39 +41,52 @@ For example, the following checks all fail:
(check-equal? 1 1.0 "not equal?") (check-equal? 1 1.0 "not equal?")
(check-not-equal? (list 1) (list 1) "equal?") (check-not-equal? (list 1) (list 1) "equal?")
] ]
}
@defproc[(check-pred (pred (-> any any)) (v any) (message string? "")) @defproc[(check-pred (pred (-> any any)) (v any) (message string? ""))
void?]{Checks that @racket[pred] returns a value that is not @racket[#f] when applied to @racket[v]. The optional @racket[message] is included in the output if the check fails. The value returned by a successful check is the value returned by @racket[pred].} void?]{
Here's an example that passes and an example that fails: Checks that @racket[pred] returns a value that is not @racket[#f] when
applied to @racket[v]. The optional @racket[message] is included in
the output if the check fails. The value returned by a successful
check is the value returned by @racket[pred].
For example, the following check passes:
@racketblock[ @racketblock[
(check-pred string? "I work") (check-pred string? "I work")
]
The following check fails:
@racketblock[
(check-pred number? "I fail") (check-pred number? "I fail")
] ]
}
@defproc[(check-= (v1 any) (v2 any) (epsilon number?) (message string? ""))
@defproc[(check-= (v1 any) (v2 any) (epsilon number?) (message string? "")) void?]{ void?]{
Checks that @racket[v1] and @racket[v2] are within Checks that @racket[v1] and @racket[v2] are within
@racket[epsilon] of one another. The optional @racket[epsilon] of one another. The optional
@racket[message] is included in the output if the check @racket[message] is included in the output if the check
fails.} fails.
Here's an example that passes and an example that fails: For example, the following check passes:
@racketblock[ @racketblock[
(check-= 1.0 1.01 0.01 "I work") (check-= 1.0 1.01 0.01 "I work")
]
The following check fails:
@racketblock[
(check-= 1.0 1.01 0.005 "I fail") (check-= 1.0 1.01 0.005 "I fail")
] ]
}
@defproc*[([(check-true (v any) (message string? "")) void?] @defproc*[([(check-true (v any) (message string? "")) void?]
[(check-false (v any) (message string? "")) void?] [(check-false (v any) (message string? "")) void?]
[(check-not-false (v any) (message string? "")) void?])]{ [(check-not-false (v any) (message string? "")) void?])]{
Checks that @racket[v] is @racket[#t], @racket[#f], or not Checks that @racket[v] is @racket[#t], is @racket[#f], or is not
@racket[#f] as appropriate. The optional @racket[message] @racket[#f], respectively. The optional @racket[message] is included
is included in the output if the check fails.} in the output if the check fails.
For example, the following checks all fail: For example, the following checks all fail:
@ -82,49 +95,76 @@ For example, the following checks all fail:
(check-false 1) (check-false 1)
(check-not-false #f) (check-not-false #f)
] ]
}
@defproc[(check-exn (exn-predicate (or/c (-> any boolean?) regexp?))
@defproc[(check-exn (exn-predicate (or/c (-> any boolean?) regexp?)) (thunk (-> any)) (message string? "")) (thunk (-> any)) (message string? ""))
void?]{ void?]{
Checks that @racket[thunk] raises an exception and that
either @racket[exn-predicate] returns @racket[#t] if it is a function,
or that it matches the message in the exception if @racket[exn-predicate]
is a regexp. In the latter case, the exception raised must be
an @racket[exn:fail?].
The optional
@racket[message] is included in the output if the check
fails. A common error is to use an expression instead of a
function of no arguments for @racket[thunk]. Remember that
checks are conceptually functions.}
Here are two examples, one showing a test that succeeds, and one showing Checks that @racket[thunk] raises an exception and that either
a common error: @racket[exn-predicate] returns @racket[#t] if it is a function, or
that it matches the message in the exception if @racket[exn-predicate]
is a regexp. In the latter case, the exception raised must be an
@racket[exn:fail?]. The optional @racket[message] is included in the
output if the check fails. A common error is to use an expression
instead of a function of no arguments for @racket[thunk]. Remember
that checks are conceptually functions.
For example, the following check succeeds:
@racketblock[ @racketblock[
(check-exn exn:fail? (check-exn exn:fail?
(lambda () (lambda ()
(raise (make-exn "Hi there" (raise (make-exn "Hi there"
(current-continuation-marks))))) (current-continuation-marks)))))
]
The following check fails:
@racketblock[
(check-exn exn:fail?
(lambda ()
(break-thread (current-thread))))
]
The following example is a common mistake. The call to @racket[error]
is not within a @racket[lambda], so it bypasses @racket[check-exn]
entirely.
@racketblock[
(code:comment "Forgot to wrap the expression in a thunk. Don't do this!") (code:comment "Forgot to wrap the expression in a thunk. Don't do this!")
(check-exn exn:fail? (check-exn exn:fail?
(error 'hi "there")) (error 'hi "there"))
] ]
}
@defproc[(check-not-exn (thunk (-> any)) (message string? "")) void?]{ @defproc[(check-not-exn (thunk (-> any)) (message string? "")) void?]{
Checks that @racket[thunk] does not raise any exceptions. Checks that @racket[thunk] does not raise any exceptions.
The optional @racket[message] is included in the output if The optional @racket[message] is included in the output if
the check fails.} the check fails.
}
@defproc[(check-regexp-match (regexp regexp?) (string string?)) void?]{Checks that @racket[regexp] matches the @racket[string].} @defproc[(check-regexp-match (regexp regexp?)
(string string?))
void?]{
The following check will succeed: Checks that @racket[regexp] matches the @racket[string].
@racketblock[(check-regexp-match "a+bba" "aaaaaabba")]
This check will fail: For example, the following check succeeds:
@racketblock[
(check-regexp-match "a+bba" "aaaaaabba")
]
The following check fails:
@racketblock[
(check-regexp-match "a+bba" "aaaabbba")
]
}
@racketblock[(check-regexp-match "a+bba" "aaaabbba")]
@defproc[(check (op (-> any any any)) @defproc[(check (op (-> any any any))
(v1 any) (v1 any)
@ -132,16 +172,31 @@ This check will fail:
(message string? "")) (message string? ""))
void?]{ void?]{
The most generic check. Succeeds if @racket[op] applied to @racket[v1] and @racket[v2] is not @racket[#f], otherwise raises an exception of type @racket[exn:test:check]. The optional @racket[message] is included in the output if the check fails. The most generic check. Succeeds if @racket[op] applied to
@racket[v1] and @racket[v2] is not @racket[#f], otherwise raises an
exception of type @racket[exn:test:check]. The optional
@racket[message] is included in the output if the check fails.
For example, the following check succeeds: For example, the following check succeeds:
@racketblock[ @racketblock[
(check < 2 3) (check < 2 3)
] ]
The following check fails:
@racketblock[
(check memq 'pine '(apple orange pear))
]
} }
@defproc[(fail (message string? "")) void?]{This checks fails unconditionally. Good for creating test stubs that you intend to fill out later. The optional @racket[message] is included in the output.} @defproc[(fail (message string? ""))
void?]{
This check fails unconditionally. Good for creating test stubs that
you intend to fill out later. The optional @racket[message] is
included in the output.
}
@section{Augmenting Information on Check Failure} @section{Augmenting Information on Check Failure}
@ -189,8 +244,7 @@ When this check fails the message
@verbatim{time: <current-seconds-at-time-of-running-check>} @verbatim{time: <current-seconds-at-time-of-running-check>}
will be printed along with the usual information on an is printed along with the usual information on an check failure.
check failure.
@defform[(with-check-info ((name val) ...) body ...)]{ @defform[(with-check-info ((name val) ...) body ...)]{
@ -214,8 +268,7 @@ When this test fails the message
@verbatim{current-element: 8} @verbatim{current-element: 8}
will be displayed along with the usual information on an is displayed along with the usual information on an check failure.
check failure.
@ -235,18 +288,16 @@ that code must be wrapped in a thunk (a function of no
arguments) by the user. The predefined @racket[check-exn] arguments) by the user. The predefined @racket[check-exn]
is an example of this type of check. is an example of this type of check.
It is also useful to understand how the check information It is also useful to understand how the check information stack
stack operates. The stack is stored in a parameter and the operates. The stack is stored in a parameter and the
@racket[with-check-info] forms evaluate to calls to @racket[with-check-info] forms evaluate to calls to
@racket[parameterize]. Hence check information has lexical @racket[parameterize]. For this reason simple checks (see below)
scope. For this reason simple checks (see below) cannot cannot usefully contain calls to @racket[with-check-info] to report
usefully contain calls to @racket[with-check-info] to report
additional information. All checks created using additional information. All checks created using
@racket[define-simple-check] or @racket[define-check] grab @racket[define-simple-check] or @racket[define-check] grab some
some information by default: the name of the checks and the information by default: the name of the checks and the values of the
values of the parameters. Additionally the macro forms of parameters. Additionally the macro forms of checks grab location
checks grab location information and the expressions passed information and the expressions passed as parameters.
as parameters.
@defform[(define-simple-check (name param ...) expr ...)]{ @defform[(define-simple-check (name param ...) expr ...)]{
@ -258,9 +309,7 @@ check fails if the result of the @racket[expr]s is
simple checks cannot report extra information using simple checks cannot report extra information using
@racket[with-check-info].} @racket[with-check-info].}
Example: For example, the following code defines a check @racket[check-odd?]
To define a check @racket[check-odd?]
@racketblock[ @racketblock[
(define-simple-check (check-odd? number) (define-simple-check (check-odd? number)
@ -309,7 +358,6 @@ tests a number if within 0.01 of the expected value:
(< (abs (- actual expected)) 0.01)) (< (abs (- actual expected)) 0.01))
] ]
@defform[(define-check (name param ...) expr ...)]{ @defform[(define-check (name param ...) expr ...)]{
The @racket[define-check] macro acts in exactly the same way The @racket[define-check] macro acts in exactly the same way
@ -318,8 +366,12 @@ if the macro @racket[fail-check] is called in the body of
the check. This allows more flexible checks, and in the check. This allows more flexible checks, and in
particular more flexible reporting options.} particular more flexible reporting options.}
@defform[(fail-check)]{The @racket[fail-check] macro raises an @racket[exn:test:check] with @defform[(fail-check)]{
the contents of the check information stack.}
The @racket[fail-check] macro raises an @racket[exn:test:check] with
the contents of the check information stack.
}
@section{The Check Evaluation Context} @section{The Check Evaluation Context}

View File

@ -48,9 +48,37 @@ so the test can be named.
@defproc[(test-case? (obj any)) boolean?]{ @defproc[(test-case? (obj any)) boolean?]{
True if @racket[obj] is a test case, and false otherwise True if @racket[obj] is a test case, and false otherwise.
} }
@subsection{Shortcuts for Defining Test Cases}
@defproc*[([(test-check [name string?]
[operator (-> any/c any/c any/c)]
[v1 any/c]
[v2 any/c])
void?]
[(test-pred [name string?]
[pred (-> any/c any/c)]
[v any/c])
void?]
[(test-equal? [name string?] [v1 any/c] [v2 any/c]) (void?)]
[(test-eq? [name string?] [v1 any/c] [v2 any/c]) void?]
[(test-eqv? [name string?] [v1 any/c] [v2 any/c]) void?]
[(test-= [name string?] [v1 real?] [v2 real?] [epsilon real?]) void?]
[(test-true [name string?] [v any/c]) void?]
[(test-false [name string?] [v any/c]) void?]
[(test-not-false [name string?] [v any/c]) void?]
[(test-exn [name string?] [pred (-> exn? any/c)] [thunk (-> any)]) void?]
[(test-not-exn [name string?] [thunk (-> any)]) void?])]{
Creates a test case with the given @racket[name] that performs the
corresponding check. For example,
@racketblock[(test-equal? "Fruit test" "apple" "pear")]
is equivalent to
@racketblock[(test-case "Fruit test" (check-equal? "apple" "pear"))]
}
@section{Test Suites} @section{Test Suites}

View File

@ -3,13 +3,17 @@
@title{Overview of RackUnit} @title{Overview of RackUnit}
There are three basic data types in RackUnit: There are three basic concepts in RackUnit:
@itemize[ @itemize[
@item{A @italic{check} is the basic unit of a test. As the name suggests, it checks some condition is true.} @item{A @italic{check} is the basic unit of a test. As the name
suggests, it checks some condition is true.}
@item{A @italic{test case} is a group of checks that form one conceptual unit. If any check within the case fails, the entire case fails.} @item{A @italic{test case} is a group of checks that form one
conceptual unit. If any check within the case fails, the entire case
fails.}
@item{A @italic{test suite} is a group of test cases and test suites that has a name.} @item{A @italic{test suite} is a group of test cases and test suites
that has a name.}
] ]

View File

@ -4,7 +4,7 @@
@title{@bold{RackUnit}: Unit Testing for Racket} @title{@bold{RackUnit}: Unit Testing for Racket}
@author[(author+email "Noel Welsh" "noelwelsh@gmail.com") @author[(author+email "Noel Welsh" "noelwelsh@gmail.com")
(author+email "Ryan Culpepper" "ryan_sml@yahoo.com")] (author+email "Ryan Culpepper" "ryanc@racket-lang.org")]
RackUnit is a unit-testing framework for Racket. It RackUnit is a unit-testing framework for Racket. It
is designed to handle the needs of all Racket programmers, is designed to handle the needs of all Racket programmers,