请选择 进入手机版 | 继续访问电脑版

技术控

    今日:46| 主题:53299
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] 微服务场景下的自动化测试

[复制链接]
我的闺蜜会发光 发表于 2016-10-2 12:41:16
325 5

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
新的挑战

   微服务和传统的单块应用相比,在测试策略上,会有一些不太一样的地方。简单来说,在微服务架构中,测试的层次变得更多,而且对环境的搭建要求更高。比如对单块应用,在一个机器上就可以setup出所有的依赖,但是在微服务场景下,由于依赖的服务往往很多,要搭建一个完整的环境非常困难,这对团队的 DevOps 的能力也有比较高的要求。
  相对于单块来说,微服务架构具有以下特点:
  
       
  • 每个微服务在物理上分属不同进程   
  • 服务间往往通过 RESTful 来集成   
  • 多语言,多数据库,多运行时   
  • 网络的不可靠特性   
  • 不同的团队和交付周期  
  上述的这些微服务环境的特点,决定了在微服务场景中进行测试自然会面临的一些挑战:
  
       
  • 服务间依赖关系复杂   
  • 需要为每个不同语言,不同数据库的服务搭建各自的环境   
  • 端到端测试时,环境准备复杂   
  • 网络的不可靠会导致测试套件的不稳定   
  • 团队之间的 沟通成本  
  测试的分层

   相比于常见的 三层测试金字塔 ,在微服务场景下,这个层次可以被扩展为5层(如果将UI测试单独抽取出来,可以分为六层)。
  
       
  • 单元测试   
  • 集成测试   
  • 组件测试   
  • 契约测试   
  • 端到端测试  
   

微服务场景下的自动化测试

微服务场景下的自动化测试

  和测试金字塔的基本原则相同:
  
       
  • 越往上,越接近业务/最终用户;越往下,越接近开发   
  • 越往上,测试用例越少   
  • 越往上,测试成本越高(越耗时,失败时的信息越模糊,越难跟踪)  
  单元测试

  单元测试,即每个微服务内部,对于领域对象,领域逻辑的测试。它的隔离性比较高,无需其他依赖,执行速度较快。
  对于业务规则:
  
       
  • 商用软件需要License才可以使用,License有时间限制   
  • 需要License的软件在到期之前,系统需要发出告警  
        
  1. @Test
  2. public void license_should_expire_after_the_evaluation_period() {
  3.     LocalDate fixed = getDateFrom("2015-09-03");
  4.     License license = new License(fixed.toDate(), 1);
  5.     boolean isExpiredOn = license.isExpiredOn(fixed.plusYears(1).plusDays(1).toDate());
  6.     assertTrue(isExpiredOn);
  7. }
  8. @Test
  9. public void license_should_not_expire_before_the_evaluation_period() {
  10.     LocalDate fixed = getDateFrom("2015-09-05");
  11.     License license = new License(fixed.toDate(), 1);
  12.     boolean isExpiredOn = license.isExpiredOn(fixed.plusYears(1).minusDays(1).toDate());
  13.     assertFalse(isExpiredOn);
  14. }
复制代码
       上面这个例子就是一个非常典型的单元测试,它和其他组件基本上没有依赖。即使要测试的对象对其他类有依赖,我们会Stub/Mock的手段来将这些依赖消除,比如使用 mockito / PowerMock 。
  集成测试

  系统内模块(一个模块对其周边的依赖项)间的集成,系统间的集成都可以归类为集成测试。比如
  
       
  • 数据库访问模块与数据库的集成   
  • 对外部 service 依赖的测试,比如对第三方支付,通知等服务的集成  
   集成测试强调模块和外部的交互的验证,在集成测试时,通常会涉及到外部的组件,比如数据库,第三方服务。这时候需要尽可能真实的去与外部组件进行交互,比如使用和真实环境相同类型的数据库,采用独立模式(Standalone)的 WireMock 来启动外部依赖的RESTful系统。
  通常会用来做模拟外部依赖工具包括:
  
       
  • WireMock   
  • mountebank  
  其中,mountbank还支持Socket级别的Mock,可以在非HTTP协议的场景中使用。
   

微服务场景下的自动化测试

微服务场景下的自动化测试

  组件测试

   贯穿应用层和领域层的测试。不过通常来说,这部分的测试不会访问真实的外部数据源,而是使用同 schema 的内存数据库,而且对外部service的访问也会使用Stub的方式:
  
       
  • 内存数据库   
  • Stub外部服务( WireMock )   
  • RestAssured  
   比如使用 h2 来做内存数据库,并且自动生成schema。使用WireMock来Stub外部的服务等。
        
  1. @Test
  2. public void should_create_user() {
  3.     given().contentType(ContentType.JSON).body(prepareUser()).
  4.             when().post("/users").
  5.             then().statusCode(201).
  6.             body("id", notNullValue()).
  7.             body("name", is("Juntao Qiu")).
  8.             body("email", is("[email protected]"));
  9. }
  10. private User prepareUser() {
  11.     User user = new User();
  12.     user.setName("Juntao Qiu");
  13.     user.setEmail("[email protected]");
  14.     user.setPassword("password");
  15.     return user;
  16. }
