单元测试随着agile的流行已经家喻户晓了,这正反映了软件的一个本质特征:软件是Man-Made的,而人是不可靠的。软件出错的高频率必然导致控制 间隔的缩短。我早是在编写matlab程序的时候独立的发现了单元测试的作用。因为matlab是弱类型的,横纵矢量也不区分,很容易犯错误,我为每 一个matlab函数编写了测试脚本,约定了命名规范为xxx_test.m, 在测试的时候通过 can_assert来做出判断而不是输出变量内容进行人工检查。 每次作了修改的时候,运行一下can_test_all.m自动搜索测试脚本并运行一遍。 后来xp出现了, 我也第一次听说了单元测试这回事,看来英雄所见略同吧 ^_^
   单元测试可以看作是对编译器的补充。编译器只能进行语法检查(形式),而单元测试可以进行语义检查(内容),它其实维护了程序的一个语义框架。如果单元测 试程序编写出来了,即使一行业务实现代码也没编写,我们手中也已经拥有了一笔宝贵的财富,因为程序的语义已经在某种意义下确定下来了。重构一般是在维护单 元测试不变的情况下进行的。即我们发现在维护语义不变量的情况下,系统具有相当的调整余地。
   坚持单元测试的另一个好处是它倾向于良好分离的模块,因为高内聚低耦合的模块才更容易进行测试。为了测试,我们会在不知不觉中在对象职责的分离上投注更多 的心力。在witrix平台中,虽然基于EasyMock提供了mock支持,在实际中却很少使用,因为模块功能一般很独立,不需要复杂的mock对象, 而对于一般的对象,eclipse有代码生成功能,可以非常轻易的生成简单的测试对象。
   虽然JUnit非常流行,我们的单元测试也是基于JUnit进行的,但是我们还是进行了一个简单的封装,将JUnit框架的特定要求与具体测试代码剥离开来。具体的,测试类从
   test.UnitTest继承,而不是从JUnit的TestCase继承。使用Debug.check()来做判断,而不是JUnit的assertEquals等。
   class MyTest extends UnitTest{
      public MyTest(String caseName){ super(caseName); }

      public void testMy(){
          MyObject my = new MyObject();
          Object value = myObject.myFunc();
          Debug.check(value.equals("aa"));
          // 可以同时提供一个出错消息
          Debug.check(value.equals("aa"),"myFunc return invalid : "+value);
      }

      public static void main(String[] args){
        // 不需要IDE或者其他外部的支持可以直接调用测试代码,将会自动输出运行时间等
        UnitTest.exec(new MyTest("testMy"));
      }
   }