ITU jTester 分享

Download Report

Transcript ITU jTester 分享

ASC JTESTER 分享
吴大瑞
2010-11-07
大纲
•
•
•
•
•
•
整体框架介绍
断言模块
Spring模块
DbFit模块
问题解答
Q&A
整体框架介绍
dbFit module
Spring module
Inject module
Junit / TestNG
jTester
jmockit
tracer module
Jtester assert
整体框架介绍
框架中的观察者模式
• 每个生命周期都是一个观察点。
• 每个模块都有一个监听器。
• 注册方式: unitils.modules=database,dbfit,jmock,inject,spring,tracer
• 当框架执行到每个生命周期时,会通知各
个模块执行对应的动作。
Spring模块的监听器
• 在测试类创建后注册mock bean对象.
•
•
老版本 @MockBean
新版本 @SpringBeanFor
• 在每个测试方法开始前
•
•
初始化spring容器(只有第一个方法做)
根据Annotation注入相应的spring bean。(@SpringBeanByName
@SpringBeanByType @SpringBean @SpringBeanFor)
DbFit模块的监听器
• 每个测试方法前,注册wiki变量;查找要运
行的wiki文件。
• 每个测试方法后,注册wiki变量;查找要运
行的wiki文件;清除wiki变量。
其他模块的监听器
• 数据库管理监听器。
• Inject模块监听器。
• Spring bean堆栈和SQL log记录监听器。
jTester中的断言
对java assert的思考?
Java Assert的2种用法
• assert <boolean表达式>
如果<boolean表达式>为true,则程序继续执行。
如果为false,则程序抛出AssertionError,并终止执
jTester的断言本质上就是java 的
行。 assert断言。凡是jTester断言可以做
的事情,java assert都可以做,无非
• assert <boolean表达式>
: <错误信息表达式>
是提供了便利性。
如果<boolean表达式>为true,则程序继续执行。
如果为false,则程序抛出java.lang.AssertionError,
并输入<错误信息表达式>。
即时生效的断言
•这条语句是立即判断alibabaAddress这个对象的性质的,任何一个性质的不符合
want.type(你要断言的值).assert(你希望这些
都将抛出AssertionError,终止测试的运行。
值拥有哪些的性质?)
• 举例:
延后生效的断言
• the.type().assert(你希望这些值拥有哪些的
定义断言器的时候并没有发生真正的assert行为,只有到程序中调用到mock
api是
性质?)
才发生断言。
注意:这里并没有传你的期望值进去。只是描述了你的期望值要有的性质。
• 举例:
jTester断言的结构分析
• matche 判断实际值是否符合性质(item)
对于即时生效的断言是马上运行的。
对于延后生效的断言是允许到对应的api时才触发。
• describeMismatch 如果不符合,返回给用户
的错误信息的描述。
jTester断言的结构分析
Hamcrest
Contains
StartsWith
……
UnitilsPropertyMatcher
几个复杂对象判断的示例
• 判断pojo对象的属性。
• 判断pojo对象集合。
• 判断map对象。
SpringModule解析
• @SpringApplicationContext
加上这个属性,
spring加载将会忽
略不存在的bean,
提高测试的健壮性
SpringModule解析
jTester根据TestCase
@SpringApplicationContext内容
• @SpringBeanByName
• @SpringBeanByType
初始化spring容器
• @SpringBean(value=“bean name”)
Spring容器
到目前为止,spring bean的注入是单向的。即框架
jTester框架从spring容器中将对应的
启动spring容器,初始化好spring
bean,然后根据
bean取出来注入到TestCase中
@SpringBeanByName等标注将对应的bean从容器中
取出,注入到testcase中。
SpringModule解析
• @AutoBeanInject
AutoBeanInject定义了查找
bean实现类的规则bean
定义了基本的公用的spring
jTester框架根据
@SpringBeanByName等标注
和规则,在spring容器初始化
前定义对应字段的bean定义。
此时phoneBookService等bean
在spring容器中并没有定义。
jTester框架初始化spring容器
现在,@SpringBeanByName等
作用是双向的。
1、往spring容器中定义bean。
2、从spring容器中取出bean。
jTester框架从spring容
器中将对应bean取出注
入到TestCase中。
@AutoBeanInject的说明
是否启动自动注入(提供一个
自动注入的规则@BeanMap 数组
开关,disabled自动注入)
例子规则说明:
这里**表示package的一部分,* 表
示classname的一部分。第一个
BeanMap规则表示,接口类的
package + “.impl”是实现类的
package,第二个BeanMap表示实
现类的package就是接口类的
根据依赖字段的属性名称或者字
package。
段类型的package,显式的排除
二个规则中:接口类的classname
依赖的查找。
+ “Impl” 就是实现类的classname。
是否忽略根据规则查找不到的属性依赖。
可以有任意个** 和 *,但要是可分
False:如果查找不到属性依赖,抛出错误。
割的。比如
True:如果查找不到属性依赖,打印一条消息,继续。
intf = **.intf.**.*Intf*
impl = **.impl.**.*Impl.*
如果我有一个实现类
adfa.dadf.edd.ImdOll
和接口类
eiu.e384d.adf.IntfId
之间根本毫无规则可言怎么办?
@SpringBeanFor的作用
@SpringBeanFor(MyImplement.class)
MyInterface myInterface;
都是定义了MyInterface
的实现是MyImplement,
jTester框架会继续查找
它们有区别吗?
MyImplement类中定义的属
性的bean定义。
@SpringBeanFor
MyInterface myInterface = new MyImplement();
引申:
@SpringBeanFor
@Mocked
MyInterface myInterface;
jTester把new MyImpelment()
作为bean对象,不在查找其
属性依赖。
jTester在Spring加载过程中
做了哪些手脚?
Inject模块解析
• Targets 表示要将
字段值注入到那
些对象中。
• Properties 表示字
段值注入到target
对象的那个属性
中,如果为空,
则默认按字段名
称注入。
Inject模块解析
• 示例
DbFit模块解析
• Wiki格式 |…|…|
• 基于表格驱动
• 以html方式呈现结果
Wiki数据
Html格式
HTML表格中数据驱动
• @DbFit(when=“”,then=“”)
Html结果呈现
DbFit模块解析
• 容易犯的错误
没有connect
|connect|
表格格式不全
|data|data|data
表格错位
|Insert|table_name|
|field1|field2|
|value1|value2|
|commit|
DbFit模块解析
• DbFit wiki文件中可使用的命令基本上都定
义在DatabaseFixture这类中。
在DbFit中使用变量
在DbFit中使用变量
• 动态使用变量
• 内置变量
@{date} 当前日期 yyyy-MM-dd
@{datetime} 当前时间 yyyy-MM-dd HH:mm:SS
@{space} 空格
自动查找wiki文件
jTester中的事务
• DatabaseModule.Transactional.value.default=commit
• @Transactional(TransactionMode.ROLLBACK)
• 在DbFit的wiki文件中显式的|commit| 或|rollback|
• api中抛出了Spring事务定义中回滚的异常。
此时,在test结束commit或rollback都会导致测试错误,解决办法。
TransactionMode.DISABLED
Mock的技术原理
• Java Proxy:java 提供的接口代理机制。
• Asm、cglib的作用:在classloader的时候静
态改变class的字节码。
• JDK5 java agent:class loader的时候动态修
改class 的行为。
• JDK6 java agent:可以做到class loader后动
态改变class的行为。
Mock的使用
• 工具类DateUtil
Mock的使用
• 问题:私有方法的mock
• 关键:new MockUp<T>针对的是class实现,
因此这种方式无法mock接口。如果一个方
法是在父类中定义的,那么应mock父类,
而不是子类。
• 所有的mock方法的限定词都是public,而不
管原方法是private, public, static还是final.
Mock的使用
• 基于行为的测试
– @Mocked / @NonStrict
– new Expectations() / new NonStrictExpectations()
• 为什么我已经mock了这个接口调用到还会
报错?
• 为什么我没有调用到这个接口也会报错?
Mock的使用
• 参照官方文档
http://code.google.com/p/jmockit/
• jTester文档及ppt
Q&A