Description使用组合模式描写叙述一个測试树。组合模式中全部元素都是Composite对象。

Description有成员变量private final ArrayList<Description>fChildren= newArrayList<Description>(); //无元素

保存其子结点。fChildren非空,所以不论什么子结点都是一个Composite,可是this. getChildren().size()为0的结点,其实就是叶子。

測试树

一颗測试树Description,有诸多Description构成。每个Description包括的数据:

privatefinal ArrayList<Description> fChildren= newArrayList<Description>(); //无元素

privatefinal String fDisplayName;

privatefinal Annotation[] fAnnotations;

叶子结点有:一个被測试的方法(atomic/ a single test),Description类中定义的的两个命名常量EMPTY(名字为"No Tests")和TEST_MECHANISM(名字为"Test mechanism")

一般元素/Composite,重点是fChildren的构造。一个单元測试类,其Description的子结点包含全部@test修饰的方法(不包含@Before等修饰的方法);一个成组測试类的子结点包含几个单元測试类。比如有Unit1、Unit2、Unit3,而SuiteUnit将Unit2、Unit3组成一组。

  1. package units;
  2. import static tool.Print.*;
  3. import org.junit.*;//各种标注
  4.  
  5. public class Unit1{
  6. public Unit1() { }
  7. @Before public void setUp(){ }
  8. @After public void tearDown(){ }
  9. @Test public void m1(){
  10. pln("Unit1.m1()");
  11. }
  12. @Test @Ignore public void m2(){
  13. pln("Unit1.m2()");
  14. }
  15. @Test public void m3(){
  16. pln("Unit1.m3()");
  17. }
  18. }
  1. package units;
  2. public class Unit2 {
  3. @org.junit.Test
  4. public void test2() {
  5. System.out.println("Unit2.test2()");
  6. }
  7. }
  8. package units;
  9. public class Unit3 {
  10.     @org.junit.Test
  11.     public void testSth() {<span style="white-space:pre"> </span>
  12.         System.out.println("Unit3.testSth()");
  13.     }
  14. }

SuiteUnit 的代码:

  1. package units;
  2. import org.junit.runner.RunWith;
  3. import org.junit.runners.Suite;
  4. @RunWith(Suite.class)
  5. @Suite.SuiteClasses({
  6. Unit2.class,
  7. Unit3.class,
  8. })
  9. public class SuiteUnit {}

先看一个样例,打印測试 Request.classes(Unit1.class,SuiteUnit.class)时的測试树。

  1. package demo;
  2. import static tool.Print.*;
  3. import units.Unit1;
  4. import units.SuiteUnit;
  5. import org.junit.runner.Description;
  6. import org.junit.runner.Request;
  7. import org.junit.runner.Runner;
  8. import java.util.regex.Matcher;
  9. import java.util.regex.Pattern;
  10. /**
  11. *測试Description的各种使用方法
  12. * @author yqj2065
  13. */
  14. public class DescriptionDemo {
  15. public static void tree(){
  16. Request rqst = Request.classes(Unit1.class,SuiteUnit.class);
  17. Runner r=rqst.getRunner();
  18. Description descr = r.getDescription();
  19. String prefix = "";
  20. print(descr,prefix);
  21. pln( "the total number of atomic tests = "+descr.testCount() );//the total number of atomic tests.
  22. }
  1. public static void print(Description now,String prefix){
  2. pln(prefix+ now.getDisplayName() );
  3. if(now.isSuite()) {
  4. prefix+=" ";
  5. for (Description x : now.getChildren()){
  6. print(x,prefix);
  7. }
  8. }
  9. }
  10. public static void main(String... args) {
  11. tree();
  12. }
  13. }

输出:

null

  units.Unit1

    m1(units.Unit1)

    m2(units.Unit1)

    m3(units.Unit1)

  units.SuiteUnit

    units.Unit2

      test2(units.Unit2)

    units.Unit3

      testSth(units.Unit3)

the total number of atomic tests = 5

此时的測试树有两个子结点:单元測试类units.Unit1(的Description)和成组測试类units.SuiteUnit。单元測试类的子结点都是叶子;而units.SuiteUnit的子结点为包括的单元測试类。

相关方法

String getDisplayName():返回fDisplayName。本描写叙述的用于打印的名字,普通情况下都採用类全名或JUnit的方法字符串如method(所属类的全名)

String getClassName()、String getMethodName():解析方法字符串,获得@Test修饰的方法相关的类全名和方法名;Class<?> getTestClass(),由getClassName()的返回值为參数name调用Class.forName(name);

 

ArrayList<Description> getChildren():返回fChildren。

void addChild(Description description)

isTest()(是否叶子)、isSuite()(是否组合):相互排斥的一对推断

isEmpty()

 

Collection<Annotation> getAnnotations():将fAnnotations数组形式的转换为Collection;本Description所相应元素前使用的标注

<T extends Annotation> T getAnnotation(Class<T> annotationType)。fAnnotations中是否含有annotationType。

 

@Override hashCode()、equals(Object obj)、toString();

 

组合模式中的Operation()的相应物为int testCount()。包括的叶子測试的总数。

构造器

Description有一个私有构造器。禁止客户类直接创建Description。

