JUnit 学习笔记 第二记

1、JUnit4添加了新的方法用于在测试类中所有测试方法执行之前或者执行之后执行,具体使用方法是使用注解@BeforeClass或者@AfterClass注解注解在public static void修饰的并且没有参数的方法之前,这样,被注解的方法就会在所有测试方法启动之前或者都结束之后执行一次。


2、@Test只能注解方法,并且它有两个可选属性:
1)timeout:设定测试方法最多能够允许执行的毫秒数,一旦超出这个毫秒数则测试不通过。
2)expected:该属性值是一个Class对象,一般是Throwable的Class,表示期望获得测试方法一个异常类的Class,只有测试方法中抛出符合该属性值的Class类异常,测试才能通过。在JUnit3.8中要完成这个功能需要在测试方法中手写捕捉异常和比较异常的代码,JUnit4的注解节省了这些过程。
如:@Test(timeout = 500,expected = Exception.class)


3、@Ignore可以注解方法也可以注解类,一旦被注解,则表示该测试方法或者测试类中的所有方法都忽略掉,不执行这些方法的测试。它可以接收一个value值,该值为一个给予用户的提醒信息。


4、JUnit4增加的新功能:参数化测试。当对一个目标方法进行测试的时候,一般都需要设计目标方法的参数数据和目标方法的测试结果比较数据。如果目标方法可能存在多种临界情况,而这些临界情况仅仅是由参数数据和结果数据不同,在JUnit3.8中就需要针对每种不同的数据写一个测试方法,这将造成代码的冗余。在JUnit4中则提供了参数化测试的方法,为一个测试方法提供多组数据,测试的时候JUnit会自动根据每组数据进行测试。具体步骤为:
1)测试类要使用注解@RunWith(Parameterized.class)表示该测试类将不使用JUnit内建的运行器运行,而使用参数化运行器运行(该注解只能注释类)。
2)在参数化的测试类中提供@Parameters注解的提供参数方法,方法要使用pubic static修饰,并且返回类型为Collection。方法块中提供多组测试数据,可以使用Object[][]数组,每组测试数据作为其一维数据,再将Object数据转换为Collection。
3)定义参数化测试类带参数的构造方法。步骤2中每组数据包含多少个数据,测试类就需要定义多少个对应类型的成员变量,构造方法的参数列表按照每组数据的排列顺序排列,构造方法块中对测试类的成员变量进行赋值。
4)测试方法中使用测试类的成员变量完成测试的代码,一共有多少组数据,JUnit就会测试多少次,将每组测试数据都执行。


5、在JUnit4中同样可以实现同时运行多个测试类,需要使用@RunWith(Suite.class)和@Suite.SuiteClasses(Class[] cla)两个注解同时注解一个测试类,这个测试类的内容没有多大意义,整个测试类的意义都在于两个注解上。其中@Suite.SuiteClasses()注解需要接收一个Class数组,在运行这个测试类的时候,Class数组中每个测试类都会被执行。特别的,Class数组中的元素也可以是另一个Suite,执行的时候,JUnit会将Class数组中每一个测试类一直链接寻找执行下去,直到找到所有可执行的TestCase执行为止。


6、模板方法模式:定义了一些固定不变的算法骨架,但骨架的具体步骤实现由具体子类实现,这么做的好处是可以复用算法的结构。模板方法模式的角色分为父类角色(提供模板)和子类角色(为模板提供实现)。


7、模板方法模式的设计步骤:
1)设计父类角色,也就是模板,一般是一个抽象类,不能是接口。父类角色抽象类中要定义算法骨架各个步骤的抽象方法和调用这些抽象方法的具体方法。模板方法模式的模板就体现在这个调用抽象方法的具体方法上,用户只要调用具体方法就能按照具体方法中规定的调用抽象方法顺序完成一个算法功能。因为要定义具体方法,所以父类角色才不能是接口。
2)继承父类角色,设计子类角色。继承父类,所以继承了父类的具体方法,同时也要实现父类中的抽象方法,这实现这些抽象方法就是对模板的具体实现。
3)根据多态构造父类角色对象,调用父类角色的具体方法就能按照模板的算法顺序执行具体子类中对模板步骤的实现。


8、JUnit3.8中的TestCase应用了模板方法设计模式:

public void runBare() throws Throwable{
setUp();
try{ runTest();}
finally{ tearDown();}
}
这就是为什么每个测试方法执行的时候一定要先执行setUp方法和测试方法执行之后一定会执行tearDown方法,原因就在于这是个模板方法模板。
JUnit4中的注解@Before和@After也是运用模板方法设计模式。


