如何对 Racket 中具有动态输出的函数使用单元测试框架?
How to use a unit-testing framework for a function that has a dynamic output in Racket?
我正在做 SICP 书上的练习 3.5。
Racket 中的 Monte Carlo 实现生成以下代码:
(define (monte-carlo trials experiment)
(define (iter trials-remaining trials-passed)
(cond ((= trials-remaining 0)
(/ trials-passed trials))
((experiment)
(iter (- trials-remaining 1) (+ trials-passed 1)))
(else
(iter (- trials-remaining 1) trials-passed))))
(iter trials 0))
(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))
; questão propriamente dita
(define (estimate-integral predicate x1 x2 y1 y2 trials)
(*(* (- x1 x2) (- y1 y2))
(monte-carlo trials predicate)))
(define (circulo?)
(>= 1 (+ (square (random-in-range -1 1))
(square (random-in-range -2 1)))))
(define (estimate-pi)
(estimate-integral circulo? -1.0 1 -2 1 100000))
; Fiquei brincando com os os parametros do retangulo, desde que o circulo continue dentro dele
(define square
(lambda (x) (* x x)))
代码正确。
但是,我决定插入一些单元测试。
因此,我导入了库 rackunit 并使用了以下测试:
(require rackunit)
(check-equal? (estimate-pi) 3.00906)
这显然是一个问题,测试总是会失败,因为由于随机函数,输出是动态的。
遇到这种情况怎么办?
对此有内置检查 - 首选解决方案:
(check-= (estimate-pi) 3.1416 1e-4 "Incorrect value for pi")
之前的检查验证结果是否在可接受的 tolerance 值范围内(也称为 epsilon),它等同于此:
(check-true (<= (abs (- (estimate-pi) 3.1416)) 1e-4))
1e-4
部分是科学记数法中的公差,意思是如果实际值与期望值的差值小于0.0001
,则我们认为结果是正确的。当然,您可以调整公差值以满足您的需要 - 数字越小,所需的精度越高。此外,知道如果 check-=
不存在,我们可以定义我们自己的检查,就像这样:
(define-binary-check (check-in-tolerance actual expected tolerance)
(<= (abs (- actual expected)) tolerance))
(check-in-tolerance (estimate-pi) 3.1416 1e-4)
我正在做 SICP 书上的练习 3.5。
Racket 中的 Monte Carlo 实现生成以下代码:
(define (monte-carlo trials experiment)
(define (iter trials-remaining trials-passed)
(cond ((= trials-remaining 0)
(/ trials-passed trials))
((experiment)
(iter (- trials-remaining 1) (+ trials-passed 1)))
(else
(iter (- trials-remaining 1) trials-passed))))
(iter trials 0))
(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))
; questão propriamente dita
(define (estimate-integral predicate x1 x2 y1 y2 trials)
(*(* (- x1 x2) (- y1 y2))
(monte-carlo trials predicate)))
(define (circulo?)
(>= 1 (+ (square (random-in-range -1 1))
(square (random-in-range -2 1)))))
(define (estimate-pi)
(estimate-integral circulo? -1.0 1 -2 1 100000))
; Fiquei brincando com os os parametros do retangulo, desde que o circulo continue dentro dele
(define square
(lambda (x) (* x x)))
代码正确。 但是,我决定插入一些单元测试。
因此,我导入了库 rackunit 并使用了以下测试:
(require rackunit)
(check-equal? (estimate-pi) 3.00906)
这显然是一个问题,测试总是会失败,因为由于随机函数,输出是动态的。
遇到这种情况怎么办?
对此有内置检查 - 首选解决方案:
(check-= (estimate-pi) 3.1416 1e-4 "Incorrect value for pi")
之前的检查验证结果是否在可接受的 tolerance 值范围内(也称为 epsilon),它等同于此:
(check-true (<= (abs (- (estimate-pi) 3.1416)) 1e-4))
1e-4
部分是科学记数法中的公差,意思是如果实际值与期望值的差值小于0.0001
,则我们认为结果是正确的。当然,您可以调整公差值以满足您的需要 - 数字越小,所需的精度越高。此外,知道如果 check-=
不存在,我们可以定义我们自己的检查,就像这样:
(define-binary-check (check-in-tolerance actual expected tolerance)
(<= (abs (- actual expected)) tolerance))
(check-in-tolerance (estimate-pi) 3.1416 1e-4)