LoginSignup
5
0

More than 5 years have passed since last update.

Yesodのテストを読み解く

Posted at

Yesodは単体テストのための仕組みも備えています。

stackのテンプレートから作ったプロジェクトでは、 test ディレクトリの下にテスト用のファイルが格納されています。

今回はテスト関連のファイルを読み解いていきましょう。

▾ test/
  ▾ Handler/
      CommentSpec.hs
      CommonSpec.hs
      HomeSpec.hs
      ProfileSpec.hs
    Spec.hs
    TestImport.hs

Spec.hs

このファイルの中身はコメントだけです。

Spec.hs
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

このコメントは、HaskellのコンパイラであるGHCのオプションを指定していてます。
テストにおいては hspec-discover が大事で、これはテストが書かれたファイルを自動で探してくれるようにする指令です。

TestImport.hs

このファイルには、テストの中で使う関数をまとめてエクスポートしてくれています。
Model モジュールや Foundation のようなアプリケーションコードに加え、Yesod.Test のようなテスト専用のモジュールをエクスポートしています。

import部分までを抜粋します(Sqliteの場合)。

TestImport.hs
module TestImport
    ( module TestImport
    , module X
    ) where

import Application           (makeFoundation, makeLogWare)
#if MIN_VERSION_classy_prelude(1, 0, 0)
import ClassyPrelude         as X hiding (delete, deleteBy, Handler)
#else
import ClassyPrelude         as X hiding (delete, deleteBy)
#endif
import Database.Persist      as X hiding (get)
import Database.Persist.Sql  (SqlPersistM, SqlBackend, runSqlPersistMPool, rawExecute, rawSql, unSingle, connEscapeName)
import Foundation            as X
import Model                 as X
import Test.Hspec            as X
import Yesod.Default.Config2 (useEnv, loadYamlSettings)
import Yesod.Auth            as X
import Yesod.Test            as X

-- Wiping the database
import Database.Persist.Sqlite              (sqlDatabase, wrapConnection, createSqlPool)
import qualified Database.Sqlite as Sqlite
import Control.Monad.Logger                 (runLoggingT)
import Settings (appDatabaseConf)
import Yesod.Core (messageLoggerSource)

テスト本体

test/Handler ディレクトリの中に置かれたファイルが、テスト本体です。

▾ test/
  ▾ Handler/
      CommentSpec.hs
      CommonSpec.hs
      HomeSpec.hs
      ProfileSpec.hs

HomeSpec.hs の中身を見てみましょう。

HomeSpec.hs
module Handler.HomeSpec (spec) where

import TestImport

spec :: Spec
spec = withApp $ do

    describe "Homepage" $ do
        it "loads the index and checks it looks right" $ do
          get HomeR
          statusIs 200
          htmlAnyContain "h1" "a modern framework for blazing fast websites"

          request $ do
              setMethod "POST"
              setUrl HomeR
              addToken
              fileByLabel "Choose a file" "test/Spec.hs" "text/plain" -- talk about self-reference
              byLabel "What's on the file?" "Some Content"

          statusIs 200
          -- more debugging printBody
          htmlAllContain ".upload-response" "text/plain"
          htmlAllContain ".upload-response" "Some Content"

        -- This is a simple example of using a database access in a test.  The
        -- test will succeed for a fresh scaffolded site with an empty database,
        -- but will fail on an existing database with a non-empty user table.
        it "leaves the user table empty" $ do
          get HomeR
          statusIs 200
          users <- runDB $ selectList ([] :: [Filter User]) []
          assertEq "user table empty" 0 $ length users

基本的な流れ

基本的には次のような流れでテストを書きます。

  1. HTTPリクエスト1を実行して
  2. 結果を検証する
    • GETであれば、レスポンスのHTMLの内容を検証
    • POSTであれば、DBの内容を検証

テスト用の設定

DBの接続先などの設定を変えたい場合は、config/test-settings.yml を書き換えます。

テストの実行

テストを実行するには次のコマンド2を実行します。stackを使っている前提です。

stack test

まとめ

非常に簡単にですが、Yesodにおけるテストを見てみました。
割と簡単にテストを書けると思います。便利ですね。


  1. request 関数がHTTPリクエストを投げる関数なのですが、これが実際にHTTPを投げているのか、それともエミュレートしているのか、分かりませんでした。。。 

  2. 一部のテストを実行する方法が分かりませんでした。。。 

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0