在上面几节课中,我们陆续介绍了微服务架构的主要测试类型。现在,让我们再回顾一下它们的特点:
- 单元测试:对生产代码中最小的可测试片段进行检查,判断其是否符合预期。
- 集成测试:检查模块的组合能否发挥作用,以及模块和外部服务、资源、数据库的通信是否正常。
- 组件测试:以单个微服务作为对象,通过内部接口和外部模拟,将微服务与外界隔离开,测试其功能。
- 契约测试:在各个微服务之间的接口上,检查它们的交互是否符合预期标准。
- 端到端测试:从整个产品/系统的角度,进行端到端的检查,判断是否符合外部要求和达到其目标。
总而言之,从上到下,测试的粒度由细到粗。一种测试的粒度越粗,涉及的部分就越多,也就越脆弱(容易误报),执行和维护的成本就越高。接下来,我们就可以用 TeamCity 或者 Jenkins 这样的调度工具,建立起一个支持持续集成/持续交付(CI/CD)的自动测试流水线。本课将详细介绍这方面的常用方法和工具。
什么是 CI/CD
持续集成(Continuous Integration)是指,在开发人员提交了新代码之后,立刻进行构建(Build)、测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。
Martin Fowler 说:“持续集成并不能消除 Bug,而是让它们非常容易发现和改正。”这样的软件开发实践,要求开发团队必须经常集成他们的工作,而不是等到一周、一个月甚至几个月之后才进行集成和测试。这符合现在最流行的测试理念:“Moving Left”(越早测试越好)。测试的提前,意味着尽早发现缺陷,解决缺陷的成本也越低。
持续交付(Continous Delivery)在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的“类生产环境”(Production-like Environments)中。例如,我们完成单元测试、集成测试、组件测试、契约测试之后,可以把代码部署到连接数据库的过渡(Staging) 环境中,进行端到端测试。如果这些测试都没有问题,可以继续部署到实际生产环境中。持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件都是随时随地可以交付的。
另外,还有一个持续部署(Continuous Deployment)的概念,是指在持续交付的基础上,把部署到生产环境的过程进一步自动化。持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。
这三个过程可以用下图来表示:
自动测试流水线
在本课程中,我们将重点介绍CI/CD中关于测试的部分。一个常见的测试流水线可以表现为:
所谓“流水线”的意思是,只有上一步成功通过,才会触发下一步操作。在单个微服务的测试完成之后,再会触发下一步、结合多个微服务的端到端测试。所有这些过程,必须归于一个自动化的周期性的集成测试过程,从检测代码、编译构建、运行测试、结果记录、测试统计等都是自动完成的,无需人工干预;需要有专门的集成服务器来执行集成构建;需要有代码托管工具支持。目前主流的 CI/CD 自动化调度工具,包括 TeamCity 和 Jenkins。
Jenkins 是一个开源的、基于 Java 的 CI 服务器软件包,经常用于 Java 项目,但是也适用于 .NET 项目,因为可以兼容很多常见的 .NET 版本控制系统,支持 MSBuild 脚本。作为免费开源软件,它拥有非常活跃的插件开发社区。Jenkins的主要部分是一个运行在Java Servlet容器(例如Apache Tomcat)内的服务器。
TeamCity是一个由 JetBrains 公司开发的、基于 Java 的商业 CI 服务器软件,特点是安装和配置极为简便。虽然基于 Java,但一样适用于 .NET 项目。主要通过浏览器界面管理用户、代理、项目和构建配置。
下面是对这两个工具的比较:
特性 | Jenkins | TeamCity |
---|---|---|
免费开源 | 是 | 否 |
广泛使用 | 是 | 是 |
文档齐全 | 是 | 是 |
便于设置、使用和配置 | 否 | 是 |
安全性(缺省配置) | 否 | 是 |
邮件通知 | 是 | 是 |
日志功能 | 是 | 是 |
动态地为多个分支运行构建任务 | 是 | 否 |
独立验证 | 否 | 是 |
端口可设置 | 否 | 是 |
下面我们将以功能设置相对较为简单的 TeamCity 为例,说明如何安装、配置和添加自动化测试任务,建立起流水线。
利用 TeamCity 建立自动测试流水线
安装 TeamCity 2017.x
TeamCity 最新版本为2017.2。下面说明在 Linux 服务器环境下如何安装 TeamCity(Windows 服务器环境中也可以安装,步骤类似,请参考官方网站说明)。
- 安装环境要求:
- JDK 1.8 以上
- 安装包下载:点击这里进行下载。
- 开始安装:
- 解压压缩包:
tar zxf TeamCity.tar.gz
- 关于解压完的目录结构,请参考这里。
- 建议把解压缩的目录放在
usr
目录下:mv TeamCity/ /usr/program/
- 进入解压目录:
cd /usr/program/TeamCity/
- 启动程序:
/usr/program/TeamCity/bin/runAll.sh start
- 停止程序:
/usr/program/TeamCity/bin/runAll.sh stop
- 解压压缩包:
如果是 Windows 平台安装 TeamCity,有一个好处就是可以安装为两个服务,一个是 TeamCity Server,一个是 TeamCity build Agent。这样,以后需要管理 TeamCity 状态时,会更方便一些,譬如安装了插件之后,可以通过重启服务来达到重启整个服务器的作用。
在 Docker 下安装 TeamCity 的方法
近来基于 Docker 的虚拟化服务越来越流行,Docker 非常便于配置和扩展,可以满足快速迭代和更新的需要。如果需要在 Docker 中启用 TeamCity 也同样简单。TeamCity 对应的 DockerHub 页面在这里。
首先要做的是获取 TeamCity 镜像。
获取镜像之后启动它的实例即可。下面是官方页面上给出的例子,当然其中的几个名称和文件位置可以根据需要自行修改。
配置TeamCity 2017.x
基本过程主要包括以下几步:
- 启动 TeamCity;
- 访问:http://localhost:8111/;
- 如果访问不了,请先关闭防火墙:
service iptables stop
; - 也可以选择把端口加入白名单中:
sudo iptables -I INPUT -p tcp -m tcp --dport 8111 -j ACCEPT
sudo /etc/rc.d/init.d/iptables save
sudo service iptables restart
- 如果要改变端口,可以修改下面这个文件中的8111:
vim /usr/program/TeamCity/conf/server.xm
。
- 进入 TeamCity 的设置向导:
- 如上图所示,TeamCity 的一些软件安装的配置、服务的配置默认都会放在
/root/.BuildServer
下面。 - 关于 TeamCity Data Directory 目录,请参阅这里。
- TeamCity 的一些构建历史、用户信息、构建结果等数据需要放在关系型数据库中,并默认内置了一个
Internal(HSQLDB)
。建议缺省使用该数据库,这样无需在一开始使用时就考虑数据库迁移或安装的问题。之后如果需要还可以更换。 - 之后,完成数据库的初始化,进入:http://localhost:8111/profile.html?tab=userGeneralSettings,可以完成管理员帐号的设置。
- 如果有 SMTP 的邮箱,可以开启邮件通知功能:http://localhost:8111/admin/admin.html?item=email
- 通知内容的模板可以设定,请参考这里。模板存放路径在
/root/.BuildServer/config/_notifications
,用的是 FreeMarker 的语法。
新建项目
第一次使用 TeamCity 的时候会提示新建项目。之后如果要新建项目,点击右上角的 Administration 即可。新建项目时需要提供项目代码的 URL,支持 Git、SVN 等工具,如下图所示:
设置构建步骤 (Build Step)
持续集成工具需要管理项目的整个生命周期,所以仅仅添加了项目还是不够的,下一步是要设置具体的项目构建步骤(Build Step)。不同的项目可能有不同的构建过程,这部分是设置的重点。
如果是 Java 项目,选用了 Maven 或 Gradle 这样的构建工具来管理项目,那么 TeamCity 只需要自动检测就可以完成所有配置步骤。如果没有使用这样的工具,那么就需要自己设置构建过程了。对于 .NET 程序,如果使用了自动检测功能的话,TeamCity 会自动帮你添加一个 Visual Studio(sln)步骤。不过仅仅这一步还不够,需要添加其他步骤。
首先考虑到项目中可能使用多种第三方库,而在 .NET 平台下第三方库一般使用 NuGet 获取。所以需要添加一个 NuGet 步骤。首先点击上图中的 configure build steps manually
,然后选择 NuGet Installer
类型,在弹出的界面中设置相应的选项。
然后需要设置构建步骤,选择 Visual Studio(sln)即可。
这样,构建步骤算初步完成了。
下一步可以开始构建(Build)项目了。点击页面上面的 Projects,切换回项目视图。然后点击项目右边的 Run 即可。这时候构建代理(Build Agent)右边的空白框也会变成蓝色,表示正在构建项目。等待片刻,项目就会构建完毕。一个构建任务就完成了。
新建自动化测试任务
在完成上述步骤之后,下面我们就可以开始着手建立我们的自动测试流水线了。首先点击对应项目的 Build 链接,然后点击构建设置(Settings),并在页面下方找到构建步骤。
在上一节中我们添加了两个步骤,这里继续添加一个测试步骤。新建一个步骤,类型选择 Visual Studio Tests,这是 Visual Studio 自带的单元测试框架。在Visual Studio Tests 下还有两个类型,MSTest 和 VSTest。它们的区别在于 VSTest 需要 TeamCity 构建代理服务器上同时安装有 Visual Studio 或者 Visual Studio Test Agent。然后“Test file names”这里需要填写测试文件的名称,只要填写相对路径就行了。最后如果需要检查测试覆盖率,还可以设置最后的 .NET Coverage tool。
设置完成后再次运行构建命令,可以看到这次不仅构建了项目,还同时运行了测试,测试结果也会一并显示。如果点击进入详情查看,还会获得更丰富的结果。因为本例中选择了代码覆盖率功能,可以方便看到图表的显示。
按照这样的方法,可以依次为所有的测试,包括单元测试、集成测试、组件测试、契约测试、端到端测试等,都建立相应的测试步骤(Build Step)。再通过自动触发的方式串联起来。如下图所示,触发器的设置在项目设置中,如果需要其他触发器设置在这里更改即可。
选择上图中的“Finish build trigger”,就表示在指定的测试任务结束之后触发当前任务。
如果选择 VCS Trigger,再勾选“Trigger a build on each check-in”,就表示每当有代码改动时就执行此构建任务。其他常用的设置还包括每天定时执行(Schedule Trigger)等选项。
这样,一环接一环,就构成了一个完整的自动测试流水线。
手动测试
前面所有课程系统介绍了微服务自动化测试的各个阶段工作,最后一步将是手动测试。如果有了完善的自动测试,手动确认的工作实际上可以非常简单。这一步的关键是要引入业务知识专家(Domain Expert),从用户的角度来探索产品的功能。可以借助微软 Azure 的 ApplicationInsight,或者谷歌云的 Analytics 等工具,记录下这些专家的行为,作为以后自动化测试的用例参考。本课程主要关注自动化测试,对手动测试的方法将不做深入探讨。
本课总结
本节课介绍了下列内容:
- 持续集成/持续交付/持续部署的概念和流程;
- 自动测试流水线的含义;
- 怎么用常见的 CI 工具 TeamCity 建立自动测试流水线;
- 手动测试的方法简述。
到目前为止,本达人课基本上已经涵盖了微服务测试的方方面面。下一节课,我将从自己的一些实践经验和体会,谈谈测试人员在微服务时代的角色演变,即怎么从单纯的测试人员,转向更为全面的 TestOps 人员。