软件工程
第五次实验
实验序号:5
实验项目名称:软件测试工具的基本应用
1.项目添加 JUnit 库
2.修改项目源代码目录
3.JUnit 运行成功界面
4.再次运行测试,未通过测试 JUnit 运行失败界面
5.修改之后,运行成功。
实验总结:对于JUnit 这个软件很陌生,以前没有用到过,刚看到这个实验题目感觉很乏力。不过在认真看过老师给的网址之后,按照上面的步骤,竟然一步步做下来了。还是感谢老师给我们接触JUnit 软件的机会,以后很有可能会用到。
第二篇:junit详解
XP单元测试工具Junit源代码学习
谢慧强 xiehuiqiang@21cn.com
Package framework
Class & Interface Hierachy
Interface Test
主要方法
countTestCases:统计TestCases数目
run:运行测试并将结果返回到指定的TestResult中
Class Assert
首先,Assert提供的public方法都可以带或不带自己定义的提示,其次Assert中的Assert方法是protected的,这意外着Assert是一个静态类,它提供的方法都是Static的。
public方法:
assert:保留(deprecated)方法,判断一个条件是否为真
assertTrue:assert的替代方法,判断一个条件是否为真
assertEquals:用于判断实际值和期望值是否相同(Equals),可以是各种JAVA对象。
assertNotNull:判断一个对象是否不为空
assertNull:判断一个对象是否为空
assertSame:判断实际值和期望值是否为同一个对象(==),注意和assertEquals区分
fail:直接返回失败,抛出AssertionFailedError
private方法:
failNotEquals:主要用于assertEquals方法,调用fail返回失败提示 failNotSame:主要用于assertSame方法,调用fail返回失败提示
Class AssertionFailedError
AssertionFailedError是从Jdk提供Error类简单继承而来,主要方法如下:
public AssertionFailedError (String message) {
super (message);
}
Class Assert中比较失败都是抛出AssertionFailedError。
Interface Protectable
这个接口是使用了一种比较少见的用法。
在Interface本身只定义了一个方法
public abstract void protect() throws Throwable;
注意方法throws的是所有Error和Exception的祖先。通过这种定义可以保证运行的时候如果出现任何Error和Exception,都将被抛出而不会导致程序不能继续运行。
Portectable的接口没有被framework包中的任何类实现,它的使用在类TestResult中的run方法中。以下是run方法中代码:
protected void run(final TestCase test) {
startTest(test);
Protectable p= new Protectable() {
public void protect() throws Throwable {
test.runBare();
}
};
runProtected(test, p);
endTest(test);
}
这里实际是声明了一个Anonymous Classes,实现了Interface Portectable
Interface TestListener
TestListener的用途和它名称一样,用于监听。主要用于运行时刻监听,BaseRunner(所有运行类,如TestRunner)实现了这一接口。由于运行是通过TestResult来实现,只要调用TestResult.addListener就可以增加监听,TestResult会调用接口中相应的方法,具体见TestResult。
主要方法:
public
addError:增加错误,注意这里错误应该指测试程序本身的错误或者被测试程序错误,而不是测试失败
addFailure:增加一个测试失败,专用于AssertionFailedError的处理 endTest:结束测试
startTest:开始测试
Class TestCase
使用者最主要使用的类,继承Class Assert,实现Interface Test。主要方法 public
TestCase:创建本身,可以指定TestCase准备运行的测试方法名称,保存在私有属性fName。
countTestCases:返回TestCase数目,直接返回1
name:deprecated,建议使用getName,返回TestCase当前准备允许的测试方法的名称(私有属性fName)
run:运行TestCase,如果没有指定结果存储的TestResult,将调用createResu(lt方法。注意,TestCase与TestResult会有互相调用。整个运行流程如下:
1、TestCase.run 调用TestResult.run
2、TestResult.run 调用TestResult .StartTest
3、TestResult.run创建一个Anonymous类,实现接口Portectable
4、在Portectable. protect方法中调用TestCase .runBare
5、通过运行Portectable.runBare 调用runBare,通过Exception捕获增加错误及失败报告
runBare:不使用TestResult直接运行
runTest:运行测试,注意每调用runTest只运行当前fName指定的方法 getName:返回fName
setName:设置fName
protected
createResult:创建一个TestResult
setUp:在运行runTest前调用
tearDown:在运行runTest后调用
Class TestFailure
用于存放测试对比失败信息的类。主要为Class TestResult调用。主要属性
protected Test fFailedTest;
protected Throwable fThrownException;
fFailedTest存放失败的TestCase信息,fThrownException存放失败提示信息。 主要方法:
public
TestFailure:初始化,对fFailedTest、fThrownException赋值。
failedTest:返回fFailedTest
thrownException:返回fThrownException
toString:
Class TestResult
TestResult用于运行并收集测试结果(通过Exception捕获),注意interface TestListener的所有方法在这里都有同名方法并在同名方法中被调用。
主要属性:
protected Vector fFailures:测试失败报告保存 protected Vector fErrors:测试错误报告保存 protected Vector fListeners:测试监听器保存 protected int fRunTests:运行的测试 private boolean fStop:是否应该停止测试标志,由stop方法设置
主要方法
public
TestResult:初试化
addError:synchronized方法,增加一个错误并向所有监听程序发送错误,调用TestListener. addError
addFailure:synchronized方法,增加一个失败并向所有监听程序发送失败,调用TestListener. addFailure
addListener:synchronized方法,增加监听程序
removeListener:synchronized方法,移走监听程序
endTest:结束测试,并通知所有监听程序,调用TestListener.endTest errorCount:synchronized方法,返回错误个数
errors:synchronized方法,用Enumeration返回所有错误
failureCount:synchronized方法,返回失败个数
failures:synchronized方法,用Enumeration返回所有失败
run:运行测试,创建一个Anonymous类,实现接口Portectable,然后调用runProtected方法,可以参看TestCase的run方法。
runCount:synchronized方法,返回运行数量
runProtected:实际运行测试
runTests:deprecated方法,被runCount方法替代
shouldStop:synchronized方法,返回是否应该停止测试。
startTest:开始测试,并通知所有监听程序,调用TestListener. startTest
stop:synchronized方法,设置停止标志fStop为真。注意是否停止测试TestReuslt不负责的,stop只是简单设置停止标志。
testErrors:deprecated synchronized方法,被errorCount替代
failureCount:deprecated synchronized方法,被testFailures替代
wasSuccessful:synchronized方法,如果所有运行过的测试方法都通过,返回真,否则为否。
private
cloneListeners:复制fListeners,主要用于要使用监听列表的endTest、startTest、addError、addFailure
Class TestSuite
TestSuite用于将多个TestCase集合起来放在一起管理,TestSuite在增加TestCase的时候实际已经将TestCase实例化(按包括方法多少做多少次实例化)。
主要属性:
private Vector fTests= new Vector(10):存放TestCase的实例 private String fName:TestSuite名称
主要方法:
public
TestSuite:初始化,可以选择空、指定名称或包括指定的类。如果是指定的类,那么在TestSuite初始话的时候,TestCase已经实例化并加入到fTests中。
addTest:增加一个TestCase/TestSuit的实例到fTests中。注意由于TestCase的实例化实际上只指定一个测试方法,即增加一个TestCase的实例是注册了其中一个测试方法,参看TestCase类。如参数是一个TestSuite,则相当于增加了一个子Suite.
addTestSuite:增加一个子Suite,实际效果同参数为TestSuite的addTest。 countTestCases:返回Suite(包括子Suite)中的TestCase实例(测试方法)数量
run:运行测试,注意这里是运行fTests中的所有测试,用了TestResult. shouldStop方法来判断是否终止运行。实际是调用了runTest,逐渐
runTest:运行某一TestCase或子Suite的测试,注意使用了递归。如果参数test是一个TestSuite,会再调用TestSuite.run
testAt:返回fTests指定顺序的TestCase或者TestSuite
testCount:返回fTests大小,注意和countTestCases的区别
tests:返回fTests 的内容
setName:设置名称
getName:增加名称
toString:
private
addTestMethod:增加一个测试方法(TestCase实例)到fTests
exceptionToString:返回一个Throwable 中的提示信息
getConstructor:返回指定类的构造函数
isPublicTestMethod:判断一个方法是否是public的测试方法,即一个函数是否是public的,同时是一个测试方法,测试方法参考下面的isTestMethod。
isTestMethod:判断一个方法是否是测试方法,既以”test”为前缀、没有参数及返回值。
warning:增加一个错误提示Testcase到fTests中,注意这里也使用了Anonymous Class。warning使用主要考虑的往往在对TestSuite进行操作的时候,不会因为有错就终止操作,而是在run的时候报告错误
Package extensions
Package extensions主要包括TestCase的各种扩展。
Class Hierarchy
Class TestDecorator
TestDecorator及其子类主要用于在TestCase运行前后加入特定操作,进行修饰。不应该使用TestDecorator而应该使用TestDecorator的子类
主要属性
protected Test fTest:被修饰的TestCase/TestSuite。
主要方法
Public
TestDecorator:初始化,对fTest赋值。
basicRun, run:这两种方法实际都一样,运行测试,为什么要有两个请看class TestSetup中的run方法代码,run方法可能被子类覆盖,但basicRun不覆盖
countTestCases:返回TestCases/TestSuite中测试方法的数量,实际是调用fTest.countTestCases
getTest:返回fTest
toString:
Class RepeatedTest
继承TestDecorator,重复运行TestSuite指定次数。
主要属性
private int fTimesRepeat:保存要运行的次数
主要方法
RepeatedTest:初始化,对fTimesRepeat、fTest赋值
countTestCases:返回要允许的测试方法总次数,TestCases/TestSuite中测试方法的数量*fTimesRepeat
run:运行测试
toString:
Class TestSetup
继承TestDecorator,在运行fTests前后执行特定操作,注意和TestCase中的setUp/dearDown不同,TestSetup是在fTests第一个方法运行前执行setUp,在所有方法执行完毕后执行dearDown,具体看run方法代码。
Public:
TestSetup:初始化,对fTests赋值
run:运行测试, 声明了一个Anonymous Classes,实现了Interface Portectable setUp:运行前要执行的操作,注意应该和fTests定义的类无关 teardown:运行前要执行的操作,注意应该和fTests定义的类无关 Class ActiveTestSuite
继承TestSuite,在不同线程中运行测试方法,在所有方法运行完毕后在关闭线程。
主要属性
private volatile int fActiveTestDeathCount:保存已经运行完毕的线程数量
主要方法
Public:
run:覆盖父类函数,运行测试。增加对fActiveTestDeathCount置0,和线程结束控制函数
runTest:覆盖父类函数,运行测试方法,主要是先创建一个Thread,然后运行测试。
waitUntilFinished:判断是否应该结束Thread,直到fActiveTestDeathCount等于testCount,即TestSuite. fTests大小
runFinished:由runTest调用,fActiveTestDeathCount加一
Class ExceptionTestCase
接触TestCase,拥有测试TestCase方法是否抛出特定Exception。 主要属性
Class fExpected:保存要抛出的Exception
主要方法
Public
ExceptionTestCase:初始化,指定fExpected
Protected
runTest:运行测试,主要是增加了Exception捕获
Package runner
Package runner 主要用于定义一个基本抽象的runner,由runner派生出来的有swing、awt和text三种TestRunner。
Class & Interface Hierachy
Interface FailureDetailView
显示失败信息接口。主要方法有:
getComponent:返回用于显示TraceView的Component
showFailure:显示失败,参数为TestFailure
clear:清除view
Interface TestSuiteLoader
定义如何装入一个TestSuite,主要方法
load:abstract方法,throws ClassNotFoundException,装入TestSuite
reload:abstract方法,throws ClassNotFoundException,重新装入TestSuite
Interface TestCollector
用于收集TestCase/TestSuite的显示名称。只有一个方法
collectTests:以Enumeration返回所有TestCase/TestSuite的显示名称。
Class Sorter 和 interface Sorter. Swapper
Class Sorter用于提供一个快速排序法,interface Swapper是一个内部接口,根据注释说明,Sorter由于与JDK 1.1.7兼容性问题,Sorter不能支持jdk2的collection类。
interface Sorter. Swapper只有一个方法
swap:进行替换
Class Sorter 只有一个方法
sortStrings:对字符进行排序
由于interface Sorter没有实现类,Sorter不能直接使用
Class Version
Class Version用于控制Junit版本,主要方法只有一个:
id:返回版本号码
Class StandardTestSuiteLoader
实现Interface TestSuiteLoader。Class StandardTestSuiteLoader是JDK2本身ClassLoader的TestSuite装载,同一个类只能装入一次。
主要方法:
load:装载
reload:重新装载
Class TestCaseClassLoader
继承JDK2 标准类java.lang.ClassLoader,用于取代系统确省的类装入类。主要是实现只从指定的路径中装入类,对于部分系统Package或其他想使用系统装入而不是使用TestCaseClassLoader装入的,可以修改defaultExclusions或将其写入到文件
excluded.properties中,系统默认使用系统装入的Package有junit.framework、junit.runner、junit. extensions,文件excluded.properties必须和Class TestCaseClassLoader放在一起。在3.72版本中的TestCaseClassLoader不能装入jar文件中类。
主要属性
private Vector fPathItems:类查找路径存放
private String[] defaultExclusions:确省要排除junit的三个package
static final String EXCLUDED_FILE:用户自定义要排除的类
private Vector fExcluded:要排除的路径
主要方法
Public:
TestCaseClassLoader:使用系统默然或指定的类查找路径(使用系统默认路径分割符号的字符串)初始化,在初始化的时候会调用scanPath将搜索路径加到fPathItems 中,调用readExcludedPackages函数,将defaultExclusions及EXCLUDED_FILE中定义的要排除的类加入到fExcluded中
getResource:返回指定资源的url路径,调用JDK2系统的 ClassLoader.getSystemResource。资源可以是audio,icon等,具体可以参看JDK2的类说明
getResourceAsStream:以输入流的方式返回指定的资源
isExcluded:判断一个类或包是否应该排除、使用系统标准装入
loadClass:synchronized方法。装入一个类,覆盖父类方法,请参看JDK2中ClassLoader. loadClass定义,对于在fExcluded的类,采用findSystemClass直接装入。其他的将在fPathItems定义的路径中寻找(调用lookupClassData),找到了就使用defineClass将lookupClassData返回的字节流转为类并返回,否则就抛出ClassNotFoundException
package private(default)
isJar:判断一个文件是否用jar或zip结尾
private
scanPath:由TestCaseClassLoader调用将搜索路径加到fPathItems 中 lookupClassData:查找指定的类,并将class内容以字节流的方式返回,调用了loadJarData,loadFileData。
loadFileData:从文件中装入类的字节流实际读入是调用函数getClassData loadJarData:从zip文件中(注意,3.72junit不支持jar文件)读入类的字节流
readExcludedPackages:将defaultExclusions及EXCLUDED_FILE中定义的要排除的类加入到fExcluded中
Class ReloadingTestSuiteLoader
实现接口TestSuiteLoader,使用TestCaseClassLoader来装入类。主要方法:
load:装载
reload:重新装载
Class ClassPathTestCollector
实现TestCollector接口,分析Java Class Path,并对Class Path中所有的类(JAR、ZIP文件除外)进行分析,根据指定的规则找出可以运行的测试类。具体规则见isTestClass方法
主要属性:
static final int SUFFIX_LENGTH:保持”.class”的长度
主要方法
Public
ClassPathTestCollector:初始化函数
collectTests:以Enumeration的方式返回所有可以运行的测试类,调用splitClassPath将Class Path 分解为一个Vector,调用collectFilesInRoots获取类
Package Private(Default)
collectFilesInRoots:搜索参数一中的路径,返回所有类。调用gatherFiles实际获取类
gatherFiles:获取指定目录下的所有类,是一个递归函数。
splitClassPath:将Class Path 分解为一个Vector
Protected
isTestClass:判断一个类是不是测试类,规则文件名中扩展名为class,不包括”$”,包含了”Test”。
classNameFromFile:从文件名中获取类名称
Class SimpleTestCollector
继承了ClassPathTestCollector,从代码来看,实际没有对ClassPathTestCollector做任何修改,虽然代码包括isTestClass,但其中的代码和ClassPathTestCollector中是一样的。
Class LoadingTestCollector
继承了ClassPathTestCollector,修改了判断测试类的方法。
主要属性:
TestCaseClassLoader fLoader:类装入类
主要方法
public:
LoadingTestCollector:初始话,实例化fLoader
protected:
isTestClass:覆盖父类中的方法,注意还有一个Package private(Default)的isTestClass。使用classFromFile从文件生成一个Class后调用Package private(Default)的isTestClass判断是否是一个测试类。
package private(Default):
classFromFile:使用TestCaseClassLoader从一个文件中装入类
isTestClass:判断一个Class是否是一个测试类,判断的依据是是否包括一个在BaseTestRunner. SUITE_METHODNAME定义名称的方法(suite)方法或者是具有以下特性:
1、实现了Interface test,
2、有一个Public 的Constructor方法
3、Modifier是public的
hasSuiteMethod:判断十分有BaseTestRunner. SUITE_METHODNAME定义名称的方法
hasPublicConstructor:判断是否有有一个Public 的Constructor方法
Class BaseTestRunner
BaseTestRunner是一个抽象类,是所有Runner的基类。BaseTestRunner使用类静态代码,在被初始化的时候运行。
主要属性
public static final String SUITE_METHODNAME= "suite":suite方法定义 static Properties fPreferences:保存参数 static int fgMaxMessageLength= 500:定义最长Message长度 static boolean fgFilterStack= true:是否过虑错误信息 boolfPreferencesean fLoading= true:标志是否使用自定义的ClassLoad类
主要方法
Public:
getTest:根据suiteClassName名称返回一个TEST类,如果类有SUITE_METHODNAME定义的方法,调用suite方法,否则返回new TestSuite(testClass),创建一个新的suite。
elapsedTimeAsString:将时间转为指定格式的字符串
setLoading:设置fLoading
extractClassName:从一个字符串中返回ClassName,主要是处理VA/Java style truncate:static方法,将一个字符串截为指定长度
getLoader:判断并返回使用ReloadingTestSuiteLoader还是StandardTestSuiteLoader,调用useReloadingTestSuiteLoader方法
getPreference:从fPreferences中返回指定的参数值
inVAJava:判断是否在VisualAge环境中
getFilteredTrace:将参数Throwable t中包括的信息进行过滤(Filter)并返回处理后的字符信息
filterStack:对字符进行过滤
filterLine:判断字符是否应该过滤
protected:
processArguments:处理传入的参数,如果参数中包括了要运行TestSuite则返回TestSuite名称,如果参数中包括“-noloading”,则调用setLoading(false)不使用ReloadingTestSuiteLoader,使用StandardTestSuiteLoader。如果参数中包括”-nofilterstack”,设置fgFilterStack=false,可以使用“-c xxx”指定要测试的类 runFailed:abstract方法,运行失败时处理
loadSuiteClass:从一个TestSuite的名称装入一个类,调用getLoader来判断使用ReloadingTestSuiteLoader还是StandardTestSuiteLoader
clearStatus:清楚状态信息,需要子类覆盖
useReloadingTestSuiteLoader:判断是否使用ReloadingTestSuiteLoader
private:
getPreferencesFile:读取参数配置文件,配置文件名称为junit.properties,应该放在System.getProperty("user.home")指定的目录下
readPreferences:将参数配置文件中的内容放到fPreferences中
程序中的静态代码完成fPreferences的初始话及读取参数文件、设置fgMaxMessageLength。
Package textui
Package textui仅有一个类TestRunner,用于实现文本方式的运行。
Class TestRunner
继承BaseTestRunner, TestRunner用于完成文本方式的测试运行。 主要属性:
PrintStream fWriter= System.out:输出流 int fColumn= 0:仅用于startTest方法,其实可以不用
主要方法:
Public:
TestRunner:构造函数,可以自己指定输出流
getLoader:覆盖父类方法,只使用默认的类装入(StandardTestSuiteLoader)
addError:synchronized方法,增加一个错误
addFailure:synchronized方法,增加一个失败
doRun:运行指定的TestSuite并返回TestResult
startTest:开始测试
endTest:结束测试
main:运行函数,用于外部直接调用。将参数直接转给start方法。主要
参数为
-wait:设定等待
-v:显示版本号
-c 类名称:要运行的测试类
具体看start方法。
print:synchronized方法,输出结果,调用printErrors(result); printFailures(result);
printHeader(result);
printErrors:输出错误
printFailures:输出失败
printHeader:输出总计
run:运行指定的TestCase/TestSuite
runAndWait:运行指定的TestSuite并等待,参看pause方法 Protected
createTestResult:创建一个TestResult
pause:判断是否要pause
start:运行测试,由main方法调用。
runFailed:运行失败处理方法
writer:返回输出流fWriter