资讯专栏INFORMATION COLUMN

Junit源码阅读(一)

Gilbertat / 873人阅读

摘要:是对测试样例的建模,用来组合多个测试样例,是中的核心内容。也是一个虚类,子类应该实现方法来决定对于是否运行。如下列代码所示组合了和,为运行时异常和断言错误屏蔽了不一致的方面,可以向上提供错误信息和样例信息。

Junit的工程结构

从上图可以清楚的看出Junit大致分为几个版块,接下来一一简略介绍这些版块的作用。

runner:定义了Junit模型中的许多基本概念,只要是一些虚类和接口,是整个Junit工程的基石

runners:提供了从注解中使用反射完成测试用例执行的实现

interval:提供了在Runner中许多虚类的默认实现,包括各类RunnerBuilder如基于注解提供Builder、各类Matchers、各类Request如类测试Request、方法测试Request。

rules:用于用户自定义扩展,规定对于不同statement的用户自定义行为

matchers:主要用于AssertThat方法,在4.4之后废弃

validator:从类、方法和域多个方面检查测试样例

experimental:一些测试特性

Runner中的基本概念

Runner:以Notifier为参数允许测试样例,运行过程中的Notifier负责监视测试过程

Request:负责记录测试样例的Description信息,同事负责提供对应的Runner。可以通过Computer结合指定或默认的RunnerBuilder来直接为一系列测试类统一提供Runner

Description:描述测试样例,使用Composite模式,组合多个样例

Result:记录异常和失败,内置一个Listener来实现与测试过程的同步,测试完成时count自增,有样例失败则加入Failure列表

Failure:将断言失败和抛出异常综合在同一个框架下,同时提供了Description的信息

Listener:监视测试过程,典型的观察者模式

Notifier:管理一系列Listener,保证线程安全

Filter:指定条件,只运行符合条件的测试样例,可以动态添加,为每次测试增加了灵活性

Runner中的依赖关系

JunitCore负责提供给用户统一的交互,从命令行运行测试样例。Notifier是一个虚类,子类需要实现如何通知Listener的方法,负责管理Listener集合,内部内置了一个静态的SafeNotifier,该类提供了一个run方法,来简单依次通知所有Listener,它用来实现在测试开始和失败出现的时候通知所有Listener。

Description是对测试样例的建模,用来组合多个测试样例,是Runner中的核心内容。

Filter也是一个虚类,子类应该实现shouldRun方法来决定对于Description是否运行。同时依然实现一个静态方法来提供什么都不过滤,以及一个判断原子描述是否等于期望描述的过滤器,对于非原子描述若其子描述均不等于期望描述则滤掉。如下列代码所示:

/**
     * Returns a {@code Filter} that only runs the single method described by
     * {@code desiredDescription}
     */
    public static Filter matchMethodDescription(final Description desiredDescription) {
        return new Filter() {
            @Override
            public boolean shouldRun(Description description) {
                if (description.isTest()) {
                    return desiredDescription.equals(description);
                }

                // explicitly check if any children want to run
                for (Description each : description.getChildren()) {
                    if (shouldRun(each)) {
                        return true;
                    }
                }
                return false;
            }

            @Override
            public String describe() {
                return String.format("Method %s", desiredDescription.getDisplayName());
            }
        };
    }

Failure组合了Description和Throwable,为运行时异常和断言错误屏蔽了不一致的方面,可以向上提供错误信息和样例信息。

Request负责提供具体的Runner来run对应的测试样例,同时是Filter作用的主体,对于Filter,会返回一个新的FilterRequest,代码如下:

package org.junit.internal.requests;

import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;

/**
 * A filtered {@link Request}.
 */
public final class FilterRequest extends Request {
    private final Request request;
    /*
     * We have to use the f prefix, because IntelliJ"s JUnit4IdeaTestRunner uses
     * reflection to access this field. See
     * https://github.com/junit-team/junit/issues/960
     */
    private final Filter fFilter;

