一个单元如何测试基于过程或者事件的代码部分

时间:2020-03-05 18:56:10  来源:igfitidea点击:

通过此演示文稿和网站上的其他评论,我相信我需要学习单元测试。我也意识到关于这里的单元测试存在很多问题。每次我考虑应该如何在当前正在处理的应用程序中完成操作时,我都会感到困惑。这是一个xulrunner应用程序应用程序,当用户单击此处时,很多逻辑都是基于事件的,此操作便会发生。

我经常看到的测试示例是测试类,它们实例化一个对象,为其提供模拟数据,然后再检查该对象的属性。这对我来说很有意义,但是非面向对象的组件又如何呢?

这个家伙提到,在大多数测试框架中,基于GUI的单元测试都是困难的,也许就是问题所在。上面链接的演示文稿提到,每个测试一次只能涉及一个类,每次只能涉及一种方法。这似乎排除了我要尝试做的事情。

那么问题是一个单元如何测试过程或者基于事件的代码?提供指向好的文档的链接,或者自己解释。

附带说明一下,我还面临一个挑战,那就是没有找到一个用于测试xulrunner应用程序的测试框架,似乎该工具尚未开发。我想这比我了解概念,编写可测试的代码,应用单元测试还要外围。

解决方案

回答

问题在于"基于事件的编程"将太多的逻辑链接到事件。设计这种系统的方式是,应该有一个引发事件的子系统(我们可以编写测试以确保按照正确的顺序引发这些事件)。并且应该有另一个子系统仅处理例如表单状态的管理。我们可以编写一个单元测试,以验证给定正确的输入(即引发事件)是否会将表单状态设置为正确的值。

除此之外,从组件1引发并调用组件2上的行为的实际事件处理程序仅仅是集成测试,可以由质量检查人员手动完成。

回答

首先,我将测试如下事件:

private bool fired;

private void HandlesEvent(object sender, EventArgs e)
{
    fired = true;
 } 

public void Test()
{
   class.FireEvent += HandlesEvent;
   class.PErformEventFiringAction(null, null);

   Assert.IsTrue(fired);
}

然后我发现了RhinoMocks。
RhinoMocks是一个框架,可以创建模拟对象,并且还可以处理事件测试。它也可能对程序测试很方便。

回答

我发现对过程代码有用的一种方法是使用TextTest。它与单元测试无关,但是可以进行自动回归测试。想法是让应用程序编写日志,然后使用texttest比较更改前后的日志。

回答

单元测试的思想是在每次测试中测试一小段代码。在基于事件的系统中,我们可以执行的一种单元测试形式是测试事件处理程序如何响应各种事件。因此,单元测试可能会将程序的一个方面设置为特定状态,然后直接调用事件侦听器方法,最后测试程序的后续状态。

如果计划对基于事件的系统进行单元测试,那么使用依赖项注入模式将使自己的生活变得更加轻松,并且理想情况下会一路走来并使用控制反转(请参见http://martinfowler.com) /articles/injection.html和http://msdn.microsoft.com/zh-cn/library/aa973811.aspx了解这些模式的详细信息)

(感谢pc1oad1etter指出我弄乱了链接)

回答

请参阅经常链接的"有效使用旧版代码"。请参阅标题为"我的应用程序是所有API调用"和"我的项目不是面向对象的。如何进行安全更改?"部分。

在C / C ++世界中(根据我的经验),实践中最好的解决方案是使用链接器" seam",并针对被测试函数调用的所有函数,针对测试double进行链接。这样,我们无需更改任何旧版代码,但仍可以单独对其进行测试。

回答

在这里回答了我自己的问题,但是我遇到了一篇文章,解释了该问题,并完成了一个简单示例-敏捷用户界面开发的演练。代码和图像很棒,下面的代码片段展示了这个想法:

Agile gurus such as Kent Beck and
  David Astels suggest building the GUI
  by keeping the view objects very thin,
  and testing the layers "below the
  surface." This "smart object/thin
  view" model is analogous to the
  familiar document-view and
  client-server paradigms, but applies
  to the development of individual GUI
  elements. Separation of the content
  and presentation improves the design
  of the code, making it more modular
  and testable. Each component of the
  user interface is implemented as a
  smart object, containing the
  application behavior that should be
  tested, but no GUI presentation code.
  Each smart object has a corresponding
  thin view class containing only
  generic GUI behavior. With this design
  model, GUI building becomes amenable
  to TDD.

回答

问题并未说明我们选择的编程语言,但是我的问题是Cso,我将以使用它为例。但是,这只是对Gilligans答案的改进,它使用匿名委托内联测试代码。我全力支持使测试尽可能易读,对我而言,这意味着测试方法中的所有测试代码。

// Arrange
var car = new Car();
string changedPropertyName = "";
car.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
                        {
                           if (sender == car) 
                                  changedPropertyName = e.PropertyName;
                        };

// Act
car.Model = "Volvo";

// Assert 
Assert.AreEqual("Model", changedPropertyName, 
    "The notification of a property change was not fired correctly.");

我在这里测试的类实现了INotifyPropertyChanged接口,因此,每当属性值更改时,都将引发NotifyPropertyChanged事件。