【JUnit4.10源码分析】3.4 Description与測试树
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组成一组。
package units;
import static tool.Print.*;
import org.junit.*;//各种标注 public class Unit1{
public Unit1() { }
@Before public void setUp(){ }
@After public void tearDown(){ }
@Test public void m1(){
pln("Unit1.m1()");
}
@Test @Ignore public void m2(){
pln("Unit1.m2()");
}
@Test public void m3(){
pln("Unit1.m3()");
}
}
package units;
public class Unit2 {
@org.junit.Test
public void test2() {
System.out.println("Unit2.test2()");
}
}
package units;
public class Unit3 {
@org.junit.Test
public void testSth() {<span style="white-space:pre"> </span>
System.out.println("Unit3.testSth()");
}
}
SuiteUnit 的代码:
package units;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
Unit2.class,
Unit3.class,
})
public class SuiteUnit {}
先看一个样例,打印測试 Request.classes(Unit1.class,SuiteUnit.class)时的測试树。
package demo;
import static tool.Print.*;
import units.Unit1;
import units.SuiteUnit;
import org.junit.runner.Description;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*測试Description的各种使用方法
* @author yqj2065
*/
public class DescriptionDemo {
public static void tree(){
Request rqst = Request.classes(Unit1.class,SuiteUnit.class);
Runner r=rqst.getRunner();
Description descr = r.getDescription();
String prefix = "";
print(descr,prefix);
pln( "the total number of atomic tests = "+descr.testCount() );//the total number of atomic tests.
}
public static void print(Description now,String prefix){
pln(prefix+ now.getDisplayName() );
if(now.isSuite()) {
prefix+=" ";
for (Description x : now.getChildren()){
print(x,prefix);
}
}
}
public static void main(String... args) {
tree();
}
}
输出:
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>的代码
@Override
public Description getDescription() {
Description description= Description.createSuiteDescription(getName(),
getRunnerAnnotations());
for (T child : getFilteredChildren())
description.addChild(describeChild(child));
return description;
}
能够通过“调试文件”,跟踪查看。
【JUnit4.10源码分析】3.4 Description与測试树的更多相关文章
- 【JUnit4.10源码分析】6.1 排序和过滤
abstract class ParentRunner<T> extends Runner implements Filterable,Sortable 本节介绍排序和过滤. (尽管JUn ...
- 【JUnit4.10源码分析】5 Statement
假设要评选JUnit中最最重要的类型.或者说核心,无疑是org.junit.runners.model.Statement.Runner等类型看起来热闹而已. package org.junit.ru ...
- 【JUnit4.10源码分析】5.2 Rule
标注@Rule TestRule是一个工厂方法模式中的Creator角色--声明工厂方法. package org.junit.rules; import org.junit.runner.Descr ...
- JUnit4.12 源码分析之TestClass
1. TestClass // 源码:org.junit.runners.model.TestClass // 该方法主要提供方法校验和注解搜索 public class TestClass impl ...
- 10.源码分析---SOFARPC内置链路追踪SOFATRACER是怎么做的?
SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...
- JUnit4.12 源码分析之Statement
1. Statement 抽象类Statement作为命令模式的Command,只有一个方法 各种Runner作为命令模式中的Invoker,将发出各种Statement,来表示它们运行JUnit测试 ...
- JUnit4.12 源码分析(二)之TestRule
1. TestRule TestRule和@Before,@After,@BeforeClass,@AfterClass功能类似,但是更加强大; JUnit 识别TestRule的两种方式: 方法级别 ...
- 11.源码分析---SOFARPC数据透传是实现的?
先把栗子放上,让大家方便测试用: Service端 public static void main(String[] args) { ServerConfig serverConfig = new S ...
- 12.源码分析—如何为SOFARPC写一个序列化?
SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...
随机推荐
- Spring Boot应用连接数据库MySQL、及一个简单的demo
一.修改pom.xml文件 在项目的pom.xml文件上增加如下代码,添加依赖文件. <dependency> <groupId>mysql</groupId> & ...
- Android之TelephonyManager
在Android平台中,通过TelephonyManager可以访问与手机通讯相关的信息,比如设备信息.网络信息及SIM卡信息,同时还可以监听电话的相关状态.下面我们通过几个方面来说明Android平 ...
- linux CentOS7 安装scala
1.打开terminal ,进入当前用户路径: cd /home/sks 2.下载Scala2.11 wget https://downloads.lightbend.com/scala/2.11.8 ...
- Dijkstra(迪杰斯特拉)算法求解最短路径
过程 首先需要记录每个点到原点的距离,这个距离会在每一轮遍历的过程中刷新.每一个节点到原点的最短路径是其上一个节点(前驱节点)到原点的最短路径加上前驱节点到该节点的距离.以这个原则,经过N轮计算就能得 ...
- jquery制作一个简单的轮播
效果图: 演示地址: http://ae6623.cn/demo/slider/index.html 思路: 利用css的定位属性 left 进行调整图片的显示,每次点击上一页下一页按钮的时候,-图片 ...
- CSS半透明兼容写法
filter: Alpha(opacity=10); -moz-opacity:0.1; opacity:0.1; 例如: background:#A5CD40; filter: Alpha(opac ...
- OC 创建单例
static BlockBackground *_sharedInstance = nil; + (BlockBackground*)sharedInstance { if (_sharedInsta ...
- vlc的应用之七:用vlc做单播,组播及点播服务器【转】
vlc的应用之七:用vlc做单播,组播及点播服务器 2009-05-31 15:56:03 标签:vod multicast vlc vlm unicast http://ubuntu.mezo ...
- WPF使用DEV之TreeListControl---加入复选框
1.绑定的Class中加入一个Bool类型的属性 2. 该属性无需初始赋值,你执行就可以看到如图: Bool类型数据自己主动变成了复选框 watermark/2/text/aHR0cDovL2Js ...
- 【C++系列小结】面向过程的编程风格
前言 编程语言有面向过程和面向对象之分,因此编程风格也有所谓的面向过程的编程和面向对象的编程,并且语言的性质不会限制编程的风格. 这里主要说一以下向过程的编程. "面向过程"(Pr ...