對 於多版本項目,要提供新版原本跟上新功能或缺陷報告增長的速度,並同時仍然保持可接受的質量水平,多是一項不小的挑戰。構建自動化可確保準確性和消除人 爲錯誤的可能性,從而部分地解決此問題。自動化還可以讓成員將精力集中在須要人類智慧的問題上,而不用分心進行自動化後一般能更快更有效地運行的任務,從而 提升了團隊效率。html
在本文中,咱們將瞭解如何實現構建過程的自動化,以得到較高的效率和質量。本文中的示例將利用 Rational 軟件交付平臺(IBM Rational Software Delivery, SDP)中的內置 Ant 支持(構建自動化過程做爲 Ant 構建文件實現)以及運行時(如 WebSphere Application Server)中的支持。本文最後將給出一些能夠用於進一步簡化此流程的可選功能。java
回頁首linux
儘管在構造* 階段以前並不會開始執行,但任務自動化應該在細化* 階段就進行規劃,以便在交付代碼進行測試以後即能供實現團隊使用。在進行了分析和設計後,組件的遠景以及應該如何對其進行構建、測試和部署就應該清楚了。 在此遠景的啓發下,應該以容許重複的方式開始完成任務自動化工做。web
爲 了便於進行重複,可能須要在開始前進行一些任務準備工做(如準備測試數據),並在完成後進行清理。對軟件配置管理(軟件存儲庫)、設計或目標部署環境的更 改也應該反映在任務自動化中。在工做預估和項目規劃期間,應該考慮實現和維護此自動化的開銷。能夠進行測試,以觀察任務自動化對具備多個迭代的項目的影 響,肯定什麼時候每一個迭代的構建、單元測試和部署的時間大幅度減小。編程
回頁首api
本文中的自動化過程適合於基於 Rational SDP 的工具,如:服務器
對於部署平臺,能夠將其用於使用 WebSphere Application Server 做爲基礎的 WebSphere 應用服務器系列,如 WebSphere Application Server、WebSphere Application Server Network Deployment 和 WebSphere Process Server。架構
示例過程能夠應用於其餘 Rational 和 WebSphere 產品。爲了簡單起見,咱們將所使用的工具稱爲集成開發環境(Integrated Development Environment,IDE)。併發
此過程能夠在各類環境配置上運行。圖 1 顯示了一個示例環境。
此環境包含一個或多個開發工做站,供開發人員編寫代碼之用。更改保存到存儲庫中。此處咱們假設使用 Rational ClearCase 存儲庫,爲每一個開發工做站提供了一個快照視圖。
開發工做站應該安裝了基於 Rational SDP 的工具。開發工做站應該具備配置爲使用軟件存儲庫的工做區。文章「使用 Rational Software Architect 和 ClearCase Remote Client」提供了關於如何使用 Rational ClearCase 進行此類配置的更多信息。還可使用其餘存儲庫;有關將 Ant 與併發版本系統 (Concurrent Versions System, CVS) 一塊兒使用的更多信息,請參見參考資料。
任何開發工做站均可以做爲構建工做站使用。最好將用於進行構建的工做站分離開,以免開發人員間出現使用競爭。構建工做站應該與任何其餘開發計算機具備相同的配置,並且可以訪問如下服務器:
能夠在 Windows® 或 Linux® 上實現典型的開發或構建工做站。對於目標部署服務器,WebSphere 產品提供了更爲普遍的受支持平臺。
全部自動化步驟都將包括在一個 Ant 構建文件中,以便進行維護。若是您尚不熟悉 Rational 工具,請按照如下所述進行操做:
ar-autotaskcode.zip
,並單擊 Finish。
build.xml
做爲文件名。單擊 Finish。(這就是咱們在此要涉及的全部步驟。)列出 Ant 構建文件,如清單 1 中所示。
<?xml version="1.0" encoding="UTF-8"?> <project name="Automation Project" default="init" basedir="."> <!-- Read project properties from a properties file. --> <property file="build.properties" /> <!-- A stub for the default target --> <target name="init" description="Initialize automation environment"> <!-- Set the standard DSTAMP, TSTAMP, and TODAY properties. --> <tstamp /> <!-- Set a variable to host environment variables. --> <property environment="env" /> <!-- Print the current WORKSPACE value. --> <echo message="Workspace: ${env.WORKSPACE}" /> <!-- Delete old export directory. --> <delete dir="${destination.dir}" /> <!-- Create the target export directory for the build. --> <mkdir dir="${destination.dir}" /> </target> </project>
能夠如今下載完整的 Ant 構建文件 ar-autotaskcode.zip。
在包含 Ant 構建項目的同一個目錄中建立屬性文件來存儲其屬性。ar-autotaskcode.zip 中也提供了完整的屬性文件。
如今 Ant 構建文件已經準備好開始添加表示自動化過程的新 Ant 目標了。
圖 2 顯示了構建自動化程序的摘要。
此部分將對這個過程的每一個步驟進行詳細描述。
第一步是從 ClearCase 存儲庫得到最新的代碼,如清單 2 中所示。
<target name="updateview" depends="init" description="Update ClearCase snapshot view"> <!-- update snapshot view --> <ccupdate viewpath="${workspace.dir}" graphical="false" overwrite="true"
currenttime="true" /> </target>
因爲工做區配置爲指向 ClearCase 視圖,更新視圖實際上將更新工做區內容。
能夠實現代碼檢查自動化。儘管不能消除手動代碼檢查需求,但建議的最佳實踐是,採用自動化檢查來肯定開發團隊在代碼質量標準方面所處的位置。Rational SDP 提供了內置的代碼檢查支持。(有關如何從 Ant 進行調用的更多信息,請參見 Code review headless mode reference。)
另外還可使用多種工具來執行自動化代碼檢查,如 PMD 和 CheckStyle。清單 3 中的示例說明了如何將 PMD 做爲 Ant 任務調用並生成 HTML 格式的結果。要運行此任務,須要將 pmd-3.8.jar、jakarta-oro-2.0.8.jar 和 jaxen-1.1-beta-10.jar 放置在 lib.dir 屬性所指定的目錄。
<target name="reviewcode" description="Review code using PMD"> <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpath="${lib.dir}/pmd-3.8.jar" /> <pmd shortFilenames="true"> <!-- Determine the ruleset to be used --> <ruleset>rulesets/favorites.xml</ruleset> <ruleset>basic</ruleset> <!-- Generate and HTML report into the designated directory --> <formatter type="html" toFile="${report.dir}/pmd_automated_code_review_report.html" /> <!-- Files to be configured for review --> <fileset dir="${workspace.dir}/"> <!-- Include all .java files except those under directories that are automatically generated --> <include name="**/*.java" /> <!-- A sample exlusion directory that has generated java source code --> <exclude name="**/generated/**/*.java" /> </fileset> </pmd> </target>
執行了此步驟後,將在 report.dir 屬性指定的目錄下找到 HTML 格式的 pmd_automated_code_review_report.html。(有關自動化代碼檢查的更多信息,請參見參考資料部分。)
如今咱們使用 IDE 中提供的內置功能來構建要包括在構建版本中的不一樣項目。
對於要在 IDE 中運行的 SDP 提供的 Ant 任務,Ant 構建文件須要在與工做區相同的 Java™ Runtime Environment (JRE) 中運行。不然,若是從命令行運行,runAnt 批處理文件將進行所需的初始化工做,以將這些任務的定義包括進來。這將在運行過程時的選項部分進行討論。清單 4 中的代碼使用 IDE 內置的「projectBuild」Ant 任務構建存在於工做區中的項目之一。
<target name="buildproject" description="Build a project"> <!-- Build the project with some options --> <projectBuild projectName="${project.name}" BuildType="full" failonerror="false" DebugCompilation="false" /> <!-- Print build errors --> <echo message="projectBuild: projectName=${project.name} project Error Count=${ProjectErrorCount} project Error Messages=${ProjectErrorMessages}" /> </target>
執行時可能出現的錯誤會輸出到控制檯,但構建不會終止。要更改此行爲,能夠將 failonerror
屬性設置爲 true
。
能夠經過將 project.name
屬性設置爲要構建的項目的名稱而爲不一樣的項目使用相同的目標,如清單 5 中所示。
<target name="buildall"> <!-- Invoke the "buildproject" target for a project from the workspace --> <antcall target="buildproject"> <!-- Pass the name of the project to be built --> <param name="project.name" value="MyFirstProject" /> </antcall> <!-- Invoke the "buildproject" target to build another project --> <antcall target="buildproject"> <!-- The project name is different --> <param name="project.name" value="MySecondProject" /> </antcall> </target>
有時候會忽略此步驟。爲所發佈的每一個構建版本使用一個版本號的方法對跟蹤缺陷和新添加的功能很是有用。Ant 提供了一個簡單 buildnumber 任務,可實現此目的。清單 6 顯示了根據須要記錄更多有關版本信息的另外一種方法。
<target name="baseline" description="Record build information"> <!-- The name of the file that holds the build information. If no such file exists, a new one gets created. --> <propertyfile file="${destination.dir}/build.info"> <!-- Initial build number is 0001. Then, any subsequent build increments
this number by one each time. --> <entry default="0001" key="build.number" operation="+" pattern="0000" type="int" /> <!-- Records the current time to the same file. --> <entry default="now" key="build.time" pattern="yyyy.MM.dd-HH.mm" type="date" /> </propertyfile> </target>
"baseline"
目標建立名爲 build.info 的文件,其中包含版本號和構建時間。若是該文件已存在,則會使用新版本號和構建時間對其進行更新。您可能須要在此文件中添加更多信息,如運行構建操做的用戶的名稱或建立構建版本的計算機的名稱。還能夠按照提取 "init"
目標中 WORKSPACE
環境變量的相同方法從環境提取此信息,如 Ant 構建文件中所述。
此步驟調用 JUnit 測試用例,這些用例不須要運行時資源(如數據源等)。咱們假定您已經得到了運行此步驟所需的此類測試用例。清單 7 說明了如何在工做區調用全部 JUnite 測試用例,並假設所有都以單詞「Test」做爲結尾。固然,若是命名約定不一樣,則能夠對此進行相應的更改。
<target name="predeptests" description="Invoke pre-deployment JUnit test cases"> <!-- Run JUnit and print a summary when done. --> <junit printsummary="yes" haltonfailure="no"> <classpath> <!-- Set the class path to include all needed classes that are used by the JUnit test cases. --> </classpath> <!-- Generate reports in an XML format --> <formatter type="xml" /> <!-- Run a batch of JUnit test cases and generate reports to the report directory. --> <batchtest fork="yes" todir="${report.dir}"> <fileset dir="${workspace.dir}/"> <!-- Include all .java files that end with "Test" --> <include name="**/*Test.java" /> </fileset> </batchtest> </junit> </target>
JUnit Ant 任務須要 junit.jar。能夠將其放在 "init"
目標中提到的 Ant 構建項目的屬性文件的 lib.dir 屬性指定的目錄下。可使用 JUnitReport Ant 任務將 JUnit 任務生成的報告轉換爲其餘格式。在咱們的示例中,報告將在 report.dir 屬性指定的目錄中生成。
在此步驟中,咱們要對可部署單元進行打包,以準備好在下一步中進行部署。清單 8 顯示瞭如何導出企業應用程序。
<target name="exportear" description="Export an Enterprise Application"> <!-- Export EAR file--> <earExport earprojectname="${project.name}"
earexportfile="${destination.dir}/${project.name}.ear" exportsource="false" IncludeProjectMetaFiles="false"
overwrite="true" /> </target>
與步驟 3(構建代碼)期間處理一組項目的方式相似,咱們能夠在導出企業應用程序時採用相同的方式。清單 9 中的代碼說明了如何進行此工做。
<target name="exportall" depends="buildall"
description="Export a set of Enterprise Applications"> <!-- Export an Enterprise Application --> <antcall target="exportear"> <!-- Pass the name of the project to be exported --> <param name="project.name" value="MyFirstEAR" /> </antcall> <!-- Export another Enterprise Application --> <antcall target="exportear"> <!-- The name of the other Enterprise Application --> <param name="project.name" value="MySecondEAR" /> </antcall> </target>
對於其餘項目類型,可使用 warExport
、ejbExport
和 jar
任務(分別用於導出 Web 模塊、EnterpriseJavaBeans (EJB) 模塊和 Java 庫)。這些都是 SDP 提供的 Ant 任務。
在此步驟中,咱們將部署上一步導出的單元。對於咱們的自動化過程,咱們將使用包裝 wsadmin
的內置 Ant 任務。清單 10 顯示了 wsListApps
、wsUninstallApp
和 wsInstallApp
Ant 任務,這些任務分別提供用於列出已安裝應用程序、卸載企業應用程序和安裝企業應用程序的管理功能。請記得在運行此步驟前啓動目標應用服務器。
關於 wsadmin 和 Ant
WebSphere Application Server Ant 支持基於其命令行管理工具 wsadmin
。做爲本文示例的替代方法,可使用 Exec Ant 任務調用 wsadmin
並按照調用任何其餘庫執行文件的方式傳遞程序參數。WebSphere Application Server 還提供了包裝 wsadmin
的 Ant 任務 WsAdmin。還有其餘包裝特定操做的 WsAdmin 任務的 Ant 任務,如應用程序安裝方面的 InstallApplication 和 StartApplication。咱們的示例中使用了後一個選項。
<target name="listapps" description="List installed Enterprise Applications"> <!-- Define the wsListApps task that lists installed Enterprise Applications. --> <taskdef name="wsListApps" classname="com.ibm.websphere.ant.tasks.ListApplications"> <!-- Include all JAR files under WebSphere Application Server lib directory. --> <classpath> <fileset dir="${was.home}/lib/" includes="*.jar" /> </classpath> </taskdef> <!-- List all installed Enterprise Application the profile specified. --> <wsListApps profilename="${was.profilename}" wasHome="${was.home}/" conntype="SOAP" host="${was.hostname}" port="${was.hostport}" user="${was.username}" password="${was.userpassword}" /> </target> <target name="uninstallapp" depends="listapps"
description="Uninstall an Enterprise Application"> <!-- Define the wsUninstallApp task that uninstalls an Enterprise Application. --> <taskdef name="wsUninstallApp"
classname="com.ibm.websphere.ant.tasks.UninstallApplication"> <!-- Include all JAR files under WebSphere Application Server lib directory. --> <classpath> <fileset dir="${was.home}/lib/" includes="*.jar" /> </classpath> </taskdef> <!-- Uninstall an Enterprise Application under the profile specified. --> <wsUninstallApp profilename="${was.profilename}" wasHome="${was.home}/" application="${project.name}" conntype="SOAP" host="${was.hostname}"
port="${was.hostport}" user="${was.username}" password="${was.userpassword}"
failonerror="false" /> <!-- Invoke listapps target to list installed applications. --> <antcall target="listapps" /> </target> <target name="installapp" depends="uninstallapp"> <!-- Define the wsInstallApp task that installs an Enterprise Application. --> <taskdef name="wsInstallApp" classname="com.ibm.websphere.ant.tasks.InstallApplication"> <!-- Include all JAR files under WebSphere Application Server lib directory. --> <classpath> <fileset dir="${was.home}/lib/" includes="*.jar" /> </classpath> </taskdef> <!-- Install an Enterprise Application under the profile specified. --> <wsInstallApp profilename="${was.profilename}" wasHome="${was.home}/"
ear="${destination.dir} /${project.name}.ear" conntype="SOAP"
host="${was.hostname}" port="${was.hostport}" user="${was.username}"
password="${was.userpassword}" failonerror="false" /> <!-- Invoke listapps target to list installed applications. --> <antcall target="listapps" /> </target>
根據須要部署的應用程序的數量不一樣,可使用 project.name 參數的不一樣值屢次調用 installapp
目標。installapp
目標將調用 uninstallapp
目標來確保企業應用程序已經卸載(若是已安裝)。兩個目標屢次調用 listapps
,以在卸載和安裝先後列出應用程序。清單 11 說明了如何進行此工做。
<target name="installallapps" description="Install all Enterprise Applications"> <!-- Invoke installapp target to install an Enterprise Application. --> <antcall target="installapp"> <!-- Pass the name of the Enterprise Application to be installed. --> <param name="project.name" value="MyAppEAR" /> </antcall> <!-- Another invocation to the installapp target can be done
for further installations. --> </target>
此步驟與運行部署前單元測試相似,不過 JUnit 測試用例的本質不一樣。部署後測試用例預期使用已經部署在運行時上且正在正常工做的代碼。這些測試用例能夠利用服務器端的資源和測試組件,如 Cactus。就構建自動化過程而言,此步驟只是調用一組 JUnit 測試用例。
設置了全部構建版本後,自動化過程會將庫部署單元和生成的報告上載到 FTP 服務器上。此步驟對於備份和保持整個構建版本的標識都很是有用。清單 12 中所示的目標說明了如何使用 FTP 來上載構建文件。
<target name="uploadbuild" description="Upload build to an FTP server"> <!-- Upload everything under the destination.dir to the FTP server. --> <ftp server="${ftp.hostname}" remotedir="/" userid="${ftp.username}" password="${ftp.userpassword}" separator="\" verbose="yes" binary="yes"> <fileset dir="${destination.dir}"> <include name="**/*.*" /> </fileset> </ftp> </target>
最後,該過程將向測試人員發送電子郵件(如清單 13中所示),告知其開始測試。如下示例假定不會在 SMTP 服務器上進行身份驗證。
<target name="notifyteam" description="Notify testing team of the new build"> <!-- Read build information from the build.info file. --> <property file="${destination.dir}/build.info" /> <!-- Send a mail to the testing team. --> <mail mailhost="${smtp.hostname}" mailport="${smtp.hostport}"
subject="Test build #${build.number}" from="${smtp.from}" tolist="${smtp.tolist}"> <message>The build #${build.number} is now available for testing.</message> </mail> </target>
若是您的 SMTP 服務器要求進行身份驗證,將須要下載 JavaMail .jar 文件。
本部分將簡單描述運行構建過程時一些可用的選項。
上面所述的自動化過程並不施加任何控制任務流的條件。若是須要此類控制,可使用容許某些任務中在出現錯誤時失敗的屬性。例如,wsInstallApp
任務具備用於此目的的 failonerror
屬性。
使用條件是控制流的另外一種方式。有關 Ant 中的條件的更多信息,請參見 Conditions task。Ant 還提供了依賴關係來在目標之間創建聯繫,以確保執行目標序列得以執行。
從 IDE 運行 Ant 構建文件很是簡單。如圖 3 中所示,能夠從 Ant 視圖中選擇出如今樹視圖下的 Ant 目標之一上的 Run Ant 選項。
在 Modify attributes and launch 對話框中,從 JRE 選項卡選擇 Run in the same JRE as the workspace,如圖 4 中所示。單擊 Apply 和 Run。
執行以後,輸出將打印到 Console 視圖,如圖 5 中所示。
<IDE installation directory>\rwd\eclipse\plugins\com.ibm.etools.j2ee.ant_6.0.1.XXX 下提供了有關自定義 Ant 來使用 Rational SDP 資源從命令行運行的信息。該目錄下提供了一個批處理文件 runAnt,可容許運行您的 Ant 構建文件。此批處理文件須要設置 WORKSPACE
環境變量。此變量指向包含自動化資源的工做區。能夠從命令行設置此變量,或者添加代碼行來指向 runAnt 批處理文件,如清單 14 中所示。
set WORKSPACE=C:\workspaces\MyWorkSpace runAnt.bat -buildfile <path to the Ant build file>\build.xml init
能夠不使用前一示例中的 init
目標,而以相似的方式調用 Ant 構建文件中的其餘目標。
因爲此構建過程已自動化,開發團隊可能會決定天天都要執行此過程,具體取決於其須要提供構建版本進行測試的頻率。此執行能夠爲部分執行(運行 Ant 目標的子集),也能夠徹底執行。在這兩種狀況下,能夠對過程進行計劃,以按所需的頻率運行。有關如何在 Windows 平臺上進行任務計劃的更多信息,請參見「使用 WebSphere Studio 和 Ant 執行無人值守的平常構建——第 2 部分」。
學習本文後,但願您已經經過使用實現軟件開發團隊的重複構建任務的自動化的過程提升了效率和質量。所使用的構建自動化過程僅僅是 Rational and WebSphere 系列軟件產品提供的自動化功能的一個子集。您將須要對此過程進行調整,以與工做環境、所使用的工具和運行時、團隊的知識以及所開發的解決方案類型匹配。
做者要感謝 Nouran Abdel-Hamid、Rosaline Makar、Amr Ali 和 Ahmed Mamdouh:正是得益於您們的工做,才最終獲得了這個自動化解決方案。
描述 | 名字 | 大小 |
---|---|---|
Automation Scripts | ar-autotaskcode.zip | 3KB |