servant-quickcheck- QuickCheck entire APIs

Safe HaskellNone




withServantServer :: HasServer a '[] => Proxy a -> IO (Server a) -> (BaseUrl -> IO r) -> IO r Source #

Start a servant application on an open port, run the provided function, then stop the application.


withServantServerAndContext :: HasServer a ctx => Proxy a -> Context ctx -> IO (Server a) -> (BaseUrl -> IO r) -> IO r Source #

Like withServantServer, but allows passing in a Context to the application.


serversEqual :: HasGenRequest a => Proxy a -> BaseUrl -> BaseUrl -> Args -> ResponseEquality ByteString -> Expectation Source #

Check that the two servers running under the provided BaseUrls behave identically by randomly generating arguments (captures, query params, request bodies, headers, etc.) expected by the server. If, given the same request, the response is not the same (according to the definition of == for the return datatype), the Expectation fails, printing the counterexample.

The Int argument specifies maximum number of test cases to generate and run.

Evidently, if the behaviour of the server is expected to be non-deterministic, this function may produce spurious failures

Note that only valid requests are generated and tested. As an example of why this matters, let's say your API specifies that a particular endpoint can only generate JSON. serversEqual will then not generate any requests with an Accept header _other_ than application/json. It may therefore fail to notice that one application, when the request has Accept: text/html, returns a 406 Not Acceptable HTTP response, and another returns a 200 Success, but with application/json as the content-type.

The fact that only valid requests are tested also means that no endpoints not listed in the API type are tested.


serverSatisfies :: HasGenRequest a => Proxy a -> BaseUrl -> Args -> Predicates -> Expectation Source #

Check that a server satisfies the set of properties specified.

Note that, rather than having separate tests for each property you'd like to test, you should generally prefer to combine all properties into a single test. This enables a more parsimonious generation of requests and responses with the same testing depth.

Example usage:

goodAPISpec = describe "my server" $ do

  it "follows best practices" $ do
    withServantServer api server $ \burl ->
      serverSatisfies api burl stdArgs (not500
                                    <%> onlyJsonObjects
                                    <%> notAllowedContainsAllowHeader
                                    <%> mempty)