Skip to content

Test Overview

Calvin Xiao edited this page Jan 19, 2014 · 4 revisions

##Overview

测试可以粗分为三种:

  • 单元测试, 针对内部实现类的白盒测试。
  • 功能测试, 针对需求的黑盒测试,通常集中在某一个子系统,可在本机运行,要求有较高的执行速度。
  • 集成测试, 将所有子系统与外部资源集成在一起的测试。

三者的测试用例数量呈金字塔模型,如果功能测试的用例较多,可挑选较重要的用例用@Category标注,组成Smoke Test。

在SpringSide中演示了前两种测试。

##1.单元测试

单元测试又有完全使用Mock隔离的,和部分使用外部资源如数据库两类。

建议所有不直接依赖于外部资源(数据库,JMS等)都使用Mock的方式进行屏蔽隔离。 Mock的方案推荐Mokito+PowerMock,详见Mock章节。

Assert语句最好用AssertJ来编写,详见AssertJ章节。

有些依赖外部资源,如JPAMappingTest,或者需要大量的预设数据,或者所需对象由Spring通过FactoryBean创建等等,你直觉如果使用了Mock,测试的性价比就相当低时,就使用基于Spring Runner的测试。详见Unit Test章节。

##2.功能测试 推荐使用嵌入式jetty,实现容器外的测试,省去打包,部署的时间。Jetty只在整个测试过程中启动一次,详见Jetty章节。

为了实现功能测试可在本地运行以及执行速度更高的目标,除了Jetty外,各种数据库,缓存,JMS等外部资源,都尽量使用嵌入式版本或用模拟器代替,详见Simulator章节。

对于GUI界面的测试,暂时最好的依然是Selenium2。同样的使用JVM退出的钩子,Selenium也只在整个过程中启动一次。 详见Selenium2章节。

另外,功能测试用例应该既支持在Jetty内运行,也可以针对远程的真实服务器运行,因此设计在application.functional.properties和application.functional.local.properties文件中的baseUrl和数据库连接的属性,可以方便进行切换。

##3.数据 ###3.1 数据库 在单元测试中,推荐使用In-Memory的嵌入式H2,在功能测试中,可使用持久化到文件的嵌入式H2,也可以使用实际的生产数据库类型。

###3.3 Random Data SpringSide core中封装了一个RandomData工具类,产生各种随机数据。

###3.3 数据刷新策略 ###3.2 数据刷新

之前使用DBUnit, 用csv/xml文件来定义数据,但后来觉得它在服务器上用命令行来执行时并不方便(需要dbunit/jdbc的jar包等), 也为了减少项目的使用技术,使用会普通的sql放置测试数据。

在springside-core中封装了DataFixtures类, 可以读取配置文件中的连接参数获得远程数据库的连接然后刷新测试数据库。详见每个项目的BaseFunctionalTestCase对DataFixtures的使用。

在Unit Test中, 因为Spring会自动rollback所有事务,因此在全部测试周期内,只需要执行初始化sql一次,初始化默认数据一次, 在applicationContext的H2定义中定义SQL即可。

在Functional Test中,事务会真实发生,所以设置总共执行sql一次,而在每个Test Class开始前刷新一次数据,也可根据情况在某些test method前刷新特殊数据。

在bin/refresh-db.bat中,通过maven,靠maven的ant-run插件调用ant的sql插件,执行sql刷新开发数据库。

Spring Profile

开发,单元测试和集成测试,以及实际生产环境,会用到不同的数据库和模拟器,和数据刷新策略,Spring3.1提供了很好的profile管理, 详见Spring章节。

Maven的目录结构及运行

关于Test代码的目录结构, 分组测试等,几经周折后的方案是将所有功能测试用例放在test/functional,以*FT命名,依然用surefire插件在test阶段执行,详见Maven章节。