写在前边
微服务应用程序的另一个好处是更快且更容易更新。当开发者对一个传统的单体应用程序进行变更时,他们必须做详细的QA测试,以确保变更不会影响其他特性或功能。但有了微服务,开发者可以更新应用程序的单个组件。
微服务在带来好处的同时,同样也带来了挑战,具体可以总结为以下几点。
- 系统依赖性增加
由单体应用过渡到微服务架构时,需要加入更多的隔离组件,这些组件的加入势必会带来更多的依赖性。也就是说,复杂性会变得更高。这同样给测试带来了相应的复杂度,原本只需要从接口层开始的测试,一下子从深度上多出来更多的依赖,测试的工作量也是成倍地增加。
我们拿一个单体应用有10个接口的工程举例,原本测试只需要测试这10个接口就可以,但是使用微服务构建之后,接口的数量明显增加,每一个接口所衍生出来的新接口都需要测试,这样可能是一个倍数的关系。所以,微服务的接口抽象及经验就显得非常重要。
- 并行开发
接口数量的增加还会带来一个问题,就是原本一个团队维护的项目,被拆分之后,可能是两个或者更多的团队来进行维护。在需求变化时,一个接口的变动,导致的可能是连锁反应,当其中的一个接口出现延期时,整个测试计划就很难得到保证。团队需要等待其他团队以完整相关微服务的并行开发,微服务数量越多,需要考虑的对象就越广泛,这意味着以并行方式开发及发布新功能就变得更加困难。所以,微服务的并行开发同样带来了管理上的挑战。
- 与传统测试的冲突
对于单块应用,在一个机器上就可以模拟出所有的依赖,但是在微服务场景下,由于依赖的服务往往很多,因此要搭建一个完整的环境非常困难。
- 更多潜在的故障
微服务迁移的另一大负面影响在于引发大量独立故障点。
- 更多的团队交互
微服务的方式对于测试来说,意味着需要交互和沟通的人数必然增加,因为一般的团队很难做到需求和实现的高效沟通。沟通成本的增加有可能导致某个重要的功能点没得到优先测试,而不重要的功能点却被优先测试,从而导致整体工期的拖延。
微服务测试
在微服务中,测试是一个非常重要的环节,相比于常见的三层测试金字塔,在微服务场景下,这个层次可以被扩展为5层,如下图所示。
和测试金字塔的基本原则相同:
- 越往上,越接近业务/最终用户;越往下,越接近开发。
- 越往上,测试用例越少。
- 越往上,测试成本越高(越耗时,失败时的信息越模糊,越难跟踪)。
- 越往上,测试的实现和维护成本就越高,测试速度也越慢。
- 接下来看一下,上面的测试模型。
UI/UE 测试
需要测试的方面很多,包括功能测试、兼容性测试、安装卸载测试等。一般是根据业务模型编写测试用例,然后根据测试用例来判断结果的正确性与否。当然也包括测试用户界面的风格是否满足客户要求,文字是否正确,页面美工是否好看,文字、图片组合是否完美,背景是否美观,操作是否友好,等等。UI测试还可确保UI中的对象按照预期的方式运行,并符合公司或行业的标准,包括用户友好性、人性化、易操作性测试。UI测试比较主观,与测试人员的喜好有关,比如页面基调颜色刺眼、用户登录页面比较难以找到、文字中出现错别字、页面图片范围太广等都属于UI测试中的缺陷。严格来说,所有的测试都包括UI/UE 测试,不仅仅是在微服务测试中。
端对端测试
除了测试服务,测试者还需要确保无论使用何种架构构建,应用都必须实现业务目标,同时我们还要测试集成系统运行的完整性。因此在微服务测试方案中,端对端测试占据了重要的角色。除此之外,考虑到在微服务架构中有一些执行相同行为的可移动部件,端对端测试时需要找出覆盖缺口,并确保在架构重构时业务功能不会受到影响。
API 测试
API (Application Programming Interface, 简称API)又称为应用编程接口,就是软件系统不同组成部分衔接的约定。
API测试是针对系统所提供的API做各方面的验证。API 的功能测试类似于UI功能测试,都是在已知输入内容和期望结果的前提下,使用这个功能/调用这个API并且验证是否能返回期望的结果。不同的是,API测试在返回结果被呈现给客户前就完成了,从而对测试环境的依赖会比较小。
API功能测试的主要手段是使用工具/软件调用待测API,然后验证是否返回期望的output。这个output通常可能是:
- 返回成功或者失败的status;
- 一段数据或者information;
- 跳转到其他API。
组件接口测试
尽管单独测试模块非常重要,但测试各个模块能否正确交互,并测试其作为子系统的交互性以查看接口的缺陷同样重要,这项工作可以通过集成测试来完成。集成测试的目的在于:通过集成模块检查路径畅通与否,来确认模块与外部组件的交互情况。执行“网关集成测试”与“持续集成测试”能确保在找到外部组件间的逻辑回归与断裂之处时迅速获得反馈,从而有助于评估各个单独模块中所含逻辑的正确性。
单元测试
单元测试的范围局限在服务内部,它是围绕着一组相关联的案例编写的。由于单元测试的数量较多,理论上应当是以自动化方式执行的。在微服务中执行单元测试时,必须将协作型单元测试(Sociable Unit Testing)与孤立型单元测试( Solitary Unit Testing)相结合,通过观察其状态变化来检查模块行为,并查看对象及其依赖项之间的交互情况。然而,测试者需要确保在单元测试中,当单元“行为”受限时,“实现"不会受到测试的限制——可以通过不断将单元测试的价值与维护成本/实现受限的成本相对比来做到这一点。
单元测试
单元测试就是编写测试代码,用来检测特定的、明确的、细颗粒的功能。单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性。
一个良好的单元测试包括三个步骤:
- 准备测试环境和数据;
- 执行目标方法;
- 验证执行结果(判断程序的运行结果是否如你所想)。
在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至用代码覆盖率来考核测试任务完成情况,比如代码覆盖率必须达到80%或90%。
那么一般的代码覆盖率都包含哪些呢?通常的评估指标如下:
- 行覆盖率;
- 分支覆盖率;
- 路径覆盖率;
- 条件覆盖率;
- 状态机覆盖率。
目前很多公司已经意识到了单元测试的重要性,但国内坚持写单元测试的团队并不多,其中一个难点在于没有考量,没有很好地执行单元测试覆盖率检测。
API测试
对于API的测试,根据不同团队的不同情况,如果测试人员的编码能力强,则建议使用编码的方式进行,方便与持续集成系统进行集成。但是目前能够达到这种级别的测试少之又少,所以测试一般使用工具完成。
Postman最基础的功能就是发送HTTP请求,支持GET/PUT/POST/DELETE,还有很多其他HTTP方法。
通过填写URL、header、 body 等就可以发送一个请求, 这对于我们平时做一些简 单的测试是够用的。
每次配置完一个请求都可以保存到一个集合中,如此一来,下次测试可以直接从集合中找到你要执行的测试。
集合不单单只有分类和存储功能,Postman支持--键运行整个集合内的测试。
当然,也可以使用Hitchhiker。Hitchhiker是一款开源的 Restful API测试工具,支持Schedule、数据对比、压力测试、支持上传脚本定制请求,可以轻松部署到本地,和团队成员一起管理API。
A/B 测试
A/B测试又叫分离测试,类似于顾客焦点团体,将一系列内容变化在一定基准内进行比较。A/B测试来自邮件宣传,发信者将同一目的内容的不同版本邮寄到目标群体中,测量回应率。根据这些数据,商家可以对以后的直邮的内容做相应修改,向更多回应率的版本改进。
A/B测试最核心的思想,即:
- 多个方案并行测试;
- 每个方案只有一个变量不同;
- 以某种规则优胜劣汰。
事实上,完全可以设计多个方案进行测试,比如A B C测试,“AB测试”这个名字只是一个习惯的叫法。A/B测试需要将多个不同的版本展现给不同的用户,即需要一个“分流"的环节。分流可以在客户端做,也可以在服务器端做。传统的AB测试- -般是在服务端分流的,即基于后端的A/B测试(Back-end AB test)。当用户的请求到达服务器时,服务器根据一定的规则,给不同的用户返回不同的版本,同时记录数据的工作也在服务端完成。
基于前端的A/B测试的监控的粒度则更细一些,能够定位到具体的用户。利用前端JavaScript方法,在客户端进行分流,同时可以用JavaScript记录下用户的鼠标行为,甚至键盘行为,直接发送到对应的打点服务器。这样的好处是不需要技术部(如果前端工程师与后端工程师分属不同部门)参与,并且可以比较精确地记录下用户在页面上的每一个行为,甚至包括后端方法难以记录到的无效点击。
对于大部分需求来说,我们希望各个版本的访问人数平均分配。解决办法有很多种,比如根据某一个Cookie ID来划分用户,这需要为每一个用户植入-一个全局不重复的Cookie ID,因为规则是自定义的,所以可以根据CookieID的规则对流量进行切分。比如单数的显示A版本,偶数的显示B版本。因为Cookie ID 一般设定后不会轻易改变,但不足之处就是如果用户浏览器不支持Cookie, 则分流就不能正常进行了。不过,现代浏览器默认情况下都是支持Cookie的,所以如果出现这种小概率的情况,我们也可以在处理样本时忽略。
还有一点需要注意的是,A/B测试的页面必须有较高的UV,即独立访客数,因为分流带有一定的随机性,如果页面UV太小,分到每-一个版本的人数就更少,结果很有可能被一些偶然因素影响。而UV较大时,根据大数定理,我们得到的结果会接近于真实数据。
对于微服务的场景,我们可以使用网关进行分流,分流之后就可以定向采集需要的数据。采集的数据根据业务分析的需要,包括用户的浏览器版本、点击事件的搁置、点击的时间、访问的URL信息等。将采集到的数据存储到大数据平台,以供需要分析的部门进行二次加工分析。
静态代码分析
在软件开发过程中,开发团队往往要花费大量的时间和精力发现并修改代码缺陷。静态代码分析(static code analysis) 工具能够在代码构建过程中帮助开发人员快速、有效地定位代码缺陷并及时纠正这些问题,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数不匹配、有歧义的嵌套语句、错误的递归、非法计算、可能出现的空指针引用等。从而极大地提高软件可靠性并节省软件开发和测试成本。
常用的分析工具包括Checkstyle、FindBugs、 PMD等,下面我们来一起认识一下这些工具。
SonarQube 质量监控
Sonar ( SonarQube)是一个开源平台,用于管理源代码的质量。Sonar 不只是一个质量数据报告工具,更是代码质量管理平台。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具。
与持续集成工具(例如,Hudson/Jenkins 等)不同,Sonar 并不是简单地把不同的代码检查工具(例如,FindBugs、 PMD等)结果直接显示在Web页面上,而是通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。
在对其他工具的支持方面,Sonar不仅提供了对IDE的支持,可以在Eclipse 和IntelliJ IDEA这些工具里联机查看结果;同时Sonar 对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用Sonar。
此外,Sonar ( SonarQube)的插件还可以对Java以外的其他编程语言提供支持,对国际化及报告文档化也有良好的支持,支持的语言包括Java、PHP、C#、C、Cobol、PL/SQL、Flex等。
SonarQube可以从多个维度检测代码质量,包括以下维度。
- 复杂度分布(complexity): 代码复杂度过高将难以理解、难以维护。
- 重复代码(duplications): 程序中包含大量复制粘贴的代码是质量低下的表现。
- 单元测试(unittests):统计并展示单元测试覆盖率。
- 编码规范(coding rules):通过FindBugs、PMD、CheckStyle 等规范代码编写。
- 注释(comments): 少了可读性差,多了看起来费劲。
- 潜在的Bug (potential bugs):通过FindBugs、PMD、CheckStyle 等检测潜在的Bug。
- 结构与设计(architecture & design):依赖、耦合等。
后记
不论是自动化测试,还是质量管理,都只是一种实现手段;它们真正存在的价值在于提高代码质量和提高产品的持续交付能力。
在现在的软件开发过程中,能够自动化地实现测试和质量管理是非常重要的,既节省了测试和质量管理人员的成本,也提高了整体软件构建的速度,在AI大行其道的今天,必将成为微服务生态闭环中非常重要一个环节。
喜欢文章请多多点赞评论转发,关注小编,你们的支持就是小编最大的动力!!!