环境背景:
  我作为项目经理和技术架构管理人员负责公司一条生产线。讨论之后,首席架构师希望我们能够实施TDD。在实施TDD的过程中,设计实施过程的整体思路就是:单元测试用例文档 - 实施单元测试 - 实施业务代码 – 修改业务代码逻辑。实施人员需要参与每个环节,按照规范编写单元测试用例文档。单元测试我们按照模块(模块与人员基本没有重合)划分包(suite),保证实施起来不会产生干扰。。技术架构决定采用:maven,junit,svn。
   
  技术背景:
  技术架构设计上,我们封装了dao层的实现,所以实施人员基本无需涉及dao层的开发。服务层我们采用了JAX-RS的服务规范,对外开发服务接口。
  在测试覆盖率方面,我们基本不要求对dao层的单元测试,但要求在服务层的单元测试达到100%。由于服务层是Restful WS的模式,所以我们采用了模拟HTTP请求的方式在测试服务层。
  由于需要模拟HTTP的请求,所以我们在单元测试中采用了jetty作为内嵌服务器,单元测试开始时同一启动,完成后关闭。
   
  实施过程:
  开发过程中,实际实施的时候发现一个问题,对于测试数据的管理问题。即测试当中需要一定的数据环境来验证业务逻辑。这个数据环境如何建立?
   
  方案一,使用dbunit和hsqldb。在测试启动时重建数据环境。
  否决,原因:
  1.与实际运行环境差异较大。
  2.反复重建数据环境,效率上有缺失。
  3.技术架构增加,学习和维护曲线较大。
   
  讨论后决定使用
  方案二,独立出一套测试数据库,完整数据环境。考虑到增删改与查询的冲突,制定默认规则,如id在20之内的不允许进行任何改动。以尽量隔离增删改的影响。
   
  针对方案二,有一个较大的问题,如何在开发过程中自由的切换数据库配置呢?由于我们还是用了Hudson作为CI服务器,还要考虑到打包的过程。整体考虑之后,有两个步骤需要注意:
  一、开发过程。开发过程中,我们将配置直接指向测试数据库。
  二、打包过程。使用了maven,存在单元测试配置与最终产品配置的冲突。
  所以最终问题的焦点集中在打包过程的maven配置方案。
   
  搜索之后比较好的资料有
  MAVEN:如何为开发和生产环境建立不同的配置文件 --我的简洁方案
  (http://www.blogjava.net/scud/archive/2010/10/27/336326.html)
  这篇博客是介绍在maven 中使用mvn package -P test 这样的自定义profile来实现的。这样是可行的,但是在Hudson中无法实现一条命令切换两套配置。
  于是继续寻找,最终在maven的官方网站找到《Building For Different Environments with Maven 2》(http://maven.apache.org/guides/mini/guide-building-for-different-environments.html)看完文章之后发现,实际maven提供了一个非常好的插件maven-antrun-plugin,以实现某些ant的功能。此处还需要了解的知识就是maven的构建生命周期标准(http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)。基于上述两个知识点,我们制定出如下方案,在项目中建立测试配置目录及产品配置目录,在maven的package阶段开始前,都使用测试配置,运行集成测试,完成在package阶段前将产品配置覆盖至打包文件夹内,然后进行打包。思路就是这样,下面贴出pom文件的关键部分。
   
   
  POM.xml
  <!—profile 节点定义覆盖文件的方式内容 -->
         <profiles>
                <profile>
                       <id>product</id>
                       <build>
                              <plugins>
                                     <plugin>
                                            <artifactId>maven-antrun-plugin</artifactId>
                                            <executions>
                                                   <execution>
                                                          <id>pre_product</id>
                                                          <phase>prepare-package</phase>
                                                          <goals>
                                                                 <goal>run</goal>
                                                          </goals>
                                                          <configuration>
  <!—此处与ant的任务相似 -->
                                                                 <tasks>
                                                                        <delete file="${project.build.outputDirectory}/spring/dataSourceContext.xml" />
                                                                        <delete file="${project.build.outputDirectory}/log4j.properties" />
                                                                        <copy file="src/product/assembly/log4j.properties" tofile="${project.build.outputDirectory}/log4j.properties" />
                                                                        <copy file="src/product/assembly/spring/dataSourceContext.xml" tofile="${project.build.outputDirectory}/spring/dataSourceContext.xml" />
                                                                 </tasks>
                                                          </configuration>
                                                   </execution>
                                            </executions>
                                     </plugin>
                              </plugins>
                       </build>
                </profile>
         </profiles>
   
  <!—构建过程 -->
         <build>
  <!—指定资源目录 -->
                <resources>
                       <resource>
                              <directory>src/test/resources</directory>
                              <includes>
                                     <include>**/*</include>
                              </includes>
                       </resource>
                       <resource>
                              <directory>src/test/assembly</directory>
                              <includes>
                                     <include>**/*</include>
                              </includes>
                       </resource>
                </resources>
   
                <finalName>po</finalName>
   
  <!—指定集成测试配置 -->
                <plugins>
                       <plugin>
                              <groupId>org.apache.maven.plugins</groupId>
                              <artifactId>maven-surefire-plugin</artifactId>
                              <version>2.4.3</version>
                              <configuration>
                                     <junitArtifactName>junit:junit</junitArtifactName>
                                     <forkMode>once</forkMode>
                              </configuration>
                              <executions>
                                     <execution>
                                            <id>default-test</id>
                                            <phase>integration-test</phase>
                                            <goals>
                                                   <goal>test</goal>
                                            </goals>
                                            <configuration>
                                                   <skip>false</skip>
                                                   <includes>
                                                          <include>**/*TestSuitex.java</include>
                                                   </includes>
                                            </configuration>
                                     </execution>
                              </executions>
                       </plugin>
                </plugins>
         </build>