代码之家  ›  专栏  ›  技术社区  ›  Arne

测试反应式异步代码的策略

  •  7
  • Arne  · 技术社区  · 15 年前

    我正在开发面向数据流的领域特定语言。为了简化,我们来看看操作。操作有许多命名参数,可以要求使用它们的当前状态来计算结果。

    为了决定一个操作何时应该产生一个结果,它得到一个决定,这个决定对从谁那里得到一个值的参数敏感。当这个决定决定被完成时,它使用观察者发出一个信号。

    访问器监听该信号,然后调用操作的结果方法,以便将其多路传输到其他操作的参数。

    到目前为止,这是一个很好的、完全分离的设计,可组合、可重用,并且,取决于所使用的特定的观察者,如您所希望的那样是异步的。

    现在我的问题是:我会的 开始根据此设计对实际测试进行编码。 但是有了异步观察器…

    • 我该如何知道整个信号和参数管道工作?
    • 我是否需要在等待信号时使用超时来表示信号是否已成功发出?
    • 我怎么能正式地 当然 如果我再等一会儿,信号就不会发出了(停止问题?;(-))
    • 我怎么能确定信号是因为 谁设置了参数,而不是另一个操作?很可能是因为我的测试来得早,在我设置参数导致决定发出信号之前看到了一个信号。

    目前,我想小的情况很容易测试,但一旦我想测试复杂的多对多-操作之间的情况,我必须求助于希望设计只是工作(tm)。

    编辑(1):

    让我们考虑下面的场景:

    假设一个操作A为操作b1、b2和b3提供了一个值,每个操作都有一个输入决策(每当更新任何参数时都会完成这个决策)。然后,让b1、b2和b3分别将它们的值提供给操作c的同一个参数(例如,将这些值聚合到一个查找表或类似的表中)。

    预期步骤如下:

    1. 表明它有一个新的价值(由于它的决定)
    2. 一段时间后,异步观测器将信号发送到任何已注册的
    3. 啊,一个注册的访问器。它的回调被调用,从而获取操作结果并将其多路传输到b1、b2和b3的参数。
    4. b1、b2和b3告知他们关于这一点的决定,这为观察者创造了三个新的信号。
    5. 一段时间后,异步观测器发送b1的信号,然后是b2,然后是b3。
    6. 每个信号导致一个存取器获取b1(2,3)的结果并将其输入c

    所以,我知道在这种情况下,我可以嘲笑C的决定,看它是否真的被告知了b1,b2和b3做了什么。问题是: 什么时候? 我检查这个安全吗?

    编辑(2):我的目标似乎更像是端到端测试,即将DSL的各个部分组合在一起,看看结果是否按照我期望的方式运行。

    编辑(3):事实证明我太过复杂了。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Andrew Anderson    15 年前

    您需要确保所有不同的组件都是接口连接的,然后一次测试一个特定的类,模拟出所有其他组件。

    注意:这个解释的前提是您使用的是依赖倒置的原则以及模拟库(如Rhino Mocks)。

    你说:

    决定什么时候应该执行操作 产生结果,得到决定 对哪个参数敏感 从谁那里得到了价值。当这 决定决定是否完成, 它使用观察者发出信号。

    存取器监听此信号 然后调用 多路复用的操作 其他操作的参数。

    这告诉我,你将建立一个操作,有一个模仿的意识形态。然后,您的单元测试可以以这样一种方式协调IDecision的行为,以执行操作可能必须处理的所有可能的场景。

    同样,您的访问器测试有一个模拟的idecision,它被设置为以现实的方式运行,这样您就可以独立地完全测试访问器类。它还可以有一个模拟操作,您可以测试访问器是否对模拟对象调用适当的方法以响应所需的刺激。

    总结 :单独测试每个类,使用所有其他部分的模拟对象来协调适当的行为。

        2
  •  1
  •   samjudson    15 年前

    我没有用过这个,但是我听说反应式框架可以用来将事件转换成LINQ语句——然后可以用它来实现简单的单元测试。

    我相信他们是如何对很多Silverlight代码进行单元测试的——事实上,反应框架是通过Silverlight工具包(system.reactive.dll)分发的。