Exet的球拍测试

时间:2016-09-30 13:16:42

标签: unit-testing exception racket raise

我正在采取Racket中的异常处理的第一步,并且想要编写单元测试,如果某个过程引发特定输入的异常,则会检查该单元测试。

以下是我已经拥有的内容:

程序,应引起例外:

(define (div-interval x y)
  ;; EXERCISE 2.10
  ; exception handling
  (with-handlers
    ([exn:fail:contract:divide-by-zero?
      (lambda (exn)
        (displayln (exn-message exn))
        #f)])

    (if (or
      (>= (upper-bound y) 0)
      (<= (lower-bound y) 0))

      (raise
        (make-exn:fail:contract:divide-by-zero
        "possible division by zero, interval spans zero"
        (current-continuation-marks)))

      (mul-interval
        x
        (make-interval
          (/ 1.0 (upper-bound y))
          (/ 1.0 (lower-bound y)))))))

单元测试:

(require rackunit)

(define exercise-test
  (test-suite
    "exercise test suite"

    #:before (lambda () (begin (display "before")(newline)))
    #:after (lambda () (begin (display "after")(newline)))

    (test-case
      "checking interval including zero"
      (check-exn
        exn:fail:contract:divide-by-zero?
        (div-interval
          (make-interval 1.0 2.0)
          (make-interval -3.0 2.0))
        "Exception: interval spans zero, possible division by zero")))

(run-test exercise-test)

此测试套件中还有一些测试,但它们用于其他过程,因此我没有将它们包含在此代码中。当我运行我的程序时,我得到以下输出:

before
possible division by zero, interval spans zero
after
'(#<test-success> #<test-success> #<test-success> #<test-success> #<test-error>)

本帖中的<test-error>适用于测试用例。

程序似乎没有引发异常。

是吗,因为我的程序中有一个handler,它返回#f,因此已经&#34;吃了#34;例外?

我通常如何为引发的异常编写单元测试?

1 个答案:

答案 0 :(得分:4)

你是完全正确的,你的代码没有引发异常,因为with-handler抓住它并返回#f。如果您希望with-handler为您重新引发异常,则需要使用raise,使您的代码看起来像:

(define (div-interval x y)
  (with-handlers
    ([exn:fail:contract:divide-by-zeor?
      (lambda (e)
        <do-stuff>
        (raise e))])
    <function-body>)

现在你的处理程序仍然会运行,但最后它会为你重新引发异常。

至于测试它,你绝对正确check-exn是正确的方法。除了因为check-exn是一个过程,你需要将你的代码包装在一个thunk中,使它看起来像:

(require rackunit)
(check-exn
  exn:fail:contract:divide-by-zero?
  (lambda ()
    (div-interval
      (make-interval 1.0 2.0)
      (make-interval -3.0 2.0))))