You are looking at historical revision 24654 of this page. It may differ significantly from its current revision.

Missbehave

Introduction

Missbehave is a toolkit that allows to you to bring behaviour driven development in the spirit of rspec, to your scheme of choice.

It is very much inspired and mostly modeled after the famous rspec-library.

Examples

(use missbehave miscmacros)

(define (callee . args) 'called)
(define (call-it n)
  (repeat n (callee)))

(describe "Missbehave features"
  (describe "implicit subject"
     (subject-set! 42)
     (it should (be 42))
     (it should (be a number)))
  
         
  (describe "Simple be matchers"
     (it "must be true"
         (expect #t (be true)))
     (it "must be a string"
         (expect "hello" to (be a string)))
     (it "can use standard operators"
         (expect 3 (be > 0)))
     (it "can use predicates"
         (expect '() (be null?))))

  (describe "Pending"
     (it "is implicitly pending")
     (it "is explicitly pending"
         (pending)
         (expect '() (be a number))))         

  (describe "Procedure expectations"
    (context "Application-count"
      (it "checks application count"
          (expect (call-it 1) to (call callee once)))
      (it "checks application count > 1"
          (expect (call-it 4) to (call callee (4 times))))
      (it "checks for no calls"
          (expect (+ 1 1) to (call callee never))))
    (context "Arguments"
     (it "checks arguments"
         (expect (callee 1 2) to (call callee (with 1 2))))
     (it "mixes arguments and application count"
         (expect (begin (callee 1 2) (callee 1 2)) to (call callee (with 1 2) twice)))))


  (describe "Procedure stubs"
    (it "can stub return values"
        (stub! callee (returns 'not-called))
        (expect (callee) to (be 'not-called)))

    (it "provides temporary stubs"
        (let ((proc (lambda () 'test)))
          (expect (proc) to (be 'test))
          (with-stubs! ((proc (returns 'passed)))
            (expect (proc) to (be 'passed)))
          (expect (proc) to (be 'test))))))

Now invoke it with:

$ behave test-spec.scm

Produces the following output:

Missbehave features
Procedure stubs
  It provides temporary stubs
  It can stub return values
Procedure expectations
Arguments
  It mixes arguments and application count
  It checks arguments
Application-count
  It checks for no calls
  It checks application count > 1
  It checks application count
Pending
  [P] It is explicitly pending
  [P] It is implicitly pending
Simple be matchers
  It can use predicates
  It can use standard operators
  It must be a string
  It must be true
implicit subject
  It should (be a number)
  It should (be 42)


Total: 15 Successful: 13 Pending: 2 Failures: 0

Authors

David Krentzlin

Api

Contexts

Contexts are a way to group your examples. You can use the the macro context and its alias describe to create them.

[syntax] (context context-name examples ...)

Create a context with the name context-name.

[syntax] (context context-name (meta (tags ...)) examples ...)

Create a context with name context-name and mark them with tags. This can be used to filter examples using the --tags command-line switch of behave.

[syntax] (context context-name (meta ((tag . value) ...) examples ...)

Create a context with name context-name and mark them with the key-value pairs. Those can be used to attach data and to filter them using the --tags command-line-switch of behave

Examples
(context "A simple context" 
  (it "does nothing"))

(context "A context with tags" (meta (long-running verbose))
  (it "is pending"))

(context "A context with value tags" (meta ((bug . "#402")))
  (it "is pending"))
  

Examples

Examples allow you to specify a specific behaviour of your subject.

[syntax] (it description)

Create a pending example with the description set to description

[syntax] (it should matcher)

Creates an example that executes matcher on the current subject. See also subject-set!.

[syntax] (it description expectation ...)

Creates an examples with the description set to description and the expectations.

(it "is pending")

(it "succeeds"
  (expect #t))
Meta-Information

Metainformation can be used to mark certain examples or provide some form of addtional information. As a plus the behave-cli allows you to use those meta-information to filter certain examples.

[syntax] (it description (meta (tags ...)) expectations)

Creates an example with expectations and tags.

[syntax] (it description (meta ((tag . value))) expectations ...)

Create an example with expectations and key-value pairs, so that it can be filtered.

Examples
(it "has tags" (meta (some tag))
  (expect #t))

(it "has more tags" (meta ((some . tag) (some . other)))
  (expect #t))

Expectations

Expectations are the bdd-way of stating assertions.

[syntax] (expect form)

Create an expection that evaluates form and will fail if form evaluates to #f and pass otherwise.

[syntax] (expect subject to (call arguments ...))

Creates an application-expectation. See also procedure-expections.

[syntax] (expect subject matcher)

Create an expection on subject with matcher matcher.

Negativ Expectations

If you want to state that a given subject should not have a certain behaviou, you can simply wrap the expect-form into a do-not form

[syntax] (do-not (expect ....))

Creates an expection that fails if its inner expectation succeeds and vice versa.

Matchers

Matchers are the way to implement the checks for a given behaviour. They verify that a given subject behaves as expected.

[syntax] (matcher (check (subject) check-code) (message (form subject negate) message-code))

Builtin Matchers

Be

The be matcher is possibly the most used. It allows you to describe what a given subject should be. The be macro allows a fair few variations. I've listed all possible forms below

[syntax] (be true)

matches if subject is #t

[syntax] (be false)

matches if subject is #f

[syntax] (be a type)

matches if subject is of the specified type. It assumes that there is a procedure type? to check that.

(expect "string" (be a string))
(expect (list 1 2 3) (be a list))

<macro>(be pred?)<macro> matches if pred? evaluates to #t when it is applied to subject

(expect 0 (be zero?))

<macro>(be value)<macro> matches if current subject is equal to value in the sense of equal?.

[syntax] (be pred? value ...)

This expands into something like (apply pred? (list subject value ...)). It provides a handy notation to write curried checks.

(expect 2 (be > 0))
(expect -100 (be <=  10))
call

This matcher is used to express procedure-expectations. It allows you to state that a form is expected to call a procedure.

[syntax] (call proc once)

matches if proc is called exactly once.

[syntax] (call proc twice)

matches if proc is called twice

[syntax] (call proc never)

matches if proc is never called.

[syntax] (call proc (n time))

matches if proc is called n times.

[syntax] (call proc (with arg ...)
[syntax] (call proc (with arg ...) amount-spec)

matches if proc is called with the given arguments and matches the amount-spec which is one of the obove (once never (n times)).

(define (foo) "foo")
(define (i-call-foo) (foo))

(define (bar x y) "bar")
(define (i-call-bar) (bar 1 2))

(expect (i-call-foo) (call foo once))
(expect (i-call-bar) (call bar (with 1 2) once))
raise

This matcher allows you to formulate expections about errors

[syntax] (raise error)

Matches if subject raises errors.

<macro>(raise (kind ...))<macro> Matches if subject raises an error and sets the kind-property at least to those specified.

(expect (error "test") (raise error))

Stubs

Missbehave provides a simple way to stub procedures. This is useful in cases where you want to control some of the procedures that interface, with the one you currently describe.

[syntax] (with-stubs! ((name stub) ... ) code ...)

This form replaces the behavior of name with the stub code. Note that there is a (returns)-form which is a short-hand to create a procedure that returns the given value.

[procedure] (returns value . more-values)

Creates a procedure that returns value. If you specify multiple value the procedure will return multiple values.

(define (return-3) 3)
(with-stubs! ((return-3 (returns "not 3"))
  (printf "return-3 returns ~A~%" (return-3)))

Hooks