用Delphi也有七八年了,但一直不知道怎样才能对窗体类进行测试(惭愧啊……),以前也曾经尝试过DUnit,但遗憾的是没有深入研究,近想好好研究一下单元测试DUnit,看了一些资料后才猛然发现:之所以一直觉得Delphi窗体类难以使用DUnit来测试,是因为没有使用MVC(Model,View,Control)之类的模式来实现软件,而是在RAD环境中直接使用了PME(Property,Method,Event)模式!

  下面我试着来总结一下Delphi之类的RAD工具出现后一般本地应用软件(Windows桌面应用软件)的开发模式。注意,以下总结仅针对我所了解的国内使用Delphi的软件企业,国外的情况我不太了解,所以也不作评论^o^

  a)所有业务逻辑相关代码与界面控制代码均在窗体(Form)中实现。一般小范围内用的个人小工具软件或新手往往这样做,我也曾经历过这个阶段。这样做感觉为直接,看起来似乎也简单,其缺点是显而易见的:代码可能很混乱(几乎是一定的),不利于后续维护及改进。公司、团队级别开发的软件几乎不可能用这种模式。当然,对写了丢的那种代码,也没必要苛求了。

  b)模型(Model)部分抽出来,放到Data Module之类的独立模块中,但业务控制(Control)部分仍与窗体显示部分(View)混在一起,都直接放在Form中实现。我相信多数使用Delphi来开发软件的公司(尤其是做MIS/MRP/ERP系统的公司)都是采用这种模式。当然,可能很多时候也会将一些业务逻辑抽象成一个个的类,但大部分的代码还是将业务与界面混在一起,我想这也是Delphi拥有强大可视化组件库(包括原生与第三方)的一个副作用吧。

  c)使用MVC模式或其变体。我想,用Delphi开发软件,还能使用MVC模式的公司恐怕凤毛麟角吧?!这倒不是说MVC模式不适合Delphi,而是用Delphi开发软件,PME (Property,Method,Event) 似乎是一种为直接自然的模式。

  以上三种模式只是从宏观角度上来观察而得到的一种粗粒度的划分,实际情况可能要复杂得多:有可能部分业务代码与模型部分混在一起,另一部分则放在界面里;也可能业务逻辑中却混杂了大量控制界面的代码;不好的是在模型部分混杂了界面的控制代码!

  如果我们用DUnit来对这三种模式的程序进行单元测试,那么分别会是怎样的情形呢?

  a)DUnit在此种情况下几乎难以使用。由于界面控制与业务逻辑代码混杂在一起,导致很难用DUnit写测试代码:多数事件/函数不是功能单一的界面控制或业务逻辑代码,而且往往有很多业务代码是作为窗体(Form)或类的内部代码而存在的,用DUnit也只能测试界面是否达到某些条件,这样的测试其实意义不大。

  b)DUnit可对模型(Model)部分进行单元测试,其他业务及界面部分要看情况而定:对于逻辑单一,条理清楚的类及函数,用DUnit测试肯定没问题,但对于那种混杂了业务逻辑和界面控制代码的窗体(Form)恐怕很难用DUnit测试了(与a类似)。

  c)多数类及函数都可以用DUnit进行单元测试,但复杂的控制(Control)类用DUnit可能也不好测试,尤其是涉及界面绘制及数据库组件的部分更难测试。一个更好的方法是使用改进的MVC模式,即将复杂的控制(Control)类进一步细分为界面控制、业务逻辑控制等部分,细分后写单元测试会容易很多。

  从上面的粗略分析可以看出,如果不使用类似MVC之类的模式来将界面控制与业务逻辑划分清楚,那么使用DUnit测试根本不现实。我想,这也是大多数用Delphi的软件企业不用或很少用DUnit测试的主要原因吧。

  用了好几年的Delphi,到现在才算有了点感悟,真是……更郁闷的是,Delphi已经日薄西山,恐怕我要被迫转到其他开发工具了,好在思想上的感悟到哪儿都能用得着,这也算不幸中的万幸了。