環(huán)境背景:
我作為項目經(jīng)理和技術架構管理人員負責公司一條生產線。討論之后,首席架構師希望我們能夠實施TDD。在實施TDD的過程中,設計實施過程的整體思路就是:單元測試用例文檔 - 實施單元測試 - 實施業(yè)務代碼 – 修改業(yè)務代碼邏輯。實施人員需要參與每個環(huán)節(jié),按照規(guī)范編寫單元測試用例文檔。單元測試我們按照模塊(模塊與人員基本沒有重合)劃分包(suite),保證實施起來不會產生干擾。。技術架構決定采用:maven,junit,svn。
技術背景:
技術架構設計上,我們封裝了dao層的實現(xiàn),所以實施人員基本無需涉及dao層的開發(fā)。服務層我們采用了JAX-RS的服務規(guī)范,對外開發(fā)服務接口。
在測試覆蓋率方面,我們基本不要求對dao層的單元測試,但要求在服務層的單元測試達到100%。由于服務層是Restful WS的模式,所以我們采用了模擬HTTP請求的方式在測試服務層。
由于需要模擬HTTP的請求,所以我們在單元測試中采用了jetty作為內嵌服務器,單元測試開始時同一啟動,完成后關閉。
實施過程:
開發(fā)過程中,實際實施的時候發(fā)現(xiàn)一個問題,對于測試數(shù)據(jù)的管理問題。即測試當中需要一定的數(shù)據(jù)環(huán)境來驗證業(yè)務邏輯。這個數(shù)據(jù)環(huán)境如何建立?
方案一,使用dbunit和hsqldb。在測試啟動時重建數(shù)據(jù)環(huán)境。
否決,原因:
1.與實際運行環(huán)境差異較大。
2.反復重建數(shù)據(jù)環(huán)境,效率上有缺失。
3.技術架構增加,學習和維護曲線較大。
討論后決定使用
方案二,獨立出一套測試數(shù)據(jù)庫,完整數(shù)據(jù)環(huán)境??紤]到增刪改與查詢的沖突,制定默認規(guī)則,如id在20之內的不允許進行任何改動。以盡量隔離增刪改的影響。
針對方案二,有一個較大的問題,如何在開發(fā)過程中自由的切換數(shù)據(jù)庫配置呢?由于我們還是用了Hudson作為CI服務器,還要考慮到打包的過程。整體考慮之后,有兩個步驟需要注意:
一、開發(fā)過程。開發(fā)過程中,我們將配置直接指向測試數(shù)據(jù)庫。
二、打包過程。使用了maven,存在單元測試配置與最終產品配置的沖突。
所以最終問題的焦點集中在打包過程的maven配置方案。
搜索之后比較好的資料有
MAVEN:如何為開發(fā)和生產環(huán)境建立不同的配置文件 --我的簡潔方案
(http://www.tkk7.com/scud/archive/2010/10/27/336326.html)
這篇博客是介紹在maven 中使用mvn package -P test 這樣的自定義profile來實現(xiàn)的。這樣是可行的,但是在Hudson中無法實現(xiàn)一條命令切換兩套配置。
于是繼續(xù)尋找,最終在maven的官方網(wǎng)站找到《Building For Different Environments with Maven 2》(http://maven.apache.org/guides/mini/guide-building-for-different-environments.html)看完文章之后發(fā)現(xiàn),實際maven提供了一個非常好的插件maven-antrun-plugin,以實現(xiàn)某些ant的功能。此處還需要了解的知識就是maven的構建生命周期標準(http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)?;谏鲜鰞蓚€知識點,我們制定出如下方案,在項目中建立測試配置目錄及產品配置目錄,在maven的package階段開始前,都使用測試配置,運行集成測試,完成在package階段前將產品配置覆蓋至打包文件夾內,然后進行打包。思路就是這樣,下面貼出pom文件的關鍵部分。
POM.xml
<!—profile 節(jié)點定義覆蓋文件的方式內容 -->
<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>