2013-05-15 2 views
3

라켓 프로그램을 구성하는 방법에 대한 조언을 찾고 있습니다. 현재 저는 약 5 가지 버전의 프로그램이 있고 각 프로그램에는 각 파일의 끝에 추가 된 동일한 단위 테스트 (RackUnit)가 있습니다. 이것은 유지하기가 어렵습니다.라켓의 다양한 파일에 대해 하나의 단위 테스트 세트 사용

내가 원하는 것은 테스트를 별도의 파일로 추출하고 RackUnit에게 각 프로그램에 대해 한 번 테스트를 실행하도록 요청하는 것입니다. 하지만 어떻게해야할지 모르겠습니다. 어떤 충고?

감사합니다.

답변

3

이 경우에는 아마도 Racket의 reflection system을 사용하여 매우 동적 인 작업을 수행 할 수 있습니다.

예를 들어 모듈 집합이 모두 단조롭게 증가하는 함수 인 f을 제공하는지 확인한다고 가정 해 보겠습니다. 동일한 배터리 테스트를 통해 구현 컬렉션을 테스트하는 프레임 워크를 어떻게 작성할 수 있습니까?

우리는 마구 쓸 수

:

  • 이 모듈 requires 질문에 구현하는 모듈을 구축을하고,
  • 그것에 일련의 테스트를 실행합니다. 테스트 모듈의 건설을 수행하고, 동적 eval를 사용하여 실행

    (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은 일반적으로 악으로 간주되지만이 특정 상황에서는 적절한 도구라고 생각합니다. 우리가이 도우미가 있으면

, 우리는 파일의 모음에서 실행할 수 있습니다, impls 하위 디렉토리에 말 :

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

당신은 모든 조각을 볼 수 complete running example (https://github.com/dyoo/monotonic-f-example)을 시도 할 수 있습니다.

1

내가이 얼마나 강력한 모른다 (이. 테스트는 위의 방법에 의해 비참하게 부족한 것이 분명해야한다)하지만, 여기에 위생 깨는 매크로를 사용하여 솔루션입니다. (대니 나를 생각 :) 어쩌면 당신은 그의 충고를 따르도록 할 것보다 똑똑하다.)

파일 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->syntaxtests 매크로는 stx의 컨텍스트에서 식별자를 사용해야합니다. 즉, 매크로가 인 경우이 호출됩니다. 일반적으로 매크로는 이 정의 된 시간에 식별자를 사용합니다 ().f1.rkt 또는 f2.rkt 파일을 실행하면 테스트가 실행됩니다. (인쇄물은 올바른 기능이 호출되었음을 증명하기위한 것입니다.)

관련 문제