Help us understand the problem. What is going on with this article?

Yesodのテストを読み解く

More than 3 years have passed since last update.

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. 一部のテストを実行する方法が分かりませんでした。。。 

jabaraster
得意な言語はJava、好きな言語はHaskell
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした