Test driving the development of a testing framework using itself in Guile
Previously :
- Kick-off
- Chapter 18. First Steps to xUnit
- Chapter 19. Set the Table
- Chapter 20. Cleaning up After
- Chapter 21. Counting
- Chapter 22. Dealing with Failure
- Chapter 23. How Suite It Is
- Revisiting Guile xUnit
My last post was full of errors ! I guess I got lost in the REPL state and faced ghosts, like variables and procedures no more defined… In this post, I give you a new version of the code without errors. You also get a bonus feature : the failing tests are named in the summary.
Enjoy !
The steps followed are almost the same as the one in the previous article of this serie.
The difference lies in the way I encapsulate everything inside functions :
* gunit-test
is the function responsible for running the tests.
* runner
and summary
are the functions under test.
* gunit-project
is the function that ensure my REPL is not relying on the state of old evaluations.
(use-modules ((debugging assert) #:select (assert))
(ice-9 exceptions))
(define (gunit-project)
(define* (runner #:key (setup (const #f)) (teardown (const #f)))
(let ([count (vector 0 0)]
[failures '()])
(lambda* (#:rest procs)
(map
(lambda (proc)
(vector-set! count 0 (1+ (vector-ref count 0)))
(guard (e
((exception? e)
(vector-set! count 1 (1+ (vector-ref count 1)))
(set! failures (cons (symbol->string (procedure-name proc)) failures))))
(dynamic-wind setup proc teardown)))
procs)
(values count failures))))
(define (summary count failures)
(format #f "~A run, ~A failed~A"
(vector-ref count 0)
(vector-ref count 1)
(string-concatenate (map
(lambda (failure)
(format #f "\n- ~A" failure))
failures))))
(define (gunit-test)
(define log "")
(define (test-proc) (set! log (string-append log "proc ")))
(define (test-proc-broken) (raise-exception (make-exception)))
(define (setup-proc) (set! log (string-append log "setup ")))
(define (teardown-proc) (set! log (string-append log "teardown ")))
(define (test-template)
((runner #:setup setup-proc #:teardown teardown-proc) test-proc)
(assert (string=? log "setup proc teardown ")))
(define (test-result)
(call-with-values (lambda () ((runner) test-proc))
(lambda (count failures)
(assert (string=? "1 run, 0 failed" (summary count failures))))))
(define (test-failed-result)
(call-with-values (lambda () ((runner) test-proc-broken))
(lambda (count failures)
(assert (string=? "1 run, 1 failed\n- test-proc-broken" (summary count failures))))))
(define (test-suite)
(call-with-values (lambda () ((runner) test-proc test-proc-broken))
(lambda (count failures)
(assert (string=? "2 run, 1 failed\n- test-proc-broken" (summary count failures))))))
(let* ([setup (lambda () (set! log ""))]
[run (runner #:setup setup)])
(call-with-values (lambda ()
(run test-template
test-result
test-failed-result
test-suite))
(lambda (count failures)
(summary count failures)))))
(gunit-test))
(gunit-project)
Thank you very much for reading this article!
Don't hesitate to give me your opinion, suggest an idea for improvement, report an error, or ask a question ! I would be so glad to discuss about the topic covered here with you ! You can reach me here.
Don't miss out on the next ones ! Either via RSS or via e-mail !
And more importantly, share this blog and tell your friends why they should read this post!
#gnu #guile #tdd #book #english
GPG: 036B 4D54 B7B4 D6C8 DA62 2746 700F 5E0C CBB2 E2D1