本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践。

测试框架的演进

截止目前为止,在 Nebula Graph 的开发过程中,测试框架一共发生三次较大的改动,如下图所示。在不断的演进中,团队还是积累了一些经验和教训,希望借由此文做个简单的介绍和梳理。

对于一个数据库产品而言,测试的重要性不言而喻,如何强调都不为过。所以测试框架无论切换到谁,出发点始终只有一个:方便快速的积累测试用例来保障 Nebula Graph 功能的稳定。这里提到的“方便快速”,不是局限于“开发者”这个群体,而是需要面向 Nebula Graph 的所有用户,可能是运维、文档甚至是非技术相关人员。为了实现这点目标,最好是能够让用户进行“无码编程”甚至不需要编程。

纵观大多数的数据库产品,往往是定制一套自己的文本规则,开发者基于这套规则来提交测试,前期我们也有过这方面的尝试,后续考虑到要从头实现定制功能太多,再加上用户又需要学习一套新的规则,最终没有真正的切换过去。直到我们开始做兼容 openCypher 的 MATCH 功能时,注意到 TCK 这个 repo,这虽然是一个兼容性的测试套件,但给我们实现 Nebula Graph 的集成测试提供了新的思路。前述尝试不好落地的一个原因是 Nebula Graph 返回的结果集中是一个可能含有点、边和路径的复合数据结构,采用类似 JSON 的方式不是不可,只是不够优雅简洁。结果集多了之后,便有“形式”大于“内容”之嫌,结构上的描述远超真正关心的数据,啰嗦冗长,不胜其烦。而 TCK 中制定的这套描述点、边和路径的描述规则足够简单直观,又契合 MATCH 中的 Pattern 语句,前后呼应,只要用过 openCypher 的用户,很容易接受和理解。只是针对 Nebula Graph 的强 schema 要求,需要对其规则做些拓展,但无伤大雅,鉴于上述的优点,让我们坚定的走向 BDD 的测试框架。

Nebula Graph 端到端的功能测试其实是个“黑盒”测试,主要完成的事情抽象出来就是:执行一条 nGQL 语句,比较返回的结果集。

首先通过下述测试用例的复杂度比较,我们可以直观的感受到每一次的进步,从上至下依次为:1. 基于 GTest 的测试;2. 基于 pytest 的测试;3. 基于 BDD 的测试。



[基于 GTest 的测试]



[基于 pytest 的测试]



[基于 BDD 的测试]

从上述对比可以看出,我们越来越靠近“测试”本真,只要关心输入和输出,无需再编码组装测试数据,再辅以一些小的自动化工具,便极大的降低了添加用例的门槛。

期望和实现

在拓展基于 TCK 的测试框架之前,我们给本次的升级定了如下几个期望达成的目标:

  1. 添加用例简单,构造期望数据方便;
  2. 支持导入其他的测试数据集;
  3. 复用 pytest 框架的灵活性,尤其是 plugins 和 fixture 等机制;
  4. 兼容 Match TCK 用例;

为了达成上述目标,我们开始了新的技术选型和模块设计。在构建 Nebula Graph 自己的 TCK 测试框架之前,首选要选择一个“合适的”测试框架,针对该框架的基本要求有如下的几点:

  1. 对基于 BDD 的测试有完善的支持;
  2. 方便灵活可拓展;
  3. 最好能与已有的 pytest 的用例兼容并存。

实现 BDD 的测试框架有很多,即便在 python 语言环境下也是一道多选题,比如 pytest-bddbehave 等。鉴于上述目标中的第三点,我们选择了基于 pytest-bdd 来构建 Nebula Graph 的整个测试流程。 pytest-bdd 是 pytest 的一个插件,可以很好的支持 BDD 的特性同时又可以直接利用 pytest 的功能,比较契合我们的预期。

在选定测试框架之后,便开始设计整个测试流程的各个模块,大体结构可以划分为五个部分:ConnectionManagerDataLoaderParserComparatorReporter

ConnectionManager

管理同 nebula graph 之间的连接,包括出错重试、错误过滤等功能。

DataLoader

读取 CSV 数据文件,解析配置中的数据类型,拼接插入数据的 INSERT 语句等。

Parser

解析 TCK 中描述的点、边和路径的字符串,转成 Nebula 定义的 Value 结构,方便比较。

Comparator

负责不同的 Value 结构的值比较,包括基础数据类型和复合数据类型,复合数据类型有:List、Map、Set、Vertex、Edge 和 Path 等。

Reporter

更好的输出出错的 nGQL 语句在 feature 文件中的位置和行号等定制功能。

模块之间相互独立又相互联系,再配合着 pytest 中 fixture 不同的 scope 可以很好的完成不同场景的隔离和测试。

何为 BDD

前文提到了很多次的 BDD,我们了解 TDD 和 DDD 比较多,可能对何为 BDD 还持有疑问。所谓 BDD 其实是由 TDD 演进而来的一种测试方法,即行为驱动测试(behavior-driven development)。通过用自然语言书写测试用例的方式完成测试,对开发人员之外的参与者更加的友好,从而拉近了开发者和用户之间的距离。在我们实践过程中发现,其实 BDD 的这套方式方法不止对管理软件质量有效,对繁杂的需求管理也是一个很好的补充手段。用户的需求描述不再局限于复杂的场景描述,可以通过期望的查询语句、过程和结论来跟开发者对齐功能需求,这些需求文件在功能开发完毕之后反过来又变成了测试场景用例,可谓一举两得。

