Httprunner 文件上传场景

使用Httprunner在做接口自动化的时候,经常会遇到需要上传文件的场景,下面讲一下关于Httpruner文件上传的用例编写。


1. 建项目

首先我们使用httprunner的脚手架快速搭建一个工程

  httprunner --startproject demo

生成的工程目录结构如下图

Httprunner 文件上传场景
简单介绍一下这些目录的作用,

  • apis ?放接口的目录
  • testcases ?放用例的目录
  • testsuites ? 放用例集的目录
  • reports ? 生成的测试报告目录
  • .env ??存放系统环境变量
  • debugtalk.py ? 编写动态逻辑函数



2. 抓包与解析

本文使用的是Fiddler抓包工具进行抓的包,访问百度识图网站PC版 ,点击本地上传,选中本地一张图片后上传。那么在Fiddler抓包工具中,我们抓到数据大致如下图所示

Httprunner 文件上传场景

选中该接口,点击File->Export Sessions->Selected Sessions, 弹出数据包类型选择,选择HTTPArchive v1.2,给文件命名,这里命名的是upload,那么将得到一个upload.har文件

Httprunner 文件上传场景


3. 用例编写

打开DOS,进入到文件所在目录,执行下方命令,将har文件转成yaml文件, 得到文件upload.yml, 文件内容如下图

  har2case -2y upload.har

Httprunner 文件上传场景

我们注意到,其实这个接口呢,主要就是传递了两个参数值,一个是data,就是图片数据,另一个就是params中的uptime,这是一个13位数的时间戳。其中呢,data数据是可以每次都不变的,但uptime是要随时间变化的,这其实也是一种过滤或者说校验手段,保证每次上传图片的唯一性和有效性。

3.1 处理时间戳问题

关于时间戳呢,在debugtalk.py文件中编写一个获取当前时间戳的动态函数

  import time
  
  def getTimeStamp():             # 获取一个13位数的时间戳
        return int(time.time()*1000)

将upload.yml文件中的时间戳替换成动态函数之后,就可以无限次数上传刚才上传的那张图片了。更改如下

  uptime: ${getTimeStamp()}

3.2 处理图片上传问题

那么如果我们想要上传其他图片呢,思路也是差不多的,只需要把data中的数据换成新的图片的数据即可,也可以像获取时间戳一样写一个带参数path(图片路径)动态逻辑函数,函数读取图片并对图片进行base64编码以及设置boundary,返回编码后的数据。这样相对来说是复杂一些,对于不同的接口编码函数甚至需要更改,为什么呢?我们看到这两张图

Httprunner 文件上传场景
-------------------------------------------图片分割线-----------------------------------------------------------
Httprunner 文件上传场景

图一显示的就是data在webform中的样子,图二显示的就是data中的raw数据(省略了很多)。从图一和图二我们可以知道,如果要写一个关于读取图片并编码的函数的话,这个函数的返回值中,不仅被要求包含图片的base64格式数据,还要含有其余三个参数的key与其对应的value,就是 tnimage_sourcefrom这三个key,以及他们的值。

写这样的函数其实也不困难,但如果另外一个接口除了图片数据之外又有其它参数要求呢,这个时候就又需要些另外一个编码函数了, 那么有没有更方便一些的方式呢?

有,接着往下看!

前面都是铺垫,下面才是重点,重点,重点!!!





方法一 ? 使用upload关键字

为了方便文件上传呢,Httprunner 2.4.1以上版本支持upload关键字,可以在请求中添加相应参数即可完成图片上传。以刚才的百度图片上传为例,使用关键字upload后的代码是

config:
    name: testcase description
    variables: {}
teststeps:
-   name: /upload
    request:
        verify: False
        upload:
            image: logo.jpg
            image_source: PC_UPLOAD_FILE
            tn: pc
            from: pc

        headers:
            Sec-Fetch-Dest: empty
            Sec-Fetch-Mode: cors
            Sec-Fetch-Site: same-origin
            User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
                (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
            X-Requested-With: XMLHttpRequest
        method: POST
        params:
            uptime: ${getTimeStamp()}
        url: https://graph.baidu.com/upload
    validate:
    -   eq:
        - status_code
        - 200
    -   eq:
        - headers.Content-Type
        - application/json
    -   eq:
        - content.is_intervene
        - false
    -   eq:
        - content.status
        - 0
    -   eq:
        - content.msg
        - Success

是不是非常非常简单呢,直接使用upload字段就可以完成编码并上传的功能了。在upload字段下面,我们有四个参数:image, image_source, tn, from

很眼熟吧,这四个参数就只之前我们提到的那些参数了,其中我们只需要重点关注image, 因为这个key的值是一个file,也就是我们需要上传的文件,所以这里填写的就是我们需要上传的图片的路径。而这个图片路径需要非常注意,它一定是相对于运行路径。以我的项目文件结构为例

Httprunner 文件上传场景

如图所示,Logo.jpg文件与api,reports,testcases,testsuites等是处于同一层级的,Logo.jpg和它们都是在根目录demo下的子层级,不要看成属于testsuites了。如果在demo中执行脚本,即命令

  hrun api/upload.yml

那么image的值就Logo.jpg。 如果进入到api中执行,即命令

  hrun upload.yml

那么image的值就是 ../Logo.jpg, 因为图片在api里的上一层级。这一点需要重点注意!!!

此外呢,可能大家也注意到使用upload字段的脚本下Headers选项中Content-type被删除了,这是因为upload会自动生成对应的Content-type,不需要画蛇添足了,不然遇到各种奇奇怪怪的问题都无从定位。


今天写不动了,也写不完了,明天继续写....

Httprunner 文件上传场景

上一篇:REST模式中HTTP请求方法(GET,POST,PUT,DELETE)


下一篇:建数据库表经验总结