9、JUnit中每执行一个测试类中的测试方法,都构造了一个测试类对象,也就是说在本质上,JUnit为每一个测试方法构造了一个测试类对象。因此,即使是同个测试类中的测试方法一块运行,在运行时它们也是在不同的测试类对象中,所以除了测试类的静态成员变量,测试方法对其它成员变量的使用不影响其它测试方法。


10、适配器模式:主要是将一个类的接口转换成用于需要的另外一个接口,适配器模式使得原本不能一起工作的类可以一起工作,通俗的讲就是将原有的但用户不能直接使用的代码进行适配器包装后就可以供用户使用。


11、适配器的角色:
1)目标抽象角色(Target):一般都是一个接口,是抽象了用户能够直接使用的接口。
2)适配器角色(Adapter):一个具体类,实现目标抽象角色接口并能够调用Adaptee中的方法,以将其进行转换。
3)被转换角色(Adaptee):一个具体类,是原有的用户不能直接使用的,就是要被转换的接口。


12、适配器模式的实现方式可分三类:
1)类适配器(采取继承Adaptee的方式实现)。
2)对象适配器(采取Adaptee对象组合的方式实现,推荐使用的方式)。
3)缺省适配器(AWT、Swing中的事件适配器)。


13、适配器模式之类适配器的实现步骤:
1)设计目标抽象角色接口Target,定义用户能够直接使用的方法。
2)设计要被转换的源适配器类Adaptee。
3)设计适配器Adapter,Adapter要继承Adaptee类和实现目标抽象角色接口Target。类适配器模式转换的关键在于Adapter既继承了Adaptee又同时实现了Target接口,因此Adapter既拥有Adaptee中的方法又需要实现Target中的也就是用户可以直接使用的方法。只要Adapter在实现的Target方法体中调用Adaptee中的方法,那么用户通过Adapter调用用户可以直接使用的Target中的方法就能够间接转换成调用Adaptee中的方法,从而实现适配器的转换。


14、适配器模式之对象适配器的实现步骤:
1)设计目标抽象角色接口Target,定义用户能够直接使用的方法。
2)设计要被转换的源适配器类Adaptee。
3)设计适配器Adapter,Adapter不用继承Adaptee,但是也要实现Target接口中的方法,并且Adapter具有一个Adaptee类对象作为成员变量,Adapter的构造方法要接收一个Adaptee对象以初始化成员变量。之所以称为对象适配器,就是因为这个模式组合了一个Adaptee对象作为成员变量,这也是与类适配器模式最大的区别。在实现Target接口方法中,通过Adaptee成员变量来调用用户实际需要调用的方法,完成适配器的转换功能。


15、适配器模式之缺省适配器的实现步骤:
1)设计目标抽象角色接口Target,定义用户能够直接使用的方法。
2)设计适配器Adapter类,需要实现接口Target,但是不用继承任何类。缺省适配器的缺省意义就在于它没有转换任何类的方法,仅仅是对Target接口中方法的一个空实现。
3)使用缺省适配器需要设计一个实际使用的类继承Adapter,并重写其中需要使用的方法。


16、适配器模式与代理模式非常类似,主要区别在于适配器模式中仅仅只是调用源对象中的方法,而代理模式在调用源对象方法的基础上加上了代理自己需要实现的一些代码。


17、JUnit3.8中使用了适配器设计模式,比如使用了模板方法设计模式中的runTest方法。JUnit3.8不可能事先知道用户设计的测试方法,所以JUnit3.8用适配器模式做了适配器runTest方法,在runTest方法中调用了用户设计的testXXX测试方法。正如JUnit3.8不可能事先知道用户设计的测试方法,所以runTest方法要想调用用户设计的测试方法只能通过反射机制来获得。在runTest方法中会判断用户的测试方法参数是否为空和测试方法是否为public,具体代码见JUnit3.8中TestCase中的源代码。


18、Eclipse中使用自带的JUnit库没有办法查看JUnit的源代码,需要在Eclipse中查看JUnit的源代码需要在Built Paths中使用外部JUnit的jar包和导入jar包的源代码。


19、命令模式:一种类似于黑匣子思想的设计模式,将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。


20、命令模式的角色:
1)客户角色:创建出一个个具体的命令对象,并将其与确定的接收者关联。
2)命令角色:一个接口或者抽象类,定义了所有具体命令类需要实现的方法。
3)具体命令角色:继承或者实现了命令角色的类,实现了命令角色中的抽象方法,通过这些方法来调用接收者的相应操作。
4)调用者角色:负责调用命令对象来执行请求(请求的最终是接收者来完成)。
5)接收者角色:负责具体实施和执行一个请求。


