lsekfe 发表于 2022-10-28 13:27:46

大神手把手教你做持续测试

5.3测试代码生成
  测试代码的开发速度跟不上制品检测需求增加的速度的问题日益明显,因此测试工程师开始全力解决该问题,不断地探索测试脚本生产方法就是其中一个方法。
  5.3.1基于二进制文件的测试代码生成
  在接口测试过程中,绝大部分的工作时间耗费在了脚本撰写和参数设计上。它相对于测试(UI测试)工作流程主要多了脚本撰写部分。参数设计等同于之前业务测试中的测试用例设计环节。因此针对Java的ClassLoader的分析和类的解析过程,设计并实现了一种针对RPC服务的测试脚本自动生成算法。
  下面就详细介绍一下这种自动生成算法。自动生成算法构造了一种特殊的线索二叉树数据结构,用于实现脚本的自动生成。
  二叉树是计算机中一种既普遍又特殊的树。其每一个节点中都有且至多拥有两个子节点。这两个子节点分别称为当前节点的左子节点和右子节点。如果左子节点非叶子节点,那么以左子节点为根的树称为基于当前节点的左子树,右子树与之类似。在二叉树中,顶端的节点(也就是无父节点的节点)称为根节点。节点所有右子树的根节点称为该节点的子节点。没有子节点的节点称为叶子节点。
  线索二叉树充分利用二叉链表中的空指针,它使空指针在某种遍历顺序下指向该节点的前驱和后继。在二叉链表中,每个节点都有*leftChild和*rightChild两个指针,除根节点之外,每个节点只与一个指针对应,即要么对应leftChild,要么对应rightChild。假设线索二叉树中一共有n个节点,因为n个节点有2n个指针,又因为n个节点中有(n?1)条边(除头节点没有边,其余节点都有一个父节点,这些节点都有1条边),剩余的空指针数就是2n?(n?1)= n+1,即有(n+1)个空指针。从这个角度也说明了线索二叉树的必要性。
  线索二叉树在二叉链表的基础上增加了两个成员数据leftTag和rightTag,分别用来标记当前节点的leftChild和rightChild指针指向的是子节点,还是线索。
  如果leftTag=rightTag=1,表示线索;如果leftTag=rightTag=0,表示孩子节点。通过线索二叉树,我们可以快速确定树中任意节点在特定遍历算法中的前驱和后继。
  针对二叉树的遍历有前序遍历、中序遍历及后序遍历3种。遍历即对树的所有节点访问一次。前序遍历指首先遍历书的根节点,然后遍历左子树,最后遍历右子树;中序遍历指首先遍历左子树,然后遍历根节点,最后遍历右子树;后序遍历指首先遍历左子树,然后遍历右子树,最后遍历根节点。
  在原有的线索二叉树的基础之上,设计了适合脚本自动生成的树节点的存储结构,如图?5-7所示。

图5-7适合脚本自动生成的树节点的存储结构


  存储节点包含名称、类型、左子指针、右子指针和父指针等信息。下面通过前驱二叉树生成算法生成一棵前驱线索二叉树,其中前驱为指向父节点的指针,代码如代码清单5-1所示。


代码清单5-1


  接下来,介绍该二叉树的具体结构和存储内容。


  在根节点中,具体结构如下。


  Name字段存储被测接口的名称。


  Type字段存储返回值类型。


  leftChild字段指向第一个被测接口入参的第一个基本类型节点,否则该字段为Null。


  rightChild字段指向第一个被测接口的第一个复杂类型节点,否则为Null。


  Father字段为Null。


  在基本类型参数中,具体结构如下。


  Name存储变量名。


  Type存储遍历类型。


  leftChild指向同层调用中的基本类型节点。


  rightChild为Null。


  Father指向同层调用的上一个节点或者指向其复杂类型的父节点的节点,如果该节点是二叉树的第二层节点,则指向根节点。


  对于Java对象类型参数,新建两个类型节点,一个是Java对象节点,另一个是对象中的节点。


  在Java对象节点中,具体结构如下。


  Name存储对象变量名。


  Type存储Java对象。


  leftChild指向其对应的对象节点。


  rightChild指向同层的复杂对象节点。


  Father指向同层调用的上一个节点或者指向其复杂类型的父节点的节点,如果该节点是二叉树的第二层节点,则指向根节点。


  在对象节点中,具体结构如下。


  Name存储Null。


  Type存储Null。


  leftChild指向其嵌套的第一个基本类型节点,否则为Null。


  rightChild指向其嵌套的第一个复杂对象节点,否则为Null。


  Father指向其对应的Java对象节点。


  对于Map类型参数,新建两个类型节点,一个是Map类型节点,另一个是Map中的节点。


  在Map类型节点中,具体结构如下。


  Name存储对象变量名。


  Type存储Map标记。


  leftChild指向其对应的Map中的节点。


  rightChild指向同层的复杂对象节点。


  Father指向同层调用的上一个节点或者指向其复杂类型的父节点中的节点,如果该节点是二叉树的第二层节点,则指向根节点。


  在Map类型中的节点中,具体结构如下。


  Name存储Null。


  Type存储Null。


  leftChild指向其第一个key节点,key节点按照具体类型处理。


  rightChild指向第一个value节点,value节点按照具体类型处理。


  Father指向其对应的Map类型节点。


  对于List类型参数,新建两个类型节点,一个是List类型节点,另一个是List类型参数中的节点。


  在Map类型节点中,具体结构如下。


  Name存储对象变量名。


  Type存储Map标记。


  leftChild指向其对应的List类型参数中的节点。


  rightChild指向同层的复杂对象节点。


  Father指向同层调用的上一个节点或者指向其复杂类型的父节点的节点,如果该节点是二叉树的第二层节点,则指向根节点。


  在List类型参数的节点中,具体结构如下。


  Name存储Null。


  Type存储Null。


  如果List是基本类型,则leftChild指向其对应基本类型节点,rightChild为Null。


  如果List是复杂类型,则rightChild指向其对应复杂类型节点,leftChild为Null。


  Father指向其对应的List类型节点。


  脚本自动生成的重点是测试参数的嵌套关系,因此通过上述数据结构,我们就可以完成被测接口入参的数据结构嵌套关系的梳理。生成算法的伪代码如代码清单5-2所示。




代码清单5-2


  依据上述算法,针对测试脚本生成过程做一个简单的介绍。被测接口如代码清单5-3所示。


代码清单5-3


  按照上述树的生成算法,生成的树的结构如图5-8所示。


图5-8生成的树的结构


  要生成实际的调用关系,采取中序遍历,首先遍历左子树,然后遍历根节点,最后遍历右子树。将遍历过程存入Map中,我们就可以完全搞清楚参数的调用关系。再通过这个Map的遍历,按照基本类型初始化,然后初始化复杂类型的逻辑规则,就完成被测接口的入参拼凑。最后按照根节点的结构,生成接口的调用语句,生成测试脚本。

5.3.2基于通用文件的测试代码生成
  基于通用文件的测试代码通常基于Swagger的测试代码生成。Swagger可以定义一个标准的RESTful风格的API,它与语言无关,是一个API规范。基于每个项目的Swagger,导出针对每一个接口的JSON文件,具体代码可以参考代码清单5-4。




代码清单5-4


  通过上述代码,生成针对每一个API的JSON文件。针对每一个JSON文件,按照已经确定的测试代码格式进行一次转换就可以得到对应的测试代码。


bellas 发表于 2022-11-14 13:46:57

:time:
页: [1]
查看完整版本: 大神手把手教你做持续测试