こういう実装と、
module FooImpl where
foo :: Foo -> Bar
foo = ...
こういうテストがあったとする。
module FooImplSpec (main, spec) where
import Test.Hspec
-- 個別のspecファイルを実行するためにはmainが必要。
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
describe "foo" $ do
it "returns bar" $ do
foo bar `shouldBe` foobar
これまでテストを実行するときは stack test などとしていたが、コンパイル遅いし(特にリンカーの実行が遅い)、TDDするには不都合で冗長だった。記憶が正しければ自動で-O1がかかるので、これも素早くテストの実行を繰り返したい場合は邪魔だろう 1。
追記: どのみちリンカーは実行されているので、めちゃめちゃ速くなっているかと言えば微妙な気がしてきた。 ![]()
まぁ、stackでテストを実行する方法の紹介にもなっているのでいいとするか。 ![]()
そこで確実にインタープリターで実行できるよう、stack runghcで個別のテストを実行する方法を調べてみた。
あらかじめ
で依存するパッケージをインストールした上で
$ stack test --only-dependencies
# コマンドの内容に反して、実際には依存関係のインストールしか行わない。
# 「依存パッケージのテスト全部実行されちゃったらどうしよう!?」みたいな心配は不要。
のように実行すればよい。
$ stack runghc --package <作成中のパッケージ名> test/FooImplSpec.hs
自分自身のパッケージを指定しておくのがポイント。
しなければ「FooImplなんてmoduleないぜ?」と怒られてしまう。
当然、runghcなんで、残りの引数を渡せば実行するexample(it)を絞ることもできる。
$ stack runghc --package <作成中のパッケージ名> -- test/FooImplSpec.hs --match "実行したいexample"
# ^^^^^^
# 「--」を挟まなければ`test/FooImplSpec.hs`ではなく`stack`にオプションが解釈されてしまう恐れがあるので注意。
# この辺の仕様はほかのCLIツールを見習ってもうちょっと柔軟にしてほしい気もする。
なお、hspecに渡せるその他のオプションについてはこちらを参照。
元のstack testで使えた--file-watchオプションと同等なことをしたい場合はwatchexecなどのほかのツールを使おう。
なお、
みたいなテストが含まれるひな形はstack-templatesのhspec.hsfilesにあるので、すぐに試したい場合は
$ stack new <作りたいパッケージの名前> hspec
と実行すればよい。
-
単に最適化をオフにしたい場合は
--fastを渡せばいいらしい。 ↩