复制代码
       如果使用Spring,还可以通过 profile 来切换不同的数据库。比如下面这个例子中,默认的profile会连接数据库 jigsaw ,而 integration 的profile会连接 jigsaw_test 数据库:
        
  1. spring:
  2.   datasource:
  3.     url: jdbc:mysql://localhost:3306/jigsaw
  4.     driver-class-title: com.mysql.jdbc.Driver
  5.     username: root
  6.     password: password
  7. ---
  8. spring:
  9.   profiles: integration
  10.   datasource:
  11.     url: jdbc:mysql://localhost:3306/jigsaw_test
  12.     driver-class-title: com.mysql.jdbc.Driver
  13.     username: root
  14.     password: password
复制代码
      组件测试会涉及到的组件包括:
  
       
  • URL路由   
  • 序列化与反序列化   
  • 应用对领域层的访问   
  • 领域层对数据的访问   
  • 数据库访问层  
  前后端分离

  除了后端的测试之外,在目前的前后端分离场景下,前端的应用越来越复杂,在这种情况下,前端的组件测试也是一个测试的重点。
  一个前端应用至少包括了这样一些组件:
  
       
  • 前端路由   
  • 模板   
  • 前端的MVVM   
  • 拦截器   
  • 事件的响应  
   要确保这些组件组合起来还能如预期的执行,相关测试必不可少。这篇文章详细讨论了前后端分离之后的测试及开发实践。
  契约测试

   在微服务场景中,服务之间会有很多依赖关系。根据 消费者驱动契约 ,我们可以将服务分为消费者端和生产者端,通常消费者自己会定义需要的数据格式以及交互细节,并生成一个契约文件。然后生产者根据自己的契约来实现自己的逻辑,并在持续集成环境中持续验证。
   Pact 已经基本上是 消费者驱动契约 (Consumer Driven Contract)的事实标准了。它已经有多种语言的实现,Java平台的可以使用 pact-jvm 及相应的 maven / gradle 插件进行开发。
  
       
  • pact / pact-jvm   
  • pact-broker  
   

微服务场景下的自动化测试

微服务场景下的自动化测试

   (图片来源: Why you should use Consumer-Driven Contracts for Microservice integration tests )
  通常在工程实践上,当消费者根据需要生成了契约之后,我们会将契约上传至一个公共可访问的地址,然后生产者在执行时会访问这个地址,并获得最新版本的契约,然后对着这些契约来执行相应的验证过程。
  一个典型的契约的片段是这样的(使用pact):
        
  1. "interactions": [
  2.     {
  3.         "description": "Project Service",
  4.         "request": {
  5.             "method": "GET",
  6.             "path": "/projects/11046"
  7.         },
  8.         "response": {
  9.             "status": 200,
  10.             "headers": {
  11.                 "Content-Type": "application/json; charset=UTF-8"
  12.             },
  13.             "body": {
  14.                 "project-id": "004c97"
  15.             },
  16.             "matchingRules": {
  17.                 "$.body.project-id": {
  18.                     "match": "type"
  19.                 }
  20.             }
  21.         },
  22.         "providerState": "project service"
  23.     }
  24. ]
复制代码
      端到端测试

  端到端测试是整个微服务测试中最困难的,一个完整的环境的创建于维护可能需要花费很大的经历,特别是当有多个不同的团队在独立开发的场景下。
   另一方面,从传统的测试金字塔来看,端到端测试应该覆盖那些业务价值最高的Happy Path。也就是说,端到端测试并不关注异常场景,甚至大部分的业务场景都不考虑。要做到这一点,需要在设计测试时,从最终用户的角度来考虑,通过 用户画像 和 User Journey 来确定测试场景。
   在端到端测试中,最重要的反而不是测试本身,而是环境的自动化能力。比如可以通过一键就可以将整个环境 provision 出来:
  
       
  • 安装和配置相关依赖   
  • 自动将测试数据Feed到数据库   
  • 自动部署   
  • 服务的自动重启  
  随着容器技术和容器的编排技术的成熟,这部分工作已经可以比较好的自动化,依赖的工具包括:
  
       
  • Docker   
  • Rancher  
  一个典型的流程是:
  
       
  • 搭建持续发布流水线   
  • 应用代码的每一次提交都可以构建出docker镜像   
  • 将docker镜像发布在内部的docker-hub上   
  • 触发部署任务,通过rancher的upgrade命令将新的镜像发布   
  • 执行端到端测试套件  
  端到端测试还可以细分为两个不同的场景:
  
       
  • 没有用户交互的场景,如一系列的微服务组成了一个业务API   
  • 有用户交互的场景  
  UI测试

   最顶层的UI测试跟传统方式的UI测试并无二致。我们可以使用BDD与实例化需求( Specification By Example )的概念,从用户使用的角度来描述需求,以及相关的验收条件。这里我们会使用WebDriver来驱动浏览器,并通过诸如 Capybara 等工具来模拟用户的操作。



上一篇:Linux Journal October 2016
下一篇:Different JSON files in ASP.net Core
飞槐 发表于 2016-10-2 20:15:30
太邪乎了吧?
回复 支持 反对

使用道具 举报

uyadz 发表于 2016-10-8 22:54:54
围观 围观 沙发在哪里!!!
回复 支持 反对

使用道具 举报

v信956924057 发表于 2016-10-10 11:35:01
只要不下流,我们就是主流!  
回复 支持 反对

使用道具 举报

wx_M7I0pc0D 发表于 2016-10-13 14:31:01
顶起出售广告位
回复 支持 反对

使用道具 举报

yxlamkiv 发表于 2016-11-6 16:23:41
1v1飘过
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )

© 2001-2017 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表