    /**
     * Creates a filtered Request
     *
     * @param request a {@link Request} describing your Tests
     * @param filter {@link Filter} to apply to the Tests described in
     * request
     */
    public FilterRequest(Request request, Filter filter) {
        this.request = request;
        this.fFilter = filter;
    }

    @Override
    public Runner getRunner() {
        try {
            Runner runner = request.getRunner();
            fFilter.apply(runner);
            return runner;
        } catch (NoTestsRemainException e) {
            return new ErrorReportingRunner(Filter.class, new Exception(String
                    .format("No tests found matching %s from %s", fFilter
                            .describe(), request.toString())));
        }
    }
}
Runner中的JunitCore

JUnitCore使用外观模式(facade),对外提供一致的界面,同时支持运行JUnit 4或JUnit 3.8.x用例,通过命令行执行用例.首先它使用jUnitCommandLineParseResult解析外部参数,将默认的TextListener加入内置的Notifier。它所运行的Runner也是由jUnitCommandLineParseResult提供的,先行通过测试filter掉不需要的样例,最后调用Runner的run方法。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65435.html

相关文章

  • Junit源码阅读(六)之Junit中的设计模式

    摘要:前言在这次的博客中我们将着重于的许多集成性功能来讨论中的种种设计模式。装饰器模式装饰器模式是为了在原有功能上加入新功能,在中绝对属于使用最频繁架构中最核心的模式,等都是通过装饰器模式来完成扩展的。 前言 在这次的博客中我们将着重于Junit的许多集成性功能来讨论Junit中的种种设计模式。可以说Junit的实现本身就是GOF设计原则的范例教本,下面就让我们开始吧。 装饰器模式 装饰器...

    jlanglang 评论0 收藏0
  • Junit源码阅读(三)之精致的Validator

    摘要:前言在建立的过程中,往往需要对当前的测试样例和注解进行验证,比如检查测试类是否含有非静态内部类,测试类是否是的。的验证机制非常精致而优美,在本次博客中我们就主要来谈一谈机制的实现。首先在中定义三个默认的类,如下。 前言 在建立Runner的过程中,往往需要对当前的测试样例和注解进行验证,比如检查测试类是否含有非静态内部类,测试类是否是Public的。Junit的验证机制非常精致而优美...

    李世赞 评论0 收藏0
  • Junit源码阅读(五)

    摘要:的作用是包装从生成的逻辑,提供两种方案生成和。最后从生成也异常简单,也就是实现其方法返回该。 前言 尽管在第二次博客中我们讲述了Runner的运行机制,但是许多其他特性比如Filter是如何与运行流程结合却并不清楚。这次我们来回顾整理一下Junit的执行流程,给出各种特性生效的机理,并分析一些代码中精妙的地方。 Junit的执行流程 JUnitCore的RunMain方法,使用jUn...

    vpants 评论0 收藏0
  • Junit源码阅读(四)之自定义扩展

    摘要:前言上次的博客中我们着重介绍了的机制,这次我们将聚焦到自定义扩展上来。在很多情形下我们需要在测试过程中加入一些自定义的动作,这些就需要对进行包装,为此提供了以接口和为基础的扩展机制。 前言 上次的博客中我们着重介绍了Junit的Validator机制,这次我们将聚焦到自定义扩展Rule上来。在很多情形下我们需要在测试过程中加入一些自定义的动作,这些就需要对statement进行包装,...

    Little_XM 评论0 收藏0
  • Junit源码阅读(二)之样例运行的机制

    摘要:前言在上次的博客中我们提到了最终由以为参数执行测试样例,但并没有解释到底测试方法是如何被运行起来的,一些诸如之类的特性又到底是如何实现的呢。这次我们就集中深入的运行机制来探究样例是如何被运行的。使用拿到的直接运行方法。 前言 在上次的博客中我们提到了最终由Runner以Notifier为参数执行测试样例,但并没有解释到底测试方法是如何被运行起来的,一些诸如RunWith、RunAft...

    meteor199 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<