一文揭秘测试平台中是如何将测试用例一键转化Jmeter压测脚本

发表于:2020-5-08 11:06

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:雷子V    来源:雷子说测试

  接上篇,一键转化将接口测试平台测试用例转化成Jmeter压测脚本思路,这里我首先在java 上面做了一个简单的实验,看看 转化的中间遇到的问题,这里呢,我只是给了一个简单的demo 版本,后续结合项目的实际的实用,还是靠各位,贴合我们的实际的项目去制定适合本公司转化的脚本。具体的业务还是要实际的分析的。首先看下我的思路
  1.点击一键生成
  2.后台拿到测试环境id,测试用例id
  3.后台去交验是否存在测试环境,测试用例id。
  4.后台开始根据用例请求参数,组织Jmeter脚本
  5.产生的脚本代码保存到本地的目录。并且将脚本的项目的信息存储到数据库
  6.前台选择执行的测试计划,远程执行的服务器,
  7.根据前端的配置的测试计划,获取对应的本地的脚本,复制到远程的服务器上
  8.通过ssh链接直接操作远程服务器开启操作。
  9.查看远程测试报告的数据,压测过程中监控
  10.测试完毕,收集汇总,如有历史记录,对比历史记录的性能差别
  上述呢,是我在整个转化的地方,想到的逻辑的,大概在上面的流程上,那么基于大概的上面的设计,我们去设计我们的代码。
  我这里的设计,是增加了一个针对存储测试脚本的一个数据表,这里存储到对应的接口的压测脚本的详细信息,包括执行的服务器的信息。具体的数据库的设计如下。
   import lombok.Data;
  import javax.persistence.Entity;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import java.util.Date;
  /**
  * @Description  存储压测文件的
  * @create 2020-04-27 21:04
  */
  @Data
  @Entity
  public class PerTestjmx {
  //存储转化后的压测文件
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  private Integer project;
  private Integer adduser;
  private String serverip;
  private String serverpassword;
  private String name;
  private String runcount;
  private String loopcount;
  private String jmxpath;
  private Date addtime;
  private Date updatime = this.addtime;
  private Integer updateuser;
  }
  设计完,我们的数据库,我们去访问底层数据模型的接口。这里我们先暂时的只是简单的实现,并没有拓展其他的方法。因为原生的访问模型就满足了。
   package pan.repository;
  import org.springframework.data.jpa.repository.JpaRepository;
  import pan.DaoObject.PerTestjmx;
  /**
  * @Description
  *
  * @create 2020-04-27 21:06
  */
  public interface PerTestjmxRepository extends JpaRepository<PerTestjmx,Integer> {
  }
  那么,我们接下来要实现的就是,我们转化用例的地方,这里我拆分了两个步骤,
  1.一个是产生脚本
  2.复制产生的脚本
  接下来,我们就会设计这个两个的实现的方法。
  我们在接口用例的接口中定义这样的两个方法,
   String  makePerTest(PerTestParamForm perTestParamForm);

  boolean runPerServer(RunServerFrom runServerFrom);
  
   RunServerFrom.java
  @Data
  @ApiModel
  public class RunServerFrom {
  @NotEmpty(message = "用例的id 不能为空")
  private Integer id;
  @NotEmpty(message = "服务器的ip不能为空")
  private  String serverip;
  @NotEmpty(message = "远程登录服务的密码不能唯恐")
  private String passowrd;
  }
 
   PerTestParamForm.java
  import io.swagger.annotations.ApiModel;
  import lombok.Data;
  /**
  * @Description
  * @auther leizi
  * @create 2020-04-27 20:34
  */
  @Data
  @ApiModel
  public class PerTestParamForm {
  @NotEmpty(message = "测试环境不能为空")
  private Integer testevents;
  @NotEmpty(message = "转换的caseid 不能为空")
  private Integer caseid;
  @NotEmpty(message = "并发数不能为空")
  private Integer loopcount;
  @NotEmpty(message = "运行次数")
  private Integer runcount;
  private  String runserverip;
  private  String runserverpassword;
  }
   我们可以在接口用例的实现方法去实现这样的两个功能。
   如下的步骤:
  /*
  产生压测脚本
  */
  @Override
  public String makePerTest(PerTestParamForm perTestParamForm) {
  Interfacecase interfacecase;
  Project project;
  Interface intefa;
  Testenvironment testenvironment;
  try{
  interfacecase=interfaceCaseRepository.findById(perTestParamForm.getCaseid()).get();
  }catch (NoSuchElementException e){
  throw  new PanExection(ResultEmus.CASE_NOT_EXIT);
  }
  try {
  project=projectRepository.findById(interfacecase.getProject()).get();
  }catch (NoSuchElementException e){
  throw new PanExection(ResultEmus.PROJECT_NOT_EXIT);
  }
  try{
  intefa=interfaceRepository.findById(interfacecase.getInterfaceid()).get();
  }catch (NoSuchElementException e){
  throw new PanExection(ResultEmus.INTERFACE_NOT_EXCIT);
  }
  try{
  testenvironment=testevironmentRepository.findById(Integer.valueOf(perTestParamForm.getTestevents())).get();
  }catch (NoSuchElementException e){
  throw  new PanExection(ResultEmus.TESTEVE_NO_EXIT);
  }
  Integer port;
  try {
  port= Integer.valueOf(testenvironment.getUrl().split("://")[1].split(":")[1]);
  }catch (ArrayIndexOutOfBoundsException e){
  port=80;
  }
  CreateJmeterUntil createJmeterUntil=new CreateJmeterUntil();
  String conetcn=createJmeterUntil.makejxm(perTestParamForm.getLoopcount().toString(),perTestParamForm.getRuncount().toString(), testenvironment.getUrl().split("://")[1].split(":")[0],port.toString()
  ,intefa.getPath(),interfacecase.getMethod(),project.getProjectname(),project.getProjectname());
  WriteRepost writeRepost=new WriteRepost();
  String name=interfacecase.getNumbering()+"_"+RandomFunction.getRandomString(20);
  String filepath=writeRepost.writPerf(conetcn,name);
  //存储产生测试用例
  PerTestjmx perTestjmx=new PerTestjmx();
  perTestjmx.setAdduser(1);
  perTestjmx.setAddtime(new Date());
  perTestjmx.setJmxpath(filepath);
  perTestjmx.setLoopcount(perTestjmx.getLoopcount());
  perTestjmx.setRuncount(perTestjmx.getRuncount());
  perTestjmx.setProject(project.getId());
  perTestjmx.setServerip(perTestParamForm.getRunserverip());
  perTestjmx.setServerpassword(perTestParamForm.getRunserverpassword());
  perTestjmx.setUpdateuser(1);
  perTestjmx.setName(name);
  perTestjmxRepository.save(perTestjmx);
  return "OK";
  }
  @Override
  public boolean runPerServer(RunServerFrom runServerFrom) {
  //执行远程测试脚本
  PerTestjmx perTestjmx = null;
  try {
  perTestjmx =perTestjmxRepository.findById(runServerFrom.getId()).get();
  }catch (NoSuchElementException e){
  log.error(e.getMessage());
  }
  if (perTestjmx.getJmxpath()!=null){
  //复制文件到远程服务器
  String cmdcopy="sshpass -p "+runServerFrom.getPassowrd()+" scp -P 6789  "+perTestjmx.getJmxpath()+" root@"+runServerFrom.getServerip()+":/home";
  try {
  Process p = Runtime.getRuntime().exec(cmdcopy);
  } catch (IOException e) {
  log.error(e.getMessage());
  }
  //链接远程服务器执行命令 这里前提你要配置好jmeter的执行环境
  String cmd="./jmeter -n -t /home"+perTestjmx.getName();
  SshTools sshTools=new SshTools();
  String reslut=sshTools.ssh_tool(cmd,runServerFrom.getPassowrd(),runServerFrom.getServerip());
  return true;
  }
  return false;
  }
  其实这中间的实现是特别简单的,代码中SshTools 代码可以看下一文告知Java如何实现通过ssh 和远程服务器开展对话聊天。产生脚本的代码,一个是jmx文件的拼接,这里根据大家平时对jmx文件的代码的解析 就可以拼接出来的。产生后会放在本地的文件中。
  大家可以根据自己的项目去定制的,写完实现的方法后,要去实现对应的api。
   @GetMapping("/make")
  public ResultVO make(@Valid PerTestParamForm perTestParamForm,
  BindingResult bindingResult) {
  if (bindingResult.hasErrors()) {
  throw new PanExection(ResultEmus.PARM_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
  }
  String interfacecase = interfaceCaseService.makePerTest(perTestParamForm);
  return ResultVOUntils.success(interfacecase);
  }
  @GetMapping("/runPerServer")
  public ResultVO runPerServer(@Valid RunServerFrom perTestParamForm,
  BindingResult bindingResult) {
  if (bindingResult.hasErrors()) {
  throw new PanExection(ResultEmus.PARM_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
  }
  boolean reslut = interfaceCaseService.runPerServer(perTestParamForm);
  if (reslut){
  return ResultVOUntils.success();
  }
  return ResultVOUntils.error("执行失败");
  }
  实现了两个的api。然后我们可以启动本地的代码去调试对应的程序。如果大家没有那么多的服务器可以测试的,可以参考我之前写的一篇文章。测开必杀技--docker安装Ubuntu系统实战 。可以利用docker 虚拟化几台服务器做测试用,特别简单的。我们可以用Jmeter去打开我们的实现的脚本代码的。
  最后写入还是返回我们的监控的平台
  说一下这个demo的缺点。因为是一个demo,它肯定有缺点的,缺点如下。
  1.数据库设计,没有前瞻性,数据库设计只是为了满足当前的开发需要,不利于后续的变更。
  2.功能的实现 中。
  2.1 参数是固定的。
  2.2 没有参数化
  2.3没有兼容到csv的大数据
  2.4依赖登录没有处理
  2.5断言不灵活
  2.6 缺乏数据的对比
  2.7 适配业务场景测试不足。
  大概我现在想到的有以上的不足,当然了,这是一个需要慢慢优化的,在后续的持续迭代中,我会将上面的不足补充。
  上述的就是一个大致的demo版本,大致的流程就是这样实现的,因为这是一个完整的平台,所以很多的代码的实现 都是复用原有的,大致的功能都已经能够实现的。关于整个测试平台的开发,后续有机会可以在群里给大家开放系列的课程的,目前的python版本的测试平台已经开源。放在了https://github.com/liwanlei/FXTest, 欢迎大家star,后续等这个功能 完美后,我会在维护开源的平台的时候,作为一个版本的迭代功能 坐上去。欢迎大家持续关注。

     本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号