2015-11-09 3 views
8

ここでは、特定のモナドアクションの動作を調べるために使ってきたイベントネットワークのサンプルを紹介します。私はコードをテストするこの特別な方法ではなく、原則的なアプローチを望んでいます。私は自分の関数をテストする方法を知っていますが、私は新しいデザインの選択肢を考えて、ビヘイビアとイベントをテストするためのベストプラクティスを探していますreactive-banana 1.0.0Reactive Banana 1.0.0 - MomentIO()モナドのユニットテスト

私はたくさん残しています。私の問題を説明するために必要です。問題を明確にするために含めるべきでないものがある場合は、教えてください。バッファが行うことになっている何

makeNetworkDescription :: Parameters -> MomentIO() 
makeNetworkDescription params = mdo 
    eInput <- fromAddHandler (input params) 
    eTick <- fromAddHandler (tick params) 
    let 
    eValidated :: Event VAC 
    eValidated = toVAC <$> eInput 

    eClearBuffer = Clear <$ eBuffer 

    eBuffer ::Event BufferMap 
    eBuffer = bBuffer <@ eTick 

    bBuffer <- accumB (BufferMap (M.empty :: M.Map AID VAC)) $ 
      manageBuffer <$> unionWith (clearBuffer) eValidated eClearBuffer  
reactimate $ writeOut_Debug <$> eBuffer 

、(その後、別の場所で処理されます)プレーヤーのコマンドを蓄積しており、プレイヤーのコマンドの特定のバッチが処理された後、その後、空にすること。次のティックで、それは再び何度も起こります。

私は、バッファが必要なときにクリアされていることを確認し、想定されているようなコマンドを蓄積します。今すぐコードが動作し、私はこのゲームを構築するときにそれが動作し続けることを保証するテストを書きたいと思う。

Behaviorを上記の例のEventネットワークから分離することはできますが、それではどうしますか?テストから正確な結果を得るための最良の方法は何ですか?

編集:更新 - 私はthis linkが十分なヒントを提供すると信じています。私はそれを刺し、明日の詳細を報告します。

編集:更新 - ユニットテストが作成されています。私はgithubにパリティがあるときにアップロードし、投稿します。上記のリンクは、何をすべきかを整理するのに非常に役立ちました。

編集:更新 - スタックテストを実行しているときにタイプエラーが発生し、再度実行すると、テストが合格したという出力が表示されます。結局のところ、私は昨日だったとは限りません。私はコードと明確な問題があります。私はthat.ctの別の投稿を開始することがあります。

編集:更新 - 私は役に立つ方法で壊れてテストがありますが、私はそれについて正確に何をしないのですか。私は文脈のためにproject全体を投稿しました。以下に、テストコード、エラー、およびいくつかの議論だけを示します。

main :: IO() 
main = defaultMain 
    [ testGroup "EventNetwork Input" 
    [testBuffer "bBuffer" Populated] 
    ] 

testBuffer :: String -> BufferState -> Test 
testBuffer name Populated = 
testCase name $ assert $ bufferPopulated (UAC (PlayerCommand (Move (ToPlanetName Mongo)) (AID (Data.Text.pack "100")))) 
testBuffer name Empty = 
testCase name $ assert $ bufferEmptied (UAC (PlayerCommand (Move (ToPlanetName Mongo)) (AID (Data.Text.pack "100")))) 

bufferPopulated :: UAC -> MomentIO Bool 
bufferPopulated ev = do 
    let eInput = ev <$ never 
     eValidated = toVAC <$> eInput 
    bBufferMap <- (buffer eValidated eClear) :: MomentIO (Behavior BufferMap) 
    let r2 = [(Just $ BufferMap $ M.insert (AID (Data.Text.pack "100")) (toVAC ev) (M.empty :: M.Map AID VAC))] 
r1 <- liftIO $ ((interpret (eBuffer bBufferMap) []) :: IO [Maybe BufferMap]) 
return $ r1 == r2 

bufferEmptied :: UAC -> MomentIO Bool 
bufferEmptied ev = undefined 

eBuffer :: Behavior BufferMap -> Event a -> Event BufferMap 
eBuffer bBufferMap nvr = 
    bBufferMap <@ (() <$ nvr) 

eClear = Clear <$ (() <$ never) 


tests/Spec.hs:26:19: 
    No instance for (Test.HUnit.Base.Assertable (MomentIO Bool)) 
     arising from a use of ‘assert’ 
In the expression: assert 
In the second argument of ‘($)’, namely 
    ‘assert 
    $ bufferPopulated 
     (UAC 
      (PlayerCommand (Move (ToPlanetName Mongo)) (AID (pack "100"))))’ 
In the expression: 
    testCase name 
    $ assert 
    $ bufferPopulated 
     (UAC 
      (PlayerCommand (Move (ToPlanetName Mongo)) (AID (pack "100")))) 

問題がMomemtIOBehaviorを作成accumBにダウンしています。もし私がbufferPopulatedを返すとIO Bool私はそれをどのように調整できますか?

編集:明白なことは、必要なインスタンスを作成することです。私はこれがおそらく赤ちゃんだと思う。どう思いますか。これは単にMomentIO Boolインスタンスを作成するだけの簡単なことですか?

編集:更新 私は正しい道にいると思う。私はのはReactive.Banana.Combinators

から MonadMomentを見てみましょう、すべてのテストハーネスのコードをコメントアウトしていると bufferPopulated

bufferPopulated :: UAC -> IO Bool 
bufferPopulated ev = do 
    let eInput = ev <$ never 
     eValidated = toVAC <$> eInput 
    bBufferMap <- liftMoment ((buffer eValidated eClear) :: Moment (Behavior BufferMap)) 
    let r2 = [(Just $ BufferMap $ M.insert (AID (Data.Text.pack "100")) (toVAC ev) (M.empty :: M.Map AID VAC))] 
    r1 <- (interpret (eBuffer bBufferMap) []) :: IO [Maybe BufferMap])   
    return $ r1 == r2 

のための署名を変更している私は、これは動作するはずと信じていますが、ここでエラーが

tests/Spec.hs:35:17: 
    No instance for (MonadMoment IO) arising from a use of ‘liftMoment’ 
    In a stmt of a 'do' block: 
     bBufferMap <- liftMoment 
         ((buffer eValidated eClear) :: Moment (Behavior BufferMap)) 

mは、いずれでもよいが、Monad,IOMonad。そうliftMomentMoment Behavior (BufferMap)からIO Behavior (BufferMap)を持ち上げる必要があり、なぜそれはしていません。私の推論で何が間違っていますか?答えの

答えて

1

ソースは、この前の回答から来ました。

Testing in reactive-banana

interpretFramwork新しい署名を必要とします。

interpretFrameWorks'' :: (Event a -> MomentIO (Behavior b)) -> [a] -> IO (b,[[b]]) 
interpretFrameWorks'' f xs = do 
    output      <- newIORef [] 
    init      <- newIORef undefined 
    (addHandler, runHandlers) <- newAddHandler 
    network      <- compile $ do 
    e <- fromAddHandler addHandler 
    f' <- f e 
    o <- changes $ f' 
    i <- valueB $ f' 
    liftIO $ writeIORef init i 
    reactimate' $ (fmap . fmap) (\b -> modifyIORef output (++[b])) o 

    actuate network 
    bs <- forM xs $ \x -> do 
     runHandlers x 
     bs <- readIORef output 
     writeIORef output [] 
     return bs 
    i <- readIORef init 
    return (i, bs) 
関連する問題