on master help sign in
doco fixes and a build tool stanza
commit900105a892af1195f7a1f69652a84dbeb9939bc0 authorMark Wotton <mwotton@gmail.com> dateTue 5 Jan 2021, 10:38 (6 years ago) parentdf67dfc
5 files changed+49−40
EXAMPLE.md+34−33 README.md+10−2 package.yaml+2−1 roboservant.cabal+3−2 stack.yaml−2
EXAMPLE.md+34−33
@@ -2,7 +2,7 @@
22
33Our api under test:
44
5−```haskell
5+``` haskell
66-- Obligatory fancy-types pragma tax
77{-# LANGUAGE DataKinds #-}
88{-# LANGUAGE TypeOperators #-}
@@ -20,6 +20,7 @@ import Servant
2020import GHC.Generics
2121import Data.Typeable
2222import Data.Hashable
23+import Data.Maybe(isNothing, isJust)
2324
2425newtype A = A Int
2526 deriving (Generic, Eq, Show, Typeable)
@@ -34,9 +35,7 @@ type Api =
3435 :<|> "itemAdd" :> Capture "one" B :> Capture "two" B :> Get '[JSON] B
3536 :<|> "item" :> Capture "itemId" B :> Get '[JSON] ()
3637
37−goodServer = server (pure $ A 0)
38−badServer = server (pure $ A 1)
39−
38+server :: Handler A -> Server Api
4039server introduce = introduce :<|> combine :<|> eliminate
4140 where
4241 combine (B i) (B j) = pure $ B (i + j)
@@ -45,36 +44,55 @@ server introduce = introduce :<|> combine :<|> eliminate
4544 | otherwise = pure ()
4645```
4746
47+We have a "good" server, that never generates anything other than a 0. This means repeated application of
48+the combination/addition rule can never bring us to the dangerous state of numbers larger than 100.
49+
50+``` haskell
51+goodServer, badServer :: Server Api
52+goodServer = server (pure $ A 0)
53+badServer = server (pure $ A 1)
54+```
55+
4856In the test file, we first define the tests: the faulty server should fail and the good server should pass.
4957
5058```haskell
59+main :: IO ()
60+main = hspec spec
61+
62+spec :: Spec
5163spec = describe "example" $ do
5264 it "good server should not fail" $ do
5365 fuzz @Api goodServer config
5466 >>= (`shouldSatisfy` isNothing)
5567 it "bad server should fail" $ do
5668 fuzz @Api badServer config
57− >>= (`shouldSatisfy` serverFailure)
69+ >>= (`shouldSatisfy` isJust)
70+```
71+
5872
73+We expect to be able to cover the whole api from our starting point, so let's set the coverage to 0.99.
74+There are other tweakable things in the config, like maximum runtime, reps,
75+per-request healthchecks, seeds, and verbose logging. Have a look at
76+Roboservant.Types.Config for details.
77+
78+``` haskell
79+config :: Config
5980config = defaultConfig
60− {
61− -- we expect to be able to cover the api from our starting point:
62− -- this will fail the test if we don't.
63− coverageThreshold = 0.99
81+ { coverageThreshold = 0.99
6482 }
65−
66−-- there are other tweakable things in the config, like maximum runtime, reps,
67−-- per-request healthchecks, seeds, and verbose logging. Have a look at
68−-- Roboservant.Types.Config for details.
6983```
7084
71−And unless we want to ship roboservant and all its dependencies to production, we also need
85+Unless we want to ship roboservant and all its dependencies to production, we also need
7286some orphan instances: because As are the only value we can get without
7387an input, we need to be able to break them down.
7488
75−```haskell
89+``` haskell
7690deriving via (Compound A) instance Breakdown A
77−-- if we wanted to assemble As from parts as well, we'd derive using Compound
91+```
92+
93+if we wanted to assemble As from parts as well, we'd derive using Compound, but in this case we don't care.
94+
95+``` haskell
7896deriving via (Atom A) instance BuildFrom A
7997
8098```
@@ -86,20 +104,3 @@ build it up from components.
86104deriving via (Compound B) instance BuildFrom B
87105deriving via (Atom B) instance Breakdown B
88106```
89−
90−finally some uninteresting utilities and the entrypoint
91−
92−```haskell
93−main = hspec spec
94−
95−serverFailure :: Maybe Report -> Bool
96−serverFailure c = case c of
97− Just Report{..} ->
98− let RoboservantException{..} = rsException
99− in failureReason /= NoPossibleMoves
100− _ -> False
101−
102−isNothing x = case x of
103− Nothing -> True
104− _ -> False
105−```
README.md+10−2
@@ -19,9 +19,14 @@ sessions and verify properties that should hold over them.
1919In essence, ```fuzz @Api yourServer config``` will make a bunch of
2020calls to your API, and record the results in a type-indexed
2121dictionary. This means that they are now available for the
22−prerequisites of other call, so as you proceed, more and more api
22+prerequisites of other calls, so as you proceed, more and more api
2323calls become possible.
2424
25+We explicitly do not try to come up with plausible values that haven't
26+somehow come back from the API. That's straying into QC/Hedgehog
27+territory: if you want that, come up with the values on that side, and
28+set them as seeds in the configuration.
29+
2530### what does it mean to be "available"?
2631
2732In a simple API, you may make a call and get back a `Foo`, which will
@@ -65,7 +70,10 @@ Sometimes there are values we'd like to smuggle into the API that are
6570not derivable from within the API itself: sometimes this is a warning
6671sign that your API is incomplete, but it can be quite reasonable to
6772require identifying credentials within an API and not provide a way to
68−get them. For those cases, override the `seed` in the `Config` with a
73+get them. It might also be reasonable to have some sample values that
74+the user is expected to come up with.
75+
76+For those cases, override the `seed` in the `Config` with a
6977list of seed values, suitably hashed:
7078
7179``` haskell
package.yaml+2−1
@@ -63,5 +63,6 @@ tests:
6363 dependencies:
6464 - roboservant
6565 - hspec
66− # build-depends: base, markdown-unlit
6766 ghc-options: -pgmL markdown-unlit
67+
68+ build-tools: markdown-unlit
roboservant.cabal+3−2
@@ -4,7 +4,7 @@ cabal-version: 1.12
44--
55-- see: https://github.com/sol/hpack
66--
7−-- hash: 3eb8db6b6899ba904be853bb6865aba4f208077587e89f5377df3169743034b0
7+-- hash: 48773018ec618e9eba02a126e3aeb93781a1d68ce28e2c405c35e9536bf94f70
88
99name: roboservant
1010version: 0.1.0.2
@@ -33,7 +33,6 @@ library
3333 Roboservant.Types.Breakdown
3434 Roboservant.Types.BuildFrom
3535 Roboservant.Types.Config
36− Roboservant.Types.Config.Internal
3736 Roboservant.Types.FlattenServer
3837 Roboservant.Types.Internal
3938 Roboservant.Types.ReifiedApi
@@ -72,6 +71,8 @@ test-suite example
7271 hs-source-dirs:
7372 ./.
7473 ghc-options: -Wall -fwrite-ide-info -hiedir=.hie -pgmL markdown-unlit
74+ build-tool-depends:
75+ markdown-unlit:markdown-unlit
7576 build-depends:
7677 base >=4.7 && <5
7778 , bytestring
stack.yaml−2
@@ -1,6 +1,4 @@
11resolver: lts-16.27
2−# bit faster on ReifiedApi stuff which is unfortunately terribly slow.
3−# compiler: ghc-8.10.3
42packages:
53- .
64