snap-testing-0.2.0.0: A library for BDD-style testing with the Snap Web Framework

Safe HaskellNone

Snap.Test.BDD

Contents

Description

This library allows you to write tests against handlers, checking response codes and bodies, modifications of state, etc. The tests are written in a hierarchical fashion, with labels to help organize them, and various ways of reporting on the results of testing are possible.

All of the tests are run in the test environment, so be sure to create the corresponding .cfg files and databases, etc.

Here is a complete example (where routes are your applications routes, and app is your site initializer):

 runSnapTests [consoleReport, desktopReport] (route routes) app $ do
   name "/auth/new_user" $ do
     name "success" $
       succeeds (get "/auth/new_user")
     name "creates a new account" $
       cleanup clearAccounts $
       changes (+1) countAccounts (post "/auth/new_user" $ params
                                   [ ("new_user.name", "Jane")
                                   , ("new_user.email", "jdoe@c.com")
                                   , ("new_user.password", "foobar")])

There are many different predicates available (and a basic way of integrating QuickCheck), and it is relatively easy to add functionality on top of what is built in. For example, to add a way of creating users and logging in as them for a block of tests you could do the following (this is using the auth snaplet - if you are doing somethinge else, obviously the `with auth ...` line would be different):

 withUser :: SnapTesting App a -> SnapTesting App a
 withUser = modifySite $ \site -> do
   au <- fmap fromJust getRandomUser
   with auth $ forceLogin au
   site

Where getRandomUser is a function written in your applications handler (using whatever state needed).

Synopsis

Types

type SnapTesting b a = WriterT [TestLog] (StateT (Handler b b (), SnapletInit b b) IO) aSource

The main type for this library, where b is your application state, often called App. This is a State and Writer monad on top of IO, where the State carries your application (or, more specifically, a top-level handler), and the Writer allows tests to be reported as passing or failing.

type TestRequest = RequestBuilder IO ()Source

TestRequests are created with get and post.

data TestResult Source

TestResults are what are used to write report generators (two are included). The result is a tree structure.

Running tests

runSnapTestsSource

Arguments

:: [[TestResult] -> IO ()]

Report generators

-> Handler b b ()

Site that requests are run against (often route routes, where routes are your sites routes).

-> SnapletInit b b

Site initializer

-> SnapTesting b ()

Block of tests

-> IO () 

Run a set of tests, putting the results through the specified report generators

consoleReport :: [TestResult] -> IO ()Source

Prints test results to the console. For example:

 /auth/new_user
  success
    PASSED
  creates a new account
    PASSED

linuxDesktopReport :: [TestResult] -> IO ()Source

Sends the test results to desktop notifications on linux. Prints how many tests passed and failed.

Labeling

nameSource

Arguments

:: Text

Name of block

-> SnapTesting b ()

Block of tests

-> SnapTesting b () 

Labels a block of tests with a descriptive name, to be used in report generation.

Creating Requests

getSource

Arguments

:: ByteString

The url to request.

-> TestRequest 

Creates a new GET request.

postSource

Arguments

:: ByteString

The url to request.

-> Map ByteString [ByteString]

The parameters to send.

-> TestRequest 

Creates a new POST request, with a set of parameters.

paramsSource

Arguments

:: [(ByteString, ByteString)]

Pairs of parameter and value.

-> Map ByteString [ByteString] 

A helper to construct parameters.

Request predicates

succeeds :: TestRequest -> SnapTesting b ()Source

Checks that the given request results in a success (200) code.

notfound :: TestRequest -> SnapTesting b ()Source

Checks that the given request results in a not found (404) code.

redirects :: TestRequest -> SnapTesting b ()Source

Checks that the given request results in a redirect (3**) code.

redirectstoSource

Arguments

:: TestRequest

Request to run

-> Text

URL it should redirect to

-> SnapTesting b () 

Checks that the given request results in a redirect to a specific url.

changesSource

Arguments

:: (Show a, Eq a) 
=> (a -> a)

Change function

-> Handler b b a

Monadic value

-> TestRequest

Request to run.

-> SnapTesting b () 

Checks that the monadic value given changes by the function specified after the request is run.

For example, if you wanted to make sure that account creation was creating new accounts:

 changes (+1) countAccounts (post "/auth/new_user" $ params
                             [ ("new_user.name", "Jane")
                             , ("new_user.email", "jdoe@c.com")
                             , ("new_user.password", "foobar")])

changes'Source

Arguments

:: (Show a, Eq a) 
=> (a -> a)

Change function

-> Handler b b a

Monadic value

-> SnapTesting b c

Block of tests to run

-> SnapTesting b () 

A more general variant of changes that allows an arbitrary block instead of a request.

containsSource

Arguments

:: TestRequest

Request to run

-> Text

Text that body should contain

-> SnapTesting b () 

Checks that the response body of a given request contains some text.

notcontainsSource

Arguments

:: TestRequest

Request to run

-> Text

Text that body should not contain

-> SnapTesting b () 

Checks that the response body of a given request does not contain some text.

Stateful unit tests

equalsSource

Arguments

:: (Show a, Eq a) 
=> a

Value to compare against

-> Handler b b a

Handler that should evaluate to the same thing

-> SnapTesting b () 

Checks that the handler evaluates to the given value.

Run actions after block

cleanupSource

Arguments

:: Handler b b ()

Action to run after tests

-> SnapTesting b ()

Tests to run

-> SnapTesting b () 

Runs an action after a block of tests, usually used to remove database state.

Evaluate arbitrary action

evalSource

Arguments

:: Handler b b a

Action to evaluate

-> SnapTesting b a 

Evaluate arbitrary actions

Create helpers

modifySiteSource

Arguments

:: (Handler b b () -> Handler b b ())

Site modification function

-> SnapTesting b a

Tests to run

-> SnapTesting b a 

Given a site to site function (like, generating a random user and logging in), run the given block of test with the modified state.

Integrate with QuickCheck

quickCheck :: Testable prop => prop -> SnapTesting b ()Source

Allows you to run a quickcheck test. All 100 test passing counts as a pass, any failure a failure. Currently the reporting is really bad (you don't see what the failing example is).