Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
== Outdated egg! This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for [[/eggref/5/missbehave|the CHICKEN 5 version of this egg]], if it exists. If it does not exist, there may be equivalent functionality provided by another egg; have a look at the [[https://wiki.call-cc.org/chicken-projects/egg-index-5.html|egg index]]. Otherwise, please consider porting this egg to the current version of CHICKEN. [[tags: egg]] == Missbehave [[toc:]] === 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 [[http://rspec.info|rspec-library]]. === Sources You can find the egg sources at: [[https://bitbucket.org/certainty/missbehave]] === The name As it has been asked on #chicken and it really can be misleading, here is why the name is spelled this way. It is intended to be a pun. (I guess not a good one, as i have to explain it) It consists of the words '''miss''' where i mean error. And '''behave''' where i mean, erm, behave. So you may read as "C'mon miss, behave!". That's by the way also the reason why the cli is called '''behave'''. So the two words together form "mis'''s'''behave" which is intentionally close to "misbehave". To be totally fair. I quite understand why this has been discussed, as i'm very aware of my limitions regarding english spelling. === Examples <enscript highlight=scheme> (use missbehave missbehave-matchers missbehave-stubs miscmacros) (define (callee . args) 'called) (define (call-it n) (repeat n (callee))) (describe "Missbehave features" (describe "implicit subject" (subject-set! 42) (it (is > 10)) (it (is a number)) (it should (be 42))) (describe "Simple be matchers" (it "must be true" (expect #t (to (be true)))) (it "must be a string" (expect "hello" (to (be a string)))) (it "can use standard operators" (expect 3 (is > 0))) (it "can use predicates" (expect '() (is null?)))) (define (numbers ls) ls) (describe "Have" (it "can be used with a collection procedure" (expect '(1 2 3) (has 3 numbers))) (it "supports arbritary sugar" (expect "foo" (has 3 characters)))) (describe "Matches string" (it "checks if regex matches string" (expect '(: (+ digit)) (matches-string "1234"))) (it "checks the submatches" (expect '(: (+ digit) (submatch (+ any))) (matches-string "1234foo" with-matches: '((1 . "foo")))))) (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) (call callee once))) (it "checks application count > 1" (expect (call-it 4) (call callee (4 times)))) (it "checks for no calls" (expect (+ 1 1) (call callee never)))) (context "Arguments" (it "checks arguments" (expect (callee 1 2) (call callee (with 1 2)))) (it "mixes arguments and application count" (expect (begin (callee 1 2) (callee 1 2)) (call callee (with 1 2) twice))))) (describe "Procedure stubs" (it "can stub return values" (stub! callee (returns 'not-called)) (expect (callee) (be 'not-called))) (it "provides temporary stubs" (let ((proc (lambda () 'test))) (expect (proc) (be 'test)) (with-stubs! ((proc (returns 'passed))) (expect (proc) (be 'passed))) (expect (proc) (be 'test)))))) </enscript> Now invoke it with: <enscript highlight=raw> $ behave test-spec.scm </enscript> Produces the following output: <enscript highlight=raw> 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 </enscript> === Authors [[/users/david-krentzlin|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. <macro>(context context-name examples ...)</macro> Create a context with the name {{context-name}}. <macro>(context context-name (meta (tags ...)) examples ...)</macro> 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'''. <macro>(context context-name (meta ((tag . value) ...)) examples ...)</macro> 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 <enscript highlight=scheme> (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")) </enscript> ==== Examples Examples allow you to specify a specific behaviour of your subject. <macro>(it description)</macro> Create a pending example with the description set to {{description}} <macro>(it should matcher)</macro> Creates an example that executes {{matcher}} on the current subject. See also '''subject-set!'''. <macro>(it description expectation ...)</macro> Creates an examples with the description set to {{description}} and the expectations. <enscript highligh=scheme> (it "is pending") (it "succeeds" (expect #t)) </enscript> ===== 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. <macro>(it description (meta (tags ...)) expectations)</macro> Creates an example with expectations and tags. <macro>(it description (meta ((tag . value))) expectations ...)</macro> Create an example with expectations and key-value pairs, so that it can be filtered. ===== Examples <enscript highligh=scheme> (it "has tags" (meta (some tag)) (expect #t)) (it "has more tags" (meta ((some . tag) (some . other))) (expect #t)) </enscript> ==== Expectations Expectations are the bdd-way of stating assertions. <macro>(expect form)</macro> Create an expection that evaluates form and will fail if {{form}} evaluates to #f and pass otherwise. <enscript highligh=scheme> (it "succeeds") (expect (string? "chickumber"))) (it "fails" ) (expect (> 2 3))) </enscript> <macro>(expect subject to (call arguments ...))</macro> Creates an application-expectation. See also procedure-expections. <enscript highligh=scheme> (define (reverse-list ls) (reverse ls)) (expect (reverse-list (list 1 2 3)) (call reverse))) (expect (reverse-list (list 1 2)) (call reverse once))) (expect (reverse-list (list 1 2)) (call reverse (with (list 1 2)))) (expect (reverse-list (list 1 2)) (call reverse (with (list 1 2)) once)) </enscript> <macro>(expect subject matcher)</macro> Create an expection on subject with matcher {{matcher}}. <enscript highligh=scheme> (expect (list 1 2) (be a list)) (expect "foobar" (have 6 characters)) (expect 3.1 (be (close-to 3))) </enscript> ===== Negative 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 <macro>(do-not (expect ....))</macro> 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. <macro>(matcher (check (subject) check-code) (message (form subject negate) message-code))</macro> This creates a fresh matcher object. You need to implement both the {{check}} and the {{message}}. * check The check is a procedure that receives one argument, the subject. The subject is a promise so you need to force it if you want to retrieve the value. * message This is the procedure that is invoked to generate the message. It receives three arguments ** {{form}} This is the quoted form that was passed to expect ** {{subject}} This is the subject. Again this is a promise so you need to force it to retrieve the actual value. ** {{negate}} Indicates if the check shall be negated. This is set to true if the expect-form has been wrapped into a (do-not) form. <enscript highlight=scheme> (define (greater-than x) (matcher (check (subject) (> (force subject) x)) (message (form subject negate) (if negate (sprintf "Expected ~A to be less than or equal to ~A" (force subject) x) (sprintf "Expected ~A to be greater than ~A" (force subject) x))))) (expect 10 (be (greater-than 5))) </enscript> ==== 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 '''Aliases:''' is <macro>(be true)</macro> matches if subject is #t <macro>(be false)</macro> matches if subject is #f <macro>(be a type)</macro> matches if subject is of the specified type. It assumes that there is a procedure type? to check that. <enscript highlight=scheme> (expect "string" (be a string)) (expect (list 1 2 3) (be a list)) </enscript> <macro>(be pred?)</macro> matches if pred? evaluates to #t when it is applied to subject <enscript highlight=scheme> (expect 0 (be zero?)) </enscript> <macro>(be value)</macro> matches if current subject is equal to value in the sense of equal?. <macro>(be pred? value ...)</macro> This expands into something like (apply pred? (list subject value ...)). It provides a handy notation to write curried checks. <enscript highlight=scheme> (expect 2 (be > 0)) (expect -100 (be <= 10)) </enscript> ====== Be-helpers There are some procedures that enhance the possibilities of the be matcher <procedure>(close-to value #!key (delta 0.3))</procedure> <enscript highlight=scheme> (expect 2 (be (close-to 1)) (expect 10/3 (be (close-to 3 delta: 0.4)) </enscript> <procedure>(any-of value . more-values)</procedure> <enscript highlight=scheme> (expect 2 (be (any-of 1 2 3 4)) </enscript> <procedure>(none-of value . more-values)</procedure> <enscript highlight=scheme> (expect 5 (be (none-of 1 2 3 4)) </enscript> <procedure>(list-including value . more-values)</procedure> <enscript highlight=scheme> (expect (list 1 2 3) (be (list-including 1 2)) </enscript> ===== match-string This matcher can be used to describe the behaviour of regular expressions. '''Aliases:''' matches-string <procedure>(match-string str #!key (with-matches #f))</procedure> This succeeds if the regular expression represented by {{subject}} matches the string {{str}}. If {{with-matches}} is supplied, it is expected to be an alist holding the expected captures. <enscript highlight=scheme> (expect '(: (+ space) (submatch (+ any))) (match-string " test" with-matches: '((1 . "test"))) (expect '(: (+ any)) (match-string "just a test")) </enscript> ===== have This matcher can be used to specify expectations on the amount of items in a collection. '''Aliases:''' has <enscript highlight=scheme> (expect "string" (has 6 chars)) (define (even-numbers ls) (filter even? ls)) (expect '(1 2 3 4 5) (has 2 even-numbers)) </enscript> ===== call This matcher is used to express procedure-expectations. It allows you to state that a form is expected to call a procedure. '''Aliases:''' calls <macro>(call proc once)</macro> matches if proc is called exactly once. <macro>(call proc twice)</macro> matches if proc is called twice <macro>(call proc never)</macro> matches if proc is never called. <macro>(call proc (n time))</macro> matches if proc is called n times. <macro>(call proc (with arg ...))</macro> matches if proc is called at least once with the given arguments. <macro>(call proc (with arg ...) amount-spec)</macro> matches if proc is called with the given arguments and matches the amount-spec which is one of the above (once never (n times)). <enscript highlight=scheme> (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)) </enscript> ===== raise This matcher allows you to formulate expections about errors <macro>(raise error)</macro> 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. <enscript highlight=scheme> (expect (error "test") (raise error)) </enscript> ==== 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. <macro>(with-stubs! ((name stub) ... ) code ...)</macro> 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)</procedure> Creates a procedure that returns value. If you specify multiple value the procedure will return multiple values. <enscript highlight=scheme> (define (return-3) 3) (with-stubs! ((return-3 (returns "not 3")) (printf "return-3 returns ~A~%" (return-3))) </enscript> ==== Hooks
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you add 20 to 2?