21、命令模式的设计步骤:
1)设计命令角色,提供具体命令角色需要实现的调用接收者角色的抽象方法。
2)设计接收者角色,完成接收者角色可以执行相应请求操作的处理方法,命令角色将通过调用接收者角色的这些方法最终完成请求的操作。
3)设计具体命令角色:继承或实现了命令角色,一般需要包含接收者角色最为其成员变量,在具体命令角色的构造方法中接收一个接收者参数对其进行初始化。实现的命令角色方法中通过调用这个接收者角色成员变量的方法来实现相应请求的相关操作。具体命令角色的设计与对象适配器设计方法类似。
4)设计调用者角色:调用者要调用命令角色,所有调用者角色中需要包含命令角色对象来做为调用者角色的成员变量,同样需要在构造方法中接收一个命令角色对象对其进行初始化。在调用者角色中设计相应方法,在方法体中调用命令角色的方法,借命令角色的方法最终调用的是接收者对象的操作方法。
5)设计客户角色:客户角色创建具体命令对象提交请求。因此,客户角色要构造具体命令角色对象(隐含需要构造接收者对象传递给命令角色)来封装客户的请求,也要将封装了客户请求的命令角色对象提交给调用者,由调用者去调用这些命令角色对象。


22、命令模式的过程类似于餐馆的点餐过程:厨师等同于接收者角色,菜单等同于命令角色,顾客等同于客户角色,顾客的订单等同于具体命令角色,服务员等同于调用者角色。


23、JUnit使用命令模式的体现:
1)JUnit的TestCase类就像命令模式的命令角色,而我们继承TestCase的具体测试类就像命令模式的具体命令角色。
2)JUnit框架就像命令模式中的调用者角色和接收者角色,我们用户提交的请求封装成具体的TestCase测试类对象,提交给JUnit框架,由JUnit框架调用这些测试类(具体命令角色),最终由JUnite的相关实现具体操作的代码执行测试,并返回测试结果。


24、组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,并使得用于对单个对象和组合对象的使用具有统一性,也就是忽略掉部分与整体之间的差异性。


25、组合模式的角色组成:
1)Component角色:抽象构建接口,是一个接口,定义了单个对象乃至管理多个对象的管理器的默认行为。
2)Leaf角色:实现了Component角色接口,实现了“部分”的行为。
3)Composite角色:实现了Component角色接口,是Leaf角色的管理器,能够容纳多个Leaf对象,并定义了操作Leaf的方法。在实现Leaf功能时,需要遍历Composite中的Leaf对象,逐个调用Leaf对象的处理方法。


26、组合模式的实现步骤:
方法一:
1)定义Component接口,在接口中只定义Leaf角色需要实现的操作方法。
2)定义Leaf类,实现了Component接口及接口中要求的Leaf需要实现的功能方法。
3)定义Composite类,类中需要定义一个Component集合以存放Leaf对象或者Composite对象。类中也要定义操作Component集合的相关方法,同时,由于Composite也实现接口Component,所以也要实现Component中定义的Leaf方法。Composite对这个方法的实现,需要遍历Composite中Component集合的每个元素,转而逐个调用Leaf的方法。
4)用户实现组合模式,组合对象需要定义为Composite类型,不能是父接口Component,因为Component中没有定义管理Composite中子元素的方法。
方法二:
1)定义Component接口,接口中不但要定义Leaf角色需要实现的方法,也要定义Composite中操作子元素Leaf对象的方法。
2)定义Leaf类,同样需要实现Component中的所有方法,除了实现Leaf需要的具体方法之外,也要实现关于操作Composite子元素的方法,但由于Leaf类中没有子元素,所以需要将这些操作子元素的方法定义为空实现方法。
3)定义Composite类,要实现Component接口中所有方法,除了自身的操作子元素方法之外,对为Leaf设计方法的实现要转成遍历Composite所有子元素调用它们的方法。
方法一和方法二的区别在于将操作Composite子元素的方法定义到Component接口中,这么一来,用户创建Composite的时候就可以向上使用Component对象来接收,让Leaf和Composite统一使用Component。


27、JUnit中对组合模式的使用:JUnit中Test相当于组合模式中的Component,用户自定义的测试类继承了TestCase相当于组合模式中的Leaf,而Suit可以包含多个测试类或者多个Suite相当于Composite。


28、JUnit中的错误(error)和失败(failure):
1)错误实质代码中抛出了异常等影响代码正常执行的情况,比如抛出ArrayIndexOutOfBoundException等,这就叫做错误。
2)失败是指我们断言所期待的结果与程序实际运行的结果不一致,或者是调用fail方法,这才叫做失败。


29、JUnit的TestResult结果输出类运用观察者模式,见TestResult源代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值