;; ;; %%HEADER%% ;; (use test) (load "../missbehave.scm") (load "../missbehave-matchers.scm") (load "../missbehave-stubs.scm") (import missbehave) (import missbehave-matchers) (import missbehave-stubs) (define (example-fails? content #!optional (name "test")) (example-failed? (run-example (create-example name content)))) (test-group "Examples" (test "stores description" "test" (example-description (create-example "test" (lambda () #t)))) (test "run a failing example" #t (example-fails? (lambda () (run-expectation #f (be true))))) (test "errors in examples" #t (example-fails? (lambda () (error "test")))) (test "run succeeding example" #f (example-fails? (lambda () (run-expectation #t (delay #t) (be true))))) (test "run pending example" #t (example-pending? (run-example (create-example "test" (lambda () #t) pending: #t)))) (test "run pending by call to pending" #t (example-pending? (run-example (create-example "test" (lambda () (pending)))))) (test "create and run pending using macros" #t (example-pending? (run-example (it "should be a test-example")))) (test "create and run failing using macros" #t (example-failed? (run-example (it "should be failing" (expect #f (be true)))))) (test "create and run succeeding using macros" #f (example-failed? (run-example (it "should be successful" (expect #t (be true))))))) (test-group "Context" (test "Stores description" "testcontext" (context-description (create-context "testcontext"))) (test "Running context signals success" #t (run-context (context "Test" (it "should succeed" (expect #t (to (be true))))))) (test "Running context signals failure" #f (run-context (context "Test" (it "should fail" (expect #t (to (be false))))))) (test "Running context runs all examples" 2 (let ((counter 0) (ctx (create-context "testcontext"))) (add-example-to-context (it "should be executed" (set! counter (+ counter 1))) ctx) (add-example-to-context (it "should be executed as well" (set! counter (+ counter 1))) ctx) (run-context ctx) counter)) (test "Before(each) hooks" 2 (let ((counter 0) (ctx (create-context "testcontext"))) (add-hook-to-context (lambda args (set! counter (+ 1 counter))) filter: 'each: type: 'before context: ctx) (add-example-to-context (it "should be executed") ctx) (add-example-to-context (it "should be executed as well") ctx) (run-context ctx) counter)) (test "After(each) hooks" #t (let ((flag #f) (ctx (create-context "testcontext"))) (add-hook-to-context (lambda args (set! flag #t)) filter: 'each: type: 'after context: ctx) (add-example-to-context (it "should be executed") ctx) (run-context ctx) flag)) (test "Before(tag-description) hooks" 1 (let ((counter 0)) (run-context (describe "testcontext" (before (tag) (set! counter (+ 1 counter))) (it "executes" (meta (tag))) (it "executes as well"))) counter)) (test "Context using macro" #t (let ((flag #f)) (run-context (describe "test-context" (it "executes example" (set! flag #t)))) flag)) (test "Context and Describe can be used interchangably" #t (let ((flag #f)) (run-context (context "test-context" (it "executes example" (set! flag #t)))) flag)) (test "Context with before(each) using macro" #t (let ((flag #f)) (run-context (describe "test-context" (before each: (set! flag #t)) (it "executes"))) flag))) (test-group "Nested contexts" (test "Runs hooks from outer contexts" 1 (let ((result 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (context "outer" (before each: (set! result (+ result 2))) (context "inner" (before each: (set! result (- result 1))) (it "should succeed" (expect 1 (be 1))))))) reporter: values) result)) (test "Runs hooks in order from grand-parents to parents to children" '(grandpa pa kid) (let ((result (list))) (run-specification (call-with-specification (make-empty-specification) (lambda () (context "grandpa" (before each: (set! result (cons 'grandpa result))) (context "pa" (before each: (set! result (cons 'pa result))) (context "kid" (before each: (set! result (cons 'kid result))) (it "should succeed" (expect 1 (be 1)))))))) reporter: values) (reverse result))) ) (test-group "Filtering" (test "Include context" 1 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "runner" (meta (tag)) (it "should be run" (set! counter (+ 1 counter)) (expect (eq? #t #f)))) (describe "no runner" (it "should not be run" (set! counter (+ 1 counter)))))) include: '((tag)) reporter: values) counter)) (test "Exclude context" 2 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "runner" (meta (tag)) (it "should be run" (set! counter (+ 1 counter)))) (describe "no runner" (it "should not be run" (set! counter (+ 2 counter)))))) exclude: '((tag)) reporter: values) counter)) (test "Include Example" 1 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "testrun" (it "should run" (meta (run)) (set! counter (+ 1 counter))) (it "should not run" (set! counter (+ 2 counter)))))) include: '((run)) reporter: values) counter)) (test "Exclude Example" 2 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "testrun" (it "should run" (meta (run)) (set! counter (+ 1 counter))) (it "should not run" (set! counter (+ 2 counter)))))) exclude: '((run)) reporter: values) counter)) (test "Include Context but exclude specific example" 2 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "testrun" (meta (context)) (it "should not run" (meta (run)) (set! counter (+ 1 counter))) (it "should run" (set! counter (+ 2 counter)))) (describe "not-run" (it "should not run" (set! counter (+ 2 counter)))))) include: '((context)) exclude: '((run)) reporter: values) counter)) ;; context filter have precedence before example-filters (test "Exclude Context but include specific example" 0 (let ((counter 0)) (run-specification (call-with-specification (make-empty-specification) (lambda () (describe "testrun" (meta (context)) (it "should run" (meta (run)) (set! counter (+ 1 counter))) (it "should not run" (set! counter (+ 2 counter)))))) exclude: '((context)) include: '((run)) reporter: values) counter)) ) (test-group "Expectations" (test "Syntactic sugar to be more expressive" #t (example-failed? (run-example (it "should fail" (expect #f ( to (be true))))))) (test "Negative expectation" #f (example-failed? (run-example (it "should succeed" (do-not (expect #f ( to (be true)))))))) (test "Negaive expectation message" "Expected #t not to be #t" (let* ((result (run-example (it "fail" (do-not (expect #t (to (be true)))))))) (example-result-messages result)))) (test-group "Subject" (test "Set subject" 'test-subject (let* ((subject-value 'nil) (context (describe "Implicit subject" (subject-set! 'test-subject) (it "Should know the subject" (set! subject-value (subject)))))) (call-with-context context (lambda () (run-context context))) subject-value)) (test "Use Implicit subject" #t (let* ((context-result 'nil) (context (describe "Implicit subject" (subject-set! #t) (it should (be true))))) (call-with-context context (lambda () (set! context-result (run-context context)))) context-result))) (define-syntax test-matcher (syntax-rules () ((_ group-name matcher positive-check negative-check failure-message) (test-group group-name (test "positive result" #f (example-failed? (run-example (it "should succeed" (expect positive-check matcher))))) (test "negative result" #t (example-failed? (run-example (it "should fail" (expect negative-check matcher))))) (test "failure-message" failure-message (let ((result (run-example (it "should fail" (expect negative-check matcher))))) (example-result-messages result))))))) (test-group "Be matchers" (test-matcher "(be true)" (be true) #t #f "Expected #f to be #t") (test-matcher "(be false)" (be false) #f #t "Expected #t to be #f") (test-matcher "(be pred?)" (be null?) '() '(1) "Expected (1) to be null?") (test-matcher "(be value)" (be "test") "test" "pie" "Expected \"pie\" to be \"test\"") (test-matcher "(be operator other)" (be > 0) 3 -1 "Expected -1 to be > 0") (test-matcher "(be a type)" (be a string) "test" (list) "Expected () to be a string")) (test-group "Be matcher helpers" (test-matcher "(be (close 1))" (be (close-to 1)) 1 2 "Expected 2 to be close to 1 ") (test-matcher "(be (close 1 delta: 0.1))" (be (close-to 1 delta: 0.1)) 0.9 2 "Expected 2 to be close to 1 delta: 0.1 ") (test-matcher "(be (any-of 1 2))" (be (any-of 1 2)) 1 3 "Expected 3 to be any of 1 2 ") (test-matcher "(be (none-of 1 2))" (be (none-of 1 2)) 3 1 "Expected 1 to be none of 1 2 ") (test-matcher "(be (list-including 1 2)" (be (list-including 1 2)) (list 1 2 3) (list) "Expected () to be list including 1 2 ")) (test-group "Match-string") (test-group "Have-matcher") (test-group "Error matchers" (test "(error)" #f (example-failed? (run-example (it "should succeed" (expect (error "boom") (raise error)))))) (test "(error) negative" #t (example-failed? (run-example (it "should fail" (expect #t (raise error)))))) (test "(error (exn))" #f (example-failed? (run-example (it "should succeed" (expect (error "boom") (raise (exn))))))) (test "(error (exn)) negative" #t (example-failed? (run-example (it "should fail" (expect (error "boom") (raise (io)))))))) (test-group "Procedure expectations" (test "(call proc once)" #f (example-failed? (run-example (let* ((callee (lambda (x) x)) (caller (lambda () (callee 42)))) (it "should succeed" (expect (caller) (call callee once))))))) (test "(call proc twice)" #f (example-failed? (run-example (let* ((callee (lambda (x) x)) (caller (lambda () (callee 42) (callee 56)))) (it "should succeed" (expect (caller) (call callee twice))))))) (test "(call (1 time))" #f (example-failed? (run-example (let* ((callee (lambda (x) x)) (caller (lambda () (callee 42)))) (it "should succeed" (expect (caller) (call callee (1 time)))))))) (test "(call (2 times))" #f (example-failed? (run-example (let* ((callee (lambda (x) x)) (caller (lambda () (callee 42) (callee 53)))) (it "should succeed" (expect (caller) (call callee (2 times)))))))) (test "(call proc never)" #f (example-failed? (run-example (let* ((callee (lambda (x) x)) (caller (lambda () 'no))) (it "should succeed" (expect (caller) (call callee never))))))) (test "(call proc (with 1 2))" #f (example-failed? (run-example (let* ((callee (lambda (x y) 42)) (caller (lambda () (callee 1 2)))) (it "should succeed" (expect (caller) (call callee (with 1 2)))))))) (test "failing (call proc (with 1 2))" #t (example-failed? (run-example (let* ((callee (lambda (x y) 42)) (caller (lambda () (callee 1 33)))) (it "should succeed" (expect (caller) (call callee (with 1 2)))))))) (test "(call proc (with 1 2) twice)" #f (example-failed? (run-example (let* ((callee (lambda (x y) 42)) (caller (lambda () (callee 1 2) (callee 1 2)))) (it "should succeed" (expect (caller) (call callee (with 1 2) twice))))))) (test "failing (call proc (with 1 2) once) because of application count" #t (example-failed? (run-example (let* ((callee (lambda (x y) 42)) (caller (lambda () (callee 1 2) (callee 1 2)))) (it "should succeed" (expect (caller) (call callee (with 1 2) once))))))) (test "failing (call proc (with 1 2) once) because of argument missmatch" #t (example-failed? (run-example (let* ((callee (lambda (x y) 42)) (caller (lambda () (callee 1 2) (callee 1 3)))) (it "should succeed" (expect (caller) (call callee (with 1 2) once))))))) ) (test-group "State" (test "Retrieve state of unset variable" #f ($ 'some-variable)) (test "Default value" 'default ($ 'some-variable default: 'default)) (test "Set state" 1 (begin (set! ($ 'number) 1) ($ 'number))) (test "reset all states" #f (begin (set! ($ 'number) 2) (reset-state!) ($ 'number)))) (test-group "Stubs" (test "stub return value" 10 (let ((return-20 (lambda () 20))) (stub! return-20 (returns 10)) (return-20))) (test "temporary stubs" (list 20 10 20) (let ((return-20 (lambda () 20))) (list (return-20) (with-stubs! ((return-20 (returns 10))) (return-20)) (return-20)))) (test "stub with custom code" "hand-crafted" (let ((return-20 (lambda () 20))) (stub! return-20 (lambda _ "hand-crafted")) (return-20))) (test "mix stubs and expectations" (list #f 20) (let ((result #f) (return-value #f)) (set! result (example-failed? (run-example (let* ((callee (lambda () 10)) (caller (lambda () (set! return-value (callee))))) (it "should succeed" (stub! callee (returns 20)) (expect (caller) (call callee once))))))) (list result return-value))) )