gpt4 book ai didi

haskell - 在 react 香蕉中进行测试

转载 作者:行者123 更新时间:2023-12-02 10:52:54 27 4
gpt4 key购买 nike

有没有办法对在 react 香蕉中创建的网络进行单元测试?假设我已经建立了一些带有一些输入事件的网络 - 是否可以验证事件已经产生了一些输出流/行为在一定数量的输入事件之后具有一些值(value)。这样做是否有意义?

我注意到有各种interpret*功能,但似乎无法弄清楚如何使用它们。还有Model看起来非常适合测试但与实际实现具有完全不同类型的模块。

最佳答案

当你说“单元测试”时,我想象的是 QuickCheck ,您将许多输入注入(inject)网络并检查输出。为了做这样的事情,我们需要一个函数:

evalNetwork :: Network a b -> [a] -> IO [b]

在这个答案即将结束时,我展示了 interpret* 之一的变体。具有类似类型的功能,用于特定类型的“网络”。

胡说八道关于 reactive-banana网络类型

这样的功能与 reactive-banana 中使用的“整个网络”的实际类型不兼容。 .对比涉及网络的实际函数的类型:
compile :: (forall t. Frameworks t => Moment t ()) -> IO EventNetwork

所以任何网络的类型都是 forall t. Frameworks t => Moment t () .没有类型变量;没有输入或输出。同样, EventNetwork类型没有参数。这告诉我们所有的输入和输出都是通过 IO 中的副作用处理的。 .这也意味着实际上不可能有类似的功能
interpret? :: EventNetwork -> [a] -> IO [b]

因为什么会 ab是?

这是 reactive-banana 设计的一个重要方面.例如,它使编写与命令式 GUI 框架的绑定(bind)变得容易。 reactive-banana 的魔力就是将所有副作用改组,正如文档所说,“一个单一的、巨大的回调函数”。

此外,事件网络通常与 GUI 本身密切相关。考虑 Arithmetic example , 其中 bInput1bInput2都是使用实际输入小部件构建的,并且输出绑定(bind)到 output ,另一个小部件。

可以像在其他语言中一样使用“模拟”技术来构建测试工具。您可以将实际的 GUI 绑定(bind)替换为类似于 pipes-concurrency 的绑定(bind)。 .我没有听说有人这样做。

如何进行单元测试:抽象出逻辑

更好的是,您可以并且应该在单独的函数中编写尽可能多的程序逻辑。如果您有两个输入,类型为 inAinB , 和一个 out 类型的输出,也许你可以写一个像
logic :: Event t inA -> Event t inB -> Behavior t out

这几乎是与 interpretFrameworks 一起使用的正确类型:
interpretFrameworks :: (forall t. Event t a -> Event t b) ->
[a] -> IO [[b]]

您可以结合两个输入 Event使用 split (或者更确切地说,将输入分成 Event 所需的两个 logic )。现在您将拥有 logic' :: Event t (Either inA inB) -> Behavior t out .

您有点难以转换输出 BehaviorEvent .在 0.7 版中, changes Reactive.Banana.Frameworks中的函数有类型 Frameworks t => Behavior t a -> Moment t (Event t a) ,您可以用它来解开 Behavior ,尽管您必须在 Moment 中执行此操作单子(monad)。然而,在 0.8 版中, a被包装为 Future a , 其中 Future是未导出的类型。 (有一个 issue on Github re exporting Future 。)

解开 Behavior 的最简单方法可能只是重新实现 interpretFrameworks与适当的类型。 (注意它返回一个包含初始值和后续值列表的元组。)即使 Future没有导出,可以使用它的 Functor实例:
interpretFrameworks' :: (forall t. Event t a -> Behavior t b) 
-> [a] -> IO (b, [[b]])
interpretFrameworks' f xs = do
output <- newIORef []
init <- newIORef undefined
(addHandler, runHandlers) <- newAddHandler
network <- compile $ do
e <- fromAddHandler addHandler
o <- changes $ f e
i <- initial $ f e
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)

这应该可以解决问题。

与其他 FRP 框架的比较

将此与其他框架进行对比,例如 Gabriel Gonzalez 的 mvc 或 Ertugrul Söylemez 的 netwire . mvc要求您将程序逻辑编写为有状态但其他方面纯的 Pipe a b (State s) () , 和 netwire网络的类型为 Wire s e m a b ;在这两种情况下,类型 ab公开网络的输入和输出。这使您可以轻松测试,但排除了 reactive-banana 提供的“内联”GUI 绑定(bind)。 .这是一个权衡。

关于haskell - 在 react 香蕉中进行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27216295/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com