测试开发

《JUnit实战》第10章 从Maven2中运行JUnit 测试(续1)

10.1.3  Maven的构建生命周期

在Maven中,另一条强大的原则是构建生命周期 (build lifecycle)。Maven项目围绕着定义构建过程、测试和分发一个特定工件的理念而被构建。Maven项目能够生成唯一的工件。这样我们就能够使用Maven来构建项目的工件,或者整理项目的目录结构,或者生成项目的文档。为了定义Maven的3个内置生命周期,我们使用 Maven的操作如下:

Default——用于生成项目的工件。

Clean——用于清理项目。

Site——用于生成项目的文档。

每个生命周期都包含了几个阶段(phase),并且为了通过某个生命周期,构建就必须遵循它的阶段。

以下列出了Default生命周期的所有阶段:

Validate———验证项目是正确的,并且所有必要的信息都是可获得的。

Compile——编译项目的源代码。

Test——使用一个合适的单元测试框架来测试编译好的源代码。这些测试应该不会要求代码被打包或者部署。

Package———将编译好的代码打包成可以发布的格式,如JAR。

Integration test———如果有必要,将发布包处理和部署到一个可以运行集成测试的环境中。

Verify——运行任何检查来证实该发布包是有效的并符合质量标准的。

Install——将发布包安装到本地仓库中,以便用作其他本地项目中的一个依赖库。Deploy——在一个集成或者发布环境,为了与其他的开发人员和项目进行共享,将最终版的发布包复制到远程仓库( remote repository)中。

你是否还记得,在使用Ant时,我们几乎拥有相同名称的目标 (target)。是的,Ant中的目标就类似于Maven中的阶段,除了一个例外。在Ant中,你编写了目标并且指定了哪个目标依赖于其他的哪个目标。而在使用 Maven时,我们在此再次看到了“约定优于配置”原则。这些阶段已经按照上文列出的先后顺序定义好了。而且,Maven会按照严格的顺序来调用这些阶段:它们按照以上列出的顺序依次被执行,从而完成整个生命周期。这就意味着,如果你调用它们中的任何一个,例如,你在项目的主目录下的命令行中输入:

mVn compile

那么Maven将会首先验证(validate)项目,然后再试着编译(compile)项目的源代码。

最后要注意的是,把所有的这些阶段看作扩展点是非常有用的。在任何时刻,你都可以把一些额外的Maven 插件添加到阶段中,并且可以精心安排这些插件被执行的顺序和方式。

10.1.4 基于插件的架构

我们将要介绍的最后一个 Maven的功能是它基于插件的架构。在这一章的开头,我们就提到Ant是一个构建源代码的框架,而Maven是一个构建源代码的环境。更具体地说,Maven是一个集插件、执行和构建源代码于一体的环境。项目的核心部分是很小的,但项目的架构允许添加多个插件到核心部分,所以Maven构建了一个可以执行不同插件的环境。

在指定的生命周期中的每一个阶段都添加了一些插件到本阶段中,并且当按照插件被声明的顺序经历指定的阶段时,Maven就会调用这些插件。下面列出了一些Maven核心的插件。

Clean插件——在构建之后清除。

Compiler插件——编译 Java源代码。

Deploy插件——将构建的工件部署到远程仓库。

Install插件—将构建的工件安装到本地合库。

Resources插件——将资源复制到输出目录下,以便包含在JAR中。

Site插件—为当前项目生成一个站点。

Surefire插件——在一个隔离的类加载器中运行JUnit测试。

Verifier插件——对于集成测试非常有用,验证某种条件的存在。

除了这些核心的Maven插件,还有几十种其他的Maven 插件,每一种插件应对于你可能遇到的某一种情况,如 WAR插件、Javadoc插件、AntRun插件以及你自己命名的任何插件。

插件在构建配置文件的plugins部分中被声明,例如:

image.png

image.png

正如你所看到的,每一个插件的声明都指定了groupId、artifactId和版本。带有这些信息的插件看起来很像依赖库,是不是?是的,的确是这样,并且它们以同样的方式被处理——它们被下载到本地仓库中,与下载依赖库的方式相同。当指定一个插件时,groupId 和版本是可选参数;如果你不声明它们,则 Maven将会寻找一个被指定artifactld 参数的插件和以下任意一个groupId: org.apache.maven.plugins 或org.codehaus.mojo。版本也是可选的。如果你正在使用2.0.9版本之前的 Maven,那么Maven将会试图下载能够获取的最新版本。但是,从Maven 2.0.9版本开始,大部分插件的版本被锁定在Super POM(即 Maven的缺省POM)中,所以,Maven将不再下载最新的版本。为了避免自动更新和不可重写的构建,强烈推荐锁定插件的版本。

在 Maven项目外部还有大量的其他插件可以使用,但这些插件只能与Maven一起使用。形成这种情况的原因就是,编写Maven插件实在是太简单了。

10.1.5 Maven项目对象模型

如果你还记得Ant有一个默认命名为build.xml的构建文件,这个文件保存了所有关于构建的信息。在这个文件中,我们以任务和目标的形式指定了所有我们想要完成的事情。

那么在 Maven中类似于Ant的 build.xml构建文件又是什么呢? Maven也有一个构建描述文件,默认命名为pom.xml,取自于Project Object Model (POM)的简写。与Ant相比,在 Maven的项目描述符中,我们不必指定我们想做的事情;但我们要为项目本身指定通用的信息,如代码10.1所示。

image.png

它看起来非常简单,是不是?但这个时候冒出来一个大问题:“Maven如何能够使用如此少的信息来构建我们的源代码?”

答案在于pom.xml的继承功能:每一个简单的pom.xml都从一个Super POM继承了大部分的功能。就像在Java中,每一个对象都会从java.lang.Object对象继承某些方法,Super POM为每一个 pom.xml授权了Maven的功能。

你看到了Java和 Maven之间的相似性。这种相似性甚至可能比你想象得还要高:Maven的多个pom.xml 能够彼此相互继承,就像在 Java中,一些类能够成为其他类的parent。例如,如果我们想要使用代码10.1中的pom作为 parent,我们所要做的就是将它的packaging值修改为pom。父项目和聚合(多模块)项目可能只有pom作为packaging值。我们也需要在parent中定义子模块,如代码10.2所示。

image.png

这段代码是代码10.1的延续。我们通过声明这个包为pom类型1和添加一个modules部分②,从而声明了这个pom是一个聚合模块。modules部分通过为项目目录(如

example-module)提供相对路径,列出了模块所拥有的所有子模块。

代码10.3给出了子pom.xml的详细代码。

image.png

要记住这个子pom.xml位于父pom.xml已声明的目录(如example-module)中。这里要特别注意两点。第一,因为我们从一些其他的pom继承,所以这里不需要为子pom 指定 groupId和version;第二,Maven默认它们会与父pom的 groupid和version保持一致。

考虑到与 Java的相似性,我们自然而然会产生一个疑问:“究竟pom可以从父pom那里继承什么类型的对象呢?”以下列出了一个 pom能够从它的父pom继承的所有元素:

依赖库;

开发者和贡献者;

插件列表;

报告列表;

ID 匹配的插件执行;

插件配置。

此外,每一个在父pom中被指定的元素都会自动被继承到子pom中。在接下来的章节中,我们将会更深人地讨论pom。

相关内容

文章评论

表情

共 0 条评论,查看全部
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~