Haskellトラックでのテスト

ExercismでHaskellの演習をテストする方法を学びます


テストの実行

テストを実行するには、演習のディレクトリで次のコマンドを実行します。

stack test

ファイルを保存するたびにテストを実行するには、代わりにこちらのコマンドを実行します。

stack test --file-watch

このようなエラーメッセージが表示されたら…

No .cabal file found in directory

おそらく古いバージョンのstackを使っているので、アップグレードする必要があります。

そうでなければ、このようなエラーメッセージが表示されたら…

No compiler found, expected minor version match with...
Try running "stack setup" to install the correct GHC...

表示されたとおりに実行すれば、正しいバージョンのコンパイラーがダウンロードされてインストールされます。

stack setup

演習を解く

演習の解答は、Haskellのモジュールです。モジュールの名前は、テストスイートのimport文で定義されています。通常はその先頭にあります。

import Test.Hspec        (Spec, describe, it, shouldBe)
import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith)

import ModuleName (someFunc)

main :: IO ()
main ...

この例では、テストファイルの4行目でModuleNameというモジュールをインポートしています。このモジュールはsomeFuncという関数をエクスポートしています。つまり、ModuleName.hsというファイルを作成する必要があります。内容は次のようになります。

module ModuleName (someFunc) where

someFunc :: ...
someFunc ...

src/には、この名前のファイルがすでに用意されています。これを解答の出発点として使えます。

ただし、このスタブは始めるためのものだという点に留意してください。変えたほうがよいと思うなら、遠慮なく丸ごと書き換えてください。

パッケージを使う

よりエレガントな解答を書くためにパッケージを使いたい場合は、まずpackage.yamlにある解答の依存関係にパッケージを追加します。

library:
  exposed-modules: ModuleName
  source-dirs: src
  dependencies:
    - foo
    - bar

ローカルで作業している間は、好きなパッケージを自由に使えます。ただし、オンラインのテストランナーが使えるパッケージは限られています。利用できるパッケージは次のとおりです。

  • GHCに最初からインストールされているもの(特にbase、containers、array、time、mtl、deepseq、exceptions、bytestring)
  • テストランナー用にビルド済みのもの。一覧はhaskell-test-runner/pre-compiled/package.yamlにあります。

利用できないパッケージを使った解答を提出すると、テストランナーはインターネットに接続できないため、次のようなエラーを出します。

Cabal file info not found for unavailable-package-1.0@..., updating
Selected mirror https://hackage.haskell.org/
Downloading root
HttpExceptionRequest Request {
  host                 = "hackage.haskell.org"
  ...
}
 (ConnectionFailure ...)

GHCiを実行する

GHCiで解答を試してみたいときは、次のコマンドを実行するだけです。

stack ghci

HLint(任意)

解答に対してhlintを実行して、見落としている点がないか確認することを強くおすすめします。

hlint ModuleName.hs

hlintの提案をすべて受け入れる必要はありませんが、ふつうは美しく慣用的なHaskellコードの書き方を学ぶ助けになります。