一个单元如何测试程序或基于事件的代码段

时间:2008-09-16 14:41:50

标签: unit-testing

我从this presentation和网站上的其他评论中确信我需要学习单元测试。我也意识到有很多关于单元测试的问题。每当我去考虑如何在我正在进行的应用程序中完成它时,我就会感到困惑。它是一个xulrunner应用程序,很多逻辑都是基于事件的 - 当用户点击此处时,就会发生此操作。

我经常看到的用于测试的示例是测试类 - 它们实例化一个对象,给它模拟数据,然后检查对象的属性。这对我来说很有意义 - 但是那些非面向对象的作品呢?

This guy mentioned基于GUI的单元测试在大多数测试框架中都很难,也许这就是问题所在。上面链接的演示文稿提到每个测试应该只触及一个类,一次一个方法。这似乎排除了我想要做的事情。

所以问题 - 一个单元如何测试程序或基于事件的代码?提供良好文档的链接,或自己解释。

另外,我还面临着一个挑战,即没有找到一个测试框架来设置测试xulrunner应用程序 - 似乎这些工具还没有开发出来。我想这比我理解概念,编写可测试代码,应用单元测试更具外围性。

7 个答案:

答案 0 :(得分:5)

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

如果您计划对基于事件的系统进行单元测试,那么如果您使用依赖注入模式,那么您将使自己的生活变得更加轻松,理想情况下,它将全面使用并使用控制反转(请参阅{{3} }和http://martinfowler.com/articles/injection.html了解这些模式的详细信息)

(感谢pc1oad1etter指出我搞砸了链接)

答案 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是一个创建模拟对象的框架,它还处理事件测试。它也可以用于您的程序测试。

答案 2 :(得分:2)

在这里回答我自己的问题,但我偶然发现了一篇解释问题的文章,并简要介绍了一个简单的例子 - Agile User Interface Development。代码和图像都很棒,这里有一个显示这个想法的片段:

  

敏捷大师,如Kent Beck和   David Astels建议构建GUI   通过保持视图对象非常薄,   并测试“下面的层”   表面。“这个”智能对象/瘦   观点“模型类似于   熟悉的文档视图和   客户端 - 服务器范例,但适用   个人GUI的发展   元素。分离内容   和演示改进了设计   代码,使其更模块化   和可测试的。每个组成部分   用户界面实现为   智能对象,包含   应该是应用程序行为   测试,但没有GUI演示代码。   每个智能对象都有一个对应的   仅包含瘦视图类   通用GUI行为。有了这个设计   模型,GUI构建变得顺从   TDD。

答案 3 :(得分:1)

问题是“基于事件的编程”与事件的逻辑联系太多。应该设计这样一个系统的方式是应该有一个子系统来引发事件(你可以编写测试来确保以正确的顺序引发这些事件)。应该有另一个子系统只处理管理,比如表单的状态。您可以编写一个单元测试来验证给定正确的输入(即正在引发的事件),将表单状态设置为正确的值。

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

答案 4 :(得分:1)

你的问题没有说明你选择的编程语言,但我的是C#所以我会举例说明。然而,这只是对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事件。

答案 5 :(得分:0)

我发现一种对程序代码有用的方法是使用TextTest。它不是单元测试,而是帮助您进行自动化回归测试。我们的想法是让您的应用程序编写日志,然后使用texttest比较更改之前和之后的日志。

答案 6 :(得分:0)

查看经常链接的Working Effectively with Legacy Code。请参阅标题为“我的应用程序是所有API调用”和“我的项目不是面向对象的部分。如何进行安全更改?”部分。

在C / C ++世界中(我的经验),实践中最好的解决方案是使用链接器“seam”并链接测试双精度,以便测试被测函数调用的所有函数。这样您就不会更改任何遗留代码,但您仍然可以单独测试它。