情况 B:
图 10. 自动判断并提取 TestSuite 流程图

当 suite 方法未在 test case 中定义时,JUnit 自动分析创建一个 test suite 。代码由 :
处进入 TestSuite(Class theclass) 方法为 TestSuite 类的构造方法,它能自动分析 theclass 所描述的类的内部有哪些方法需要测试,并加入到新构造的 TestSuite 中。代码如下:
图 11. TestSuite 函数代码

TestSuite 采用了Composite 设计模式。在该模式下,可以将 TestSuite 比作一棵树,树中可以包含子树(其它 TestSuite),也可以包含叶子 (TestCase),以此向下递归,直到底层全部落实到叶子为止。 JUnit 采用 Composite 模式维护测试集合的内部结构,使得所有分散的 TestCase 能够统一集中到一个或若干个 TestSuite 中,同类的 TestCase 在树中占据同等的位置,便于统一运行处理。另外,采用这种结构使测试集合获得了无限的扩充性,不需要重新构造测试集合,就能使新的 TestCase 不断加入到集合中。
在 TestSuite 类的代码中,可以找到:
此即为内部维护的“子树或树叶”的列表。
红框内的代码完成提取整个类继承体系上的测试方法的提取。循环语句由 Class 类型的实例 theClass 开始,逐级向父类的继承结构追溯,直到优异 Object 类,并将沿途各级父类中所有合法的 testXXX() 方法都加入到 TestSuite 中。
合法 testXXX 的判断工作由:
完成,实际上该方法还把判断成功的方法转化为 TestCase 对象,并加入到 TestSuite 中。代码如下图 :
图 12. addTestMethod 函数代码

首先通过 String name= m.getName(); 利用 Refection API 获得 Method 对象 m 的方法名,用于特征判断。然后通过方法
isTestMethod(Method m)
中的
来判别方法名是不是以字符串“ test ”开始。
而代码:
return;
用于在逐级追溯过程中,防止不同级别父类中的 testXXX() 方法重复加入 TestSuite 。
对于符合条件的 testXXX() 方法,addTestMethod 方法中用语句:
将 testXXX 方法转化为 TestCase,并加入到 TestSuite 。其中,addTest 方法接受 Test 接口类型的参数,其内部有 countTestCases 方法和 run 方法,该接口被 TestSuite 和 TestCase 同时实现。这是 Command 设计模式精神的体现,
Command 模式将调用操作的对象与如何实现该操作的对象解耦。在运行时,TestCase 或 TestSuite 被当作 Test 命令对象,可以像一般对象那样进行操作和扩展,也可以在实现 Composite 模式时将多个命令复合成一个命令。另外,增加新的命令十分容易,隔离了现有类的影响,今后,也可以与备忘录模式结合,实现 undo 等高级功能。
加入 TestSuite 的 TestCase 由 createTest(theClass, name) 方法创建,代码如下:
图 13. CreateTest 函数代码(查看大图)

TestSuite 和 TestCase 都有一个fName实例变量,是在其后的测试运行及结果返回阶段中该 Test 的唯一标识,对 TestCase 来说,一般也是要测试的方法名。在 createTest 方法中,测试方法被转化成一个 TestCase 实例,并通过:
用该方法名标识 TestCase 。其中,test 对象也是通过 Refection 机制,通过 theClass 构建的:
注意:theClass 是图 8 中 getTest 方法的 suiteClassName 字符串所构造的 Class 类实例,而后者其实是命令行参数传入的带测试类 Calculator,它继承了 TestCase 方法。因此,theClass 完全具备转化的条件。
至此整个流程的初始化完成。