Testing in Haskell with Servant
hspec-wai を使って Servant server のテストを書く方法を紹介します。
Hspec は Haskell のユニットテストライブラリです。このライブラリの詳しい説明は省略します。
本記事のソースコードは以下のリポジトリにおいてあります。
http://github.com/algas/haskell-servant-cookbook
テスト対象
servant server のコードを用意します。
"/" にリクエストを投げると "Simple" を返すだけの簡単な API です。
lib/SimpleApi.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module SimpleApi where
import Data.Aeson
import Data.Proxy
import Data.Text (Text)
import GHC.Generics
import Network.Wai
import Servant
import Servant.API
type SimpleAPI = Get '[PlainText] Text
simpleApi :: Proxy SimpleAPI
simpleApi = Proxy
server :: Server SimpleAPI
server = return "Simple"
app :: Application
app = serve simpleApi server
テストコード
次にテストコードを用意します。
上記の SimpleApi
から app
を呼び出します。
hspec-wai から with
を使っているのがポイントです。
with :: IO a -> SpecWith a -> Spec
以下がテストコードです。
test/Spec.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module Main (main) where
import SimpleApi (app)
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
main :: IO ()
main = hspec spec
spec :: Spec
spec = with (return app) $ do
describe "GET /" $ do
it "responds with 200" $ do
get "/" `shouldRespondWith` 200
it "responds with 'Simple'" $ do
get "/" `shouldRespondWith` "Simple"
haskell-servant-cookbook.cabal
test-suite test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, hspec
, hspec-wai
, hspec-wai-json
, aeson
, transformers
, haskell-servant-cookbook
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
動作確認
以下のコマンドでテストを実行します。
$ stack test
haskell-servant-cookbook-0.1.0.0: test (suite: test)
Progress: 1/2
GET /
responds with 200
responds with 'Simple'
Finished in 0.0138 seconds
2 examples, 0 failures
Completed 2 action(s).
Template 化
上記のテストの雛形を stack の servant template に組み込むために PR
を1つ送っています。
無事に取り入れられれば、stack new (myproj) servant
でテストの雛形まで作られた状態になります。
参考文献