对 于多版本项目,要提供新版原本跟上新功能或缺陷报告增长的速度,并同时仍然保持可接受的质量水平,多是一项不小的挑战。构建自动化可确保准确性和消除人 为错误的可能性,从而部分地解决此问题。自动化还可以让成员将精力集中在须要人类智慧的问题上,而不用分心进行自动化后一般能更快更有效地运行的任务,从而 提升了团队效率。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 |