abstract class ParentRunner<T> extends Runner implements Filterable,Sortable

本节介绍排序和过滤。

(尽管JUnit4.8.2源码分析-6.1 排序和过滤中演示了客户使用排序和过滤的方式,也有些不明确其设计意图。可是。先读懂源码为妙。说不定看着看着就明确了。

org.junit.runner.manipulation包

排序和过滤的相关类型。在org.junit.runner.manipulation包中。Sortable和Filterable是两个依赖注入接口。而Sorter和Filter的apply是注入方法

1.比如Sortable是一个函数接口。yqj2065认为Sortable.sort(Sorter)不如叫Sortable.setSorter(Sorter)

package org.junit.runner.manipulation;
public interface Sortable {
public void sort(Sorter sorter);
}

2.Filterable类似,定义了void filter(Filter filter) throws NoTestsRemainException;

3.NoTestsRemainException抱怨filter 将全部的測试都过滤掉了。

4.Sorter implements Comparator<Description>。我们知道。java.util.Comparator接口是一个策略类,定义了int compare(T o1, T o2)方法。而Sorter是一个简单的代理模式的Proxy角色。

通过构造器注入的方式Sorter(Comparator<Description>comparator)初始化realSubject角色。測试程序猿能够定义自己的排序器。并且。Sorter应用Null
Object模式
,定义了NULL静态内部子类。

package org.junit.runner.manipulation;
import java.util.Comparator;
import org.junit.runner.Description;
public class Sorter implements Comparator<Description> {
/**
* NULL is a <code>Sorter</code> that leaves elements in an undefined order
*/
public static Sorter NULL= new Sorter(new Comparator<Description>() {
public int compare(Description o1, Description o2) {
return 0;
}});
	public void apply(Object object) {
if (object instanceof Sortable) {
Sortable sortable = (Sortable) object;
sortable.sort(this);
}
} }

Sorter的方法apply(Object object),将this应用于Object 身上。

5.Filter是一个抽象类。当须要过滤某些測试时。測试程序猿要定义自己的过滤器。

Filter应用Null Object模式,定义了ALL静态内部子类。静态工厂生成public static Filter matchMethodDescription(final Description desiredDescription)。而public
Filter intersect(final Filter second)同意多个Filter串接。

依照上述几个样例,我们能够写出自己的过滤器。

package sortFilter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.runner.Description;
import org.junit.runner.manipulation.Filter; /**
*排除指定的方法。
* @author yqj2065
*/
public class MethodNameFilter extends Filter {
private final Set<String> excludedMethods = new HashSet<>(); public MethodNameFilter(String... excludedMethods) {
this.excludedMethods.addAll(Arrays.asList(excludedMethods));
} @Override
public boolean shouldRun(Description description) {
String methodName = description.getMethodName();
return !excludedMethods.contains(methodName);
} @Override
public String describe() {
return this.getClass().getSimpleName() + "-excluded methods: "
+ excludedMethods;
}
}

Unit4有測试方法a() 、@Ignore b() 、c() 和d()等,

package demo;

import static tool.Print.*;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
import sortFilter.MethodNameFilter;
import units.Unit4; /**
*
* @author yqj2065
*/
public class FilterDemo { public static void main(String... args) {
try {
BlockJUnit4ClassRunner runner = null;
try {
runner = new BlockJUnit4ClassRunner(Unit4.class);
} catch (InitializationError e) {
}
runner.filter(new MethodNameFilter("a","b","c", "d"));//排除全部
runner.run(new RunNotifier());
} catch (NoTestsRemainException ex) {
pln(ex);
}
}
}

输出:org.junit.runner.manipulation.NoTestsRemainException

保留@Ignore b(),尽管没有运行測试。可是不抛出异常。

ParentRunner<T>与排序和过滤

ParentRunner implements Filterable,Sortable

注意到:JUnit4.8.2中ParentRunner 有域Filter fFilter= null;而JUnit4.10不再有该域。而是以过滤后的private List<T> fFilteredChildren= null代替。

因为ParentRunner<T>的类型參数T,代表其某种孩子的类型。BlockJUnit4ClassRunner的T为FrameworkMethod。Suite的T为Runner

在ParentRunner中统一地处理T显得比較复杂。并且JUnit4.10代码变化较大。

过滤相关的代码

getFilteredChildren()惰性初始化域fFilteredChildren,当中调用getChildren()由子类给出实现,返回List<T>。

@Override filter(Filter filter),就须要差别对待FrameworkMethod和Runner

1.JUnit没有使用instanceof。而是利用abstract Description describeChild(T child),无论T是FrameworkMethod还是Runner。总能够构造(FrameworkMethod)或获得(Runner)一个Description返回值;

2.而Filter定义的public abstract boolean shouldRun(Description description),能够统一处理两者。

3.因而。ParentRunner定义了boolean shouldRun(Filter filter, T each) ,调用前者。

可是,从实际參数看,filter.shouldRun(FrameworkMethod的Description )才进行比較和过滤;而filter.shouldRun(Runner.getDescription ),总是返回true、

于是,第5行代码if (shouldRun(filter, each))出现有意思的情况。

对于FrameworkMethod each。假设shouldRun,其代码应该为

try {

//

} catch (NoTestsRemainException e) {

iter.remove();

}

由于filter.apply(FrameworkMethod )肯定直接return;而shouldRun推断不通过,就意味着iter.remove();在fFilteredChildren中删除该方法;

对于Runner each。总是shouldRun,并且运行filter.apply(each);从而调用到each.filter(filter);能够看出。假设没有FrameworkMethod ,能够直接运行each.filter(filter);可是如今不得不打乒乓球。利用filter.apply(each)排除掉FrameworkMethod

    private List<T> fFilteredChildren= null;
public void filter(Filter filter) throws NoTestsRemainException {
for (Iterator<T> iter = getFilteredChildren().iterator(); iter.hasNext(); ) {
T each = iter.next();
if (shouldRun(filter, each))
try {
filter.apply(each);
} catch (NoTestsRemainException e) {
iter.remove();
}
else
iter.remove();
}
if (getFilteredChildren().isEmpty()) {
throw new NoTestsRemainException();
}
}
private List<T> getFilteredChildren() {
if (fFilteredChildren == null)
fFilteredChildren = new ArrayList<T>(getChildren());
return fFilteredChildren;
}
private boolean shouldRun(Filter filter, T each) {
return filter.shouldRun(describeChild(each));
}

作为比較,JUnit4.8.2的相关代码列在以下,有时间再看。

    private Filter fFilter= null;
public void filter(Filter filter) throws NoTestsRemainException {
fFilter= filter;
for (T each : getChildren())
if (shouldRun(each))
return;
throw new NoTestsRemainException();
} private List<T> getFilteredChildren() {
ArrayList<T> filtered= new ArrayList<T>();
for (T each : getChildren())
if (shouldRun(each))
try {
filterChild(each);
sortChild(each);
filtered.add(each);
} catch (NoTestsRemainException e) {
// don't add it
}
Collections.sort(filtered, comparator());
return filtered;
} private void filterChild(T child) throws NoTestsRemainException {
if (fFilter != null)
fFilter.apply(child);
} private boolean shouldRun(T each) {
return fFilter == null || fFilter.shouldRun(describeChild(each));
}

排序的非常easy。略。

最新文章

  1. wpf Webbrowser 乱码问题及弹窗被遮挡
  2. AOJ DSL_2_E Range Add Query (RAQ)
  3. matlab 调用VLfeat库开篇问题
  4. 再识C中的结构体
  5. mysql replication inside
  6. 常用js函数
  7. 控制器View的加载过程
  8. Ubuntu 下配置Samba 实现Linux和windows之间文件共享
  9. lua的前景??
  10. 笔记:Spring Cloud Hystrix Command属性
  11. ng-if ng-show ng-hide区别(面试题)
  12. 设置SSH免密码登录
  13. python小练习,利用dict,做一个简单的登录。
  14. 安装supset遇到的问题
  15. Spark学习之路 (二十七)图简介
  16. C#基础第九天-作业-储蓄账户(SavingAccount)和信用账户(CreditAccount)
  17. jmeter+maven 的简单使用 记录(Windows环境)
  18. java-- 的子类/父类构造方法 转
  19. 基于windowsphone7的控制ppt播放
  20. c# string 和 byte[]数组之间转换

热门文章

  1. bzoj1008 矩乘递推
  2. jquery with ajax
  3. 关于vscode的个人配置
  4. Ubuntu 15.10 安装比特币客户端
  5. python特有的协程
  6. hdu 1054(最小点覆盖集)
  7. 服务端指南 数据存储篇 | 聊聊 Redis 使用场景(转)
  8. 解决Unknown host &#39;d29vzk4ow07wi7.cloudfront.net&#39;. You may need to adjust the proxy settings in Gradle.
  9. React Native - 0序言
  10. tomcat中reloadable作用