说到 BDD,是离不开 Gherkin 语言的。它定义了一组基本的语法规则用来有效的组织普通文本的结构,以便于 BDD 测试工具可以理解文本中描述的内容。存放 Gherkin 语言文本的文件以 .feature 作为拓展名,其中可以描述很多的场景(Scenario)以及每个场景中的步骤是什么(Given/When/Then)。这些语法的规则非常简单易懂,而且关键词数量也少,所以阅读 Gherkin 的测试文本就像“一问一答”的对话,很容易上手。

Nebula Graph 的测试框架期望借助 BDD 的方法打造一个纯“黑盒”的测试流程,无论用户是否是开发者都只需要关注两点,输入的 nGQL 是什么和期望返回的结果数据是什么?如此才能减轻用户添加用例的心智负担,方便其为 Nebula Graph 添砖加瓦。在我们完成框架改造半年之内,内部便已经积累了大约 2500 个测试用例,为 2.0 项目的重构提供了有力的质量保证。所有的用例都分门别类的置于 repo 中的 tests/tck/features 目录中,这些用例本质上也是一部 nGQL 的使用指南,下次用户再碰到棘手的问题不知如何用 nGQL 描述时,也可以先参考这里的用例。

总结

本篇简单回顾了 Nebula Graph 的测试框架的演变历程,后续会向大家展示目前测试框架已经完成的功能以及如何使用它来测试对 Nebula Graph 源码的改动。

交流图数据库技术?加入 Nebula 交流群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~

基于 BDD 理论的 Nebula 集成测试框架重构(上篇)的更多相关文章

  1. 基于特定领域国土GIS应用框架设计及应用

              基于特定领域国土GIS应用框架 设计及应用              何仕国 2012年8月16日   摘要: 本文首先讲述了什么是框架和特定领域框架,以及与国土GIS 这个特定领 ...

  2. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  3. 基于CPU版本的Caffe推理框架

    最近一段时间,认真研究了一下caffe.但是,里面内容过多,集合了CPU版本和GPU版本的代码,导致阅读起来有些复杂.因此,特意对caffe代码进行了重构,搭建一个基于CPU版本的Caffe推理框架. ...

  4. 转-基于NodeJS的14款Web框架

    基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...

  5. 第三篇 基于.net搭建热插拔式web框架(重造Controller)

    由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个contro ...

  6. 第二篇 基于.net搭建热插拔式web框架(沙箱的构建)

    上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章很多人看了以后,都表示不解,觉得不知道我到底 ...

  7. 基于.net搭建热插拔式web框架(实现原理)

    第一节:我们为什么需要一个热插拔式的web框架? 模块之间独立开发 假设我们要做一个后台管理系统,其中包括“用户活跃度”.“产品管理”."账单管理"等模块.每个模块中有自己的业务特 ...

  8. SpaceBase – 基于 Sass 的响应式 CSS 框架

    SpaceBase 是一个基于 Sass 的响应式 CSS 框架.SpaceBase 是可以在建立和定制您的需要的一个样板层,它结合最佳实践为今天的响应式网页与我们对每一个项目中使用的核心组件. 在线 ...

  9. 基于SpringMVC下的Rest服务框架搭建【1、集成Swagger】

    基于SpringMVC下的Rest服务框架搭建[1.集成Swagger] 1.需求背景 SpringMVC本身就可以开发出基于rest风格的服务,通过简单的配置,即可快速开发出一个可供客户端调用的re ...

随机推荐

  1. 通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务

    我个人认为Actor应该是Dapr里比较重头的部分也是Dapr一直在讲的所谓"stateful applications"真正具体的一个实现(个人认为),上一章讲到有状态服务可能很 ...

  2. Salesforce学习之路(四)利用Jenkins和Git实现Salesforce的CI/CD功能

    上文提到,基于CRM的二次开发是必不可少的,但是在实际项目中CI/CD是不可忽略的一个重要部分,与传统的Java,Python项目不同,如果对Salesforce进行持续集成和持续部署呢? 结合找到的 ...

  3. 【故障公告】数据库服务器 CPU 100% 引发网站故障

    悄悄地它又突然来了 -- 数据库服务器 CPU 100% 问题,上次光临时间是 3-30 8:48,这次是 4-28 9:41. 这次我们做出了快速反应,发现后立即进行主备切换,这次一次切换成功,CP ...

  4. 2021S软件工程——结对项目第一阶段

    # 2021S软件工程--结对项目第一阶段 2021春季软件工程(罗杰 任健) 项目地址 1020 1169 --- ## 1 结对感受 总体来说,结对编程与之前的个人编程感觉有很大的不同.有如下几个 ...

  5. 976. Largest Perimeter Triangle

    Given an array A of positive lengths, return the largest perimeter of a triangle with non-zero area, ...

  6. D - 下个也是签到题 FZU - 2221(博弈)

    ZB loves watching RunningMan! There's a game in RunningMan called 100 vs 100. There are two teams, e ...

  7. vuex 引用方法

    引入Vuex(前提是已经用Vue脚手架工具构建好项目) 1.利用npm包管理工具,进行安装 vuex.在控制命令行中输入下边的命令就可以了. npm install vuex --save 要注意的是 ...

  8. Spring初识及其IOC入门

    一.框架 框架是一些类和接口的集合,它一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架时直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度. 二.Spri ...

  9. PhotoShop 第一课 功能认识

    功能认识 1.基本界面 可以对各工具栏进行编辑,对工具/栏目进行勾选添加和整合并搭建自己的专属操作页面. 2.画布设置 拍照或者画画都需要一个东西来呈现这个东西叫做画布(可以通过导航栏-文件-新建画布 ...

  10. PHP基础-PHP中预定义的超全局数组

    预定义数组: 自动全局变量---超全局数组 1. 包含了来自WEB服务器,客户端,运行环境和用户输入的数据 2. 这些数组比较特别 3. 全局范围内自动生效,都可以直接使用这些数组 4. 用户不能自定 ...