1

私が大好きな Pipes を使用するプロジェクトのプログラムを作成しました。ただし、コードの単体テストに苦労しています。

Pipe In Out IO ()HSpec でテストしたいタイプ (たとえば) の一連の関数があります。これについてどうすればいいですか?

たとえば、次のドメインがあるとします。

data Person = Person String Int | Unknown deriving (Show, Eq)
data Classification = Friend | Foe | Undecided deriving Show

そしてこのパイプ:

classify :: Pipe Person (Person, Classification) IO ()
classify = do
    p@(Person name _) <- await
    case name of 
      "Alex" -> yield (p, Friend)
      "Bob" -> yield (p, Foe)
      _ -> yield (p, Undecided)

仕様を書きたいと思います:

main = hspec $ do
  describe "readFileP" $ 
    it "yields all the lines of a file"
      pendingWith "How can I test this Pipe? :("
4

2 に答える 2

1

パッケージの関数を使用temporaryして、期待されるデータで一時ファイルを作成し、データがパイプによって正しく読み取られることをテストできます。

ちなみに、遅延 I/O を実行するPipeものを使用しています。readFileLazy I/O とパイプのようなストリーミング ライブラリはあまりうまく混ざりません。実際、後者は主に前者の代替として存在します!

代わりに、 や などの厳密な I/O を実行する関数を使用する必要がopenFileありgetLineます。

厳密な I/O の厄介な点の 1 つは、リソースの割り当てをより慎重に検討する必要があることです。最後に、またはエラーが発生した場合に、各ファイルハンドルが確実に閉じられるようにする方法は? ResourceT IOこれを実現する 1 つの可能な方法は、直接ではなく、モナドで作業することIOです。

于 2016-08-27T16:16:38.803 に答える
1

コツはtoListMPipesListTモナド変換子から使うことです。

import Pipes
import qualified Pipes.Prelude as P
import Test.Hspec

data Person = Person String Int | Unknown deriving (Show, Eq)
data Classification = Friend | Foe | Undecided deriving (Show, Eq)

classify :: Pipe Person (Person, Classification) IO ()
classify = do
  p@(Person name _) <- await
  case name of 
    "Alex" -> yield (p, Friend)
    "Bob" -> yield (p, Foe)
    _ -> yield (p, Undecided)

ListT トランスフォーマーを使用してパイプを ListT に変換し、HSpec を使用してアサートするテスト:

main = hspec $ do
  describe "classify" $ do
    it "correctly finds friends" $ do
      [(p, cl)] <- P.toListM $ each [Person "Alex" 31] >-> classify
      p `shouldBe` (Person "Alex" 31)
      cl `shouldBe` Friend

を使用する必要はないことに注意してeachくださいyield

于 2016-09-08T08:47:37.290 に答える