3

我正在寻找有关如何构建我的球拍程序的建议。目前,我有大约 5 个不同版本的程序,每个程序都有相同的单元测试(RackUnit),只是添加到每个文件的末尾。这很难维护。

我想要做的是将测试提取到一个单独的文件中,并要求 RackUnit 为每个程序运行一次测试。但我不知道该怎么做。有什么建议吗?

谢谢!

4

2 回答 2

4

在这种情况下,也许我们可以通过使用 Racket 的反射系统来做一些高度动态的事情。

例如,假设我们要确保一组模块都提供一个f似乎是单调递增函数的函数。我们如何编写一个框架,用相同的测试组测试一组实现?

我们可以编写一个工具:

  • 构造一个模块,该模块是requires一个有问题的实现模块,并且
  • 在其上运行一组测试。

代码可能如下所示:

(define (test-module-with-monotonic-f module-path-name)
  (define ns (make-base-namespace))
  (printf "testing ~s\n" module-path-name)
  (eval `(begin (module a-test-module racket/base
                  (require rackunit
                           (file ,(path->string module-path-name)))
                  (check-true (> (f 1) (f 0))
                              (format "~a fails to provide monotonic f" ,module-path-name))
                  (check-true (> (f 3) (f 2))
                              (format "~a fails to provide monotonic f" ,module-path-name)))
                (require 'a-test-module))
        ns))

它构建了测试模块,并使用动态eval. eval通常被认为是邪恶的,但在这种特殊情况下,我认为这是一个合适的工具。

一旦我们有了这个助手,我们就可以在一个文件集合上运行它,比如在一个impls子目录中:

(for ([mod-name (in-directory "impls")]
      #:when (equal? (filename-extension mod-name) #"rkt"))
  (test-module-with-monotonic-f mod-name))

您可以尝试完整的运行示例(https://github.com/dyoo/monotonic-f-example)来查看所有部分。

(顺便说一句,应该清楚的是,上面的测试严重不足。)

于 2013-05-15T20:57:24.997 回答
1

我不知道这有多强大,但这里有一个使用破坏卫生的宏的解决方案。(不过 Danny 比我聪明 :) 所以也许你会想听从他的建议。)

文件f1.rkt

#lang racket
(define (f x) (displayln "f1's f") (+ x 1))
(define (g x) (displayln "f1's g") (+ x 2))
(require "f-tests.rkt")
(tests)

文件f2.rkt

#lang racket
(define (f x) (displayln "f2's f") (+ 1 x))
(define (g x) (displayln "f2's g") (+ 2 x))
(require "f-tests.rkt")
(tests)

文件f-tests.rkt

#lang racket
(provide tests)
(define-syntax (tests stx)
  (syntax-case stx ()
    [(_)
     (datum->syntax 
      stx
      '(begin
         (require rackunit)
         (check-equal? (f 10) 11)
         (check-equal? (g 20) 22)))]))

datum->syntax说宏应该在的tests上下文中使用标识符stx,即宏被调用的地方(通常,宏将在定义宏时使用标识符)。运行任一文件f1.rktf2.rkt将运行测试。(打印只是为了证明正在调用正确的函数。)

于 2013-05-15T22:13:50.023 回答