これは、特定のモナド アクションの動作を調査するために使用してきたイベント ネットワークのサンプルです。コードをテストするこのアドホックな方法ではなく、原則に基づいたアプローチが必要です。自分の関数をテストする方法は知っていますが、新しい設計の選択肢があるため、ビヘイビアとイベントをテストするためのベスト プラクティスを探しています。reactive-banana 1.0.0
私の問題を説明するために必要なものだけを含めることを期待して、私は多くを省略しています。問題を明確にするために含めるべき何かが欠けている場合はお知らせください。
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
テストから正確な結果を得る最良の方法は何ですか?
編集: 更新 -このリンクで十分なヒントが得られると思います。詳しくは明日調べて報告します。
編集: 更新 - 単体テストを作成しました。きれいになったらgithubにアップロードしてから投稿します。上記のリンクは、何をすべきかを整理するのに非常に役立ちました。
編集: 更新 - スタック テストを実行して型エラーが発生し、再度実行すると、テストが合格したという出力が得られます。結果として、私は昨日の私に近づいていません。コードとより明確な問題があります。そのために別の投稿を始めるかもしれません.ct
編集:更新 - 役立つ方法で壊れるテストがありますが、正確に何をすべきかわかりません。コンテキストのためにプロジェクト全体を投稿しました。以下に、テストコード、エラー、およびいくつかの説明のみを含めます。
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"))))
問題は、 で をaccumB
作成することに帰着Behavior
しMomemtIO
ます。bufferPopulated
返品した場合、どうすればそれIO Bool
を調整できますか?
編集: 明らかなことは、必要なインスタンスを作成することです。これはおそらくニシンだと思います。どう思いますか。MomentIO Bool
これはインスタンスを書くだけで簡単ですか?
編集:更新私は正しい軌道に乗っていると思います。すべてのテスト ハーネス コードをコメント アウトし、署名を変更しました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))
MonadMoment
から見てみましょう。Reactive.Banana.Combinators
class Monad m => MonadMoment m where
An instance of the MonadMoment class denotes a computation that happens at one particular moment in time.
Unlike the Moment monad, it need not be pure anymore.
Methods
liftMoment :: Moment a -> m a
Instances
MonadMoment MomentIO
MonadMoment Moment
m
は任意Monad
です。に持ち上げる必要がありますが、そうしないのはなぜですか。私の推論の何が問題になっていますか?IO
Monad
liftMoment
Moment Behavior (BufferMap)
IO Behavior (BufferMap)