private Description(final String displayName, Annotation... annotations) {

fDisplayName= displayName;

fAnnotations= annotations;

}

然而,Description的构造,它提供了静态方法获得Description对象。

这些静态方法构造本Description的基本信息,不加入子结点。因而4个静态方法都是调用私有构造器,

public static Description createSuiteDescription(String name, Annotation... annotations)

public static Description createSuiteDescription(Class<?> testClass) 

public static Description createTestDescription(Class<?> clazz, String name, Annotation... annotations) {

return new Description(String.format("%s(%s)", name, clazz.getName()), annotations);

}

public static Description createTestDescription(Class<?

> clazz, String name) {

return createTestDescription(clazz, name, new Annotation[0]);

}

当中String str = String.format("%s(%s)", "m1", "Class1");

str为m1(Class1),JUnit的方法字符串如method(所属类的全名)

DescriptionDemo中測试树是怎样构建的呢?ParentRunner<T>的代码

  1. @Override
  2. public Description getDescription() {
  3. Description description= Description.createSuiteDescription(getName(),
  4. getRunnerAnnotations());
  5. for (T child : getFilteredChildren())
  6. description.addChild(describeChild(child));
  7. return description;
  8. }

能够通过“调试文件”,跟踪查看。

【JUnit4.10源码分析】3.4 Description与測试树的更多相关文章

  1. 【JUnit4.10源码分析】6.1 排序和过滤

    abstract class ParentRunner<T> extends Runner implements Filterable,Sortable 本节介绍排序和过滤. (尽管JUn ...

  2. 【JUnit4.10源码分析】5 Statement

    假设要评选JUnit中最最重要的类型.或者说核心,无疑是org.junit.runners.model.Statement.Runner等类型看起来热闹而已. package org.junit.ru ...

  3. 【JUnit4.10源码分析】5.2 Rule

    标注@Rule TestRule是一个工厂方法模式中的Creator角色--声明工厂方法. package org.junit.rules; import org.junit.runner.Descr ...

  4. JUnit4.12 源码分析之TestClass

    1. TestClass // 源码:org.junit.runners.model.TestClass // 该方法主要提供方法校验和注解搜索 public class TestClass impl ...

  5. 10.源码分析---SOFARPC内置链路追踪SOFATRACER是怎么做的?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

  6. JUnit4.12 源码分析之Statement

    1. Statement 抽象类Statement作为命令模式的Command,只有一个方法 各种Runner作为命令模式中的Invoker,将发出各种Statement,来表示它们运行JUnit测试 ...

  7. JUnit4.12 源码分析(二)之TestRule

    1. TestRule TestRule和@Before,@After,@BeforeClass,@AfterClass功能类似,但是更加强大; JUnit 识别TestRule的两种方式: 方法级别 ...

  8. 11.源码分析---SOFARPC数据透传是实现的?

    先把栗子放上,让大家方便测试用: Service端 public static void main(String[] args) { ServerConfig serverConfig = new S ...

  9. 12.源码分析—如何为SOFARPC写一个序列化?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

随机推荐

  1. JavaScript字符串数组拼接的性能测试及优化方法

    传统上,字符串连接一直是js中性能最低的操作之一. var text="Hello"; text+=" World!"; 早期浏览器没有对这种运算进行优化.由于 ...

  2. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  3. 编写和执行C#代码的插件:CS-Script for Notepad++

    这个插件可以方便得让您在Notepad++编辑器中编辑和执行C#代码(脚本).它具备通用的C#智能感知和项目任务管理功能,方式非常类似于MS Visual Studio.除了这一点,它提供了通用的调试 ...

  4. 【华为OJ平台练习题】求最大公共子串的个数和元素

    1.原题是求出最大公共子串的个数就可以 原理:利用二维矩阵排列的方式.将俩字符串进行比較 #include <iostream> #include <vector> using ...

  5. HDU OJ Digital Roots 题目1013

     /*Digital Roots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  6. 关于PHP写的投票网站之刷票风云

    最近学校导航站找我让我给他们做一个投票系统的网站,我一口答应了,他们只是要求不准刷票情况出现,我也一口答应了..我答应的太干脆了. 然后我便开始做这个网站,网站做出来没花太多时间,并且我是用IP来判断 ...

  7. Linux/Unix分配进程ID的方法以及源代码实现

    在Linux/Unix系统中.每一个进程都有一个非负整型表示的唯一进程ID.尽管是唯一的.可是进程的ID能够重用.当一个进程终止后,其进程ID就能够再次使用了. 大多数Linux/Unix系统採用延迟 ...

  8. 使用第三方控件DotNetBar来美化程序

    VS的控件确实有点丑陋,需要美化一下.我最先接触的就是DotNetBar,一直用它,一般都还稳定.下面简单地讲解一下使用方法 1. 下载破解版DotNetBar 10版本:http://www.cr1 ...

  9. maven下载源代码,解决中文注释为乱码的问题

    通过maven下载源代码,直接通过eclipse浏览源代码时,发现中文注释为乱码的问题.其实这个eclipse默认编码造成的问题.可以通过以下方法解决: 1.修改Eclipse中文本文件的默认编码:w ...

  10. 【Qt】splitter

    一段简单的切割窗体的程序: <span style="font-size:18px;">#include "mainwindow.h" #inclu ...