内容简介:项目的测试工作相当重要,它直接影响到项目的质量。通常一个项目,虽然外围测试团队会进行高强度、多维度的测试,但作为开发者的我们,在测试团队正式测试之前,自己编写一些测试案例,输入一些常规的数据,测试接口是否返回正确的数据,这种工作是非常有必要的,开发者不能没有经过测试,就直接扔给测试团队。编写测试案例,总体思路是:先分别定义一个请求结构体和响应结构体,再定义一个发送 POST 请求的函数,函数接收请求结构体实例,返回响应结构体实例,最后通过 html 页面罗列所有的接口链接,测试者点击链接,链接就调用发送 P
项目的测试工作相当重要,它直接影响到项目的质量。通常一个项目,虽然外围测试团队会进行高强度、多维度的测试,但作为开发者的我们,在测试团队正式测试之前,自己编写一些测试案例,输入一些常规的数据,测试接口是否返回正确的数据,这种工作是非常有必要的,开发者不能没有经过测试,就直接扔给测试团队。
编写测试案例,总体思路是:先分别定义一个请求结构体和响应结构体,再定义一个发送 POST 请求的函数,函数接收请求结构体实例,返回响应结构体实例,最后通过 html 页面罗列所有的接口链接,测试者点击链接,链接就调用发送 POST 请求的函数,把函数返回的请求数据和响应数据直接显示出来,验证测试结果是否正确。
我们新建一个 chapter01/src/test 测试包,定义结构体和辅助函数:
*代码清单 - 测试实体结构体代码片段*
package test
import "time"
// TestCaseReq 测试案例请求结构体
type TestCaseReq struct {
Name string
URL string
Params map[string]interface{}
}
// TestCaseResp 测试案例请响应结构体
type TestCaseResp struct {
Name string
URL string
ReqJSON string
RespJSON string
TimeMs time.Duration
}
请求结构体,包括一个测试的接口名、URL 测试地址、传递给接口的参数(字典方式);响应结构体同样是接口名、URL 测试地址、请求参数 JSON 字符串(是字段转成了 JSON 字符串)、响应参数 JSON 字符串、耗费时长。请求结构体都是 POST 请求接口所需要的东西,响应结构体是我们想在 html 页面看到的东西。
*代码清单 - 测试公共函数代 码片段*
<em>package test
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"time"
"chapter01/src/common"
)
// PostTestCaseDataToServer 发送 POST 测试案例请求的函数
func PostTestCaseDataToServer(testCaseReq TestCaseReq) *TestCaseResp {
start := time.Now()
bytParams, err := json.Marshal(testCaseReq.Params)
if err != nil {
common.ShowErr(err)
return nil
}
body := bytes.NewBuffer(bytParams)
req, err := http.NewRequest("POST", testCaseReq.URL, body)
if err != nil {
common.ShowErr(err)
return nil
}
req.Header.Set("Content-Type", applicationJSONCharSet)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
common.ShowErr(err)
return nil
}
defer resp.Body.Close()
respJSON, _ := ioutil.ReadAll(resp.Body)
testCaseResp := TestCaseResp{
Name: testCaseReq.Name,
URL: testCaseReq.URL,
ReqJSON: string(bytParams),
RespJSON: string(respJSON),
TimeMs: time.Since(start),
}
return &testCaseResp
}</em>
辅助函数实际上就是发送 POST 请求函数,把请求 JSON 字符串 POST 给我们的服务,服务接口再返回响应 JSON 数据。
这些都是程序化的东西,相对固定,有迹可循,也是必不可少的,然而案例测试数据才是最关键的,它是变化的,需要根据不同的接口,初始化请求结构体实例,放入字典里,给辅助函数调用。
*代码清单 - 案例测试数据片段*
package test
import (
"chapter01/src/model"
"chapter01/src/util"
)
const (
testDomain = "http://localhost:3000"
applicationJSONCharSet = "application/json;charset=utf-8"
)
// ALLTestCaseReqData 全部测试案例请求数据
func ALLTestCaseReqData() map[string]TestCaseReq {
allTestCaseReq := map[string]TestCaseReq{}
allTestCaseReq["pathProductList"] = TestCaseReq{
Name: "产品列表",
URL: testDomain + "/api/v1/product/list",
Params: map[string]interface{}{
"category": 1,
"start": 1,
"end": 10,
},
}
allTestCaseReq["pathProductDetail"] = TestCaseReq{
Name: "产品详情页",
URL: testDomain + "/api/v1/product/detail",
Params: map[string]interface{}{
"productID": 1,
},
}
allTestCaseReq["pathProductSearch"] = TestCaseReq{
Name: "产品搜索",
URL: testDomain + "/api/v1/product/search",
Params: map[string]interface{}{
"category": 1,
"key": "语言",
"start": 1,
"end": 10,
},
}
allTestCaseReq["pathProductAdd"] = TestCaseReq{
Name: "新增一个产品",
URL: testDomain + "/api/v1/product/add",
Params: map[string]interface{}{
"category": 1,
"name": "Go",
"intro": "Go 语言的圣经书籍,年度畅销书籍",
"price": 56.98,
"photoEdit": []model.PhotoArgs{model.PhotoArgs{
Path: "/product/154192547123856140062_b.png",
Seq: 1,
}, model.PhotoArgs{
Path: "/product/154192547123856140062_b.png",
Seq: 2,
}, model.PhotoArgs{
Path: "/product/154192547123856140062_b.png",
Seq: 3}},
},
}
allTestCaseReq["pathProductModify"] = TestCaseReq{
Name: "修改一个产品",
URL: testDomain + "/api/v1/product/modify",
Params: map[string]interface{}{
"productID": 3,
"category": 1,
"name": "Go",
"intro": "Go 语言的圣经书籍,年度畅销书籍666",
"price": 56.98,
"photoEdit": []model.PhotoArgs{model.PhotoArgs{
ID: 1,
Path: "/product/154192547123856140062_b.png",
Seq: 1,
}, model.PhotoArgs{
ID: 2,
Path: "/product/154192547123856140062_b.png",
Seq: 2,
}, model.PhotoArgs{
ID: 3,
Path: "/product/154192547123856140062_b.png",
Seq: 3}},
},
}
allTestCaseReq["pathProductDelete"] = TestCaseReq{
Name: "删除一个产品",
URL: testDomain + "/api/v1/product/delete",
Params: map[string]interface{}{
"productID": 3,
},
}
allTestCaseReq["pathProductPhotoUpload"] = TestCaseReq{
Name: "产品图片上传",
URL: testDomain + "/api/v1/product/photo/upload",
Params: map[string]interface{}{
"file": util.PathToBytes("D:\\t.png"),
"fileExt": "png",
"seq": 1,
},
}
return allTestCaseReq
}
案例测试数据随着接口的增多,也会相应增加,做法上没有技术性的难点,我们只需要熟悉业务性的东西,自然就可以按需制造数据,用于发送 POST 请求进行测试。
案例测试数据其实就是一个大字典,是键值对结构的,key 是接口的名称标识,value 是 TestCaseReq 实例,我们大部分的精力都放在 TestCaseReq 实例数据上了。
最后我通过 HTML 方式,把大字典的 key 和 value 循环绑定到链接上 ,相当于罗列了所有测试接口的请求链接,给用户点击链接,就把 value (TestCaseReq 实例)传递给辅助函数 PostTestCaseDataToServer,得到一个 响应结构体的实例(TestCaseResp 实例),再把实例的所有字段的数据显示到另外的 html 结果页面上。渲染 HTML 由 controller 控制层来完成:
*代码清单 - 测试控制器代码片段*
package controller
import (
"net/http"
"chapter01/src/test"
)
// RunTestIndex 循环罗列所有的接口链接
func RunTestIndex(w http.ResponseWriter, req *http.Request) {
ctx := map[string]interface{}{}
ctx["allTestCaseReq"] = test.ALLTestCaseReqData()
r.HTML(w, http.StatusOK, "run_api_test_index", ctx)
return
}
// RunTestResult 显示 POST 请求后的结果页面
func RunTestResult(w http.ResponseWriter, req *http.Request) {
key := req.FormValue("key")
testCaseReqData := test.ALLTestCaseReqData()[key]
testCaseResp := test.PostTestCaseDataToServer(testCaseReqData)
ctx := map[string]interface{}{}
ctx["testCaseResp"] = testCaseResp
r.HTML(w, http.StatusOK, "run_api_test_result", ctx)
return
}
文件夹 template 中的两个 HTML 页面,一个是循环罗列所有的接口链接(run_api_test_index.html),一个是显示 POST 请求后返回的显示结果页面(run_api_test_result.html)
*代码清单 - run_api_test_index.html 循环罗列所有的接口链接代码*
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>接口测试首页</title>
</head>
<body>
<h3>接口测试链接</h3>
<ol>
{{range $key,$val:= .allTestCaseReq}}
<li><a target="_blank" href="/test/result?key={{$key}}">{{$val.Name}} {{$val.URL}}</a></li>
{{end}}
</ol>
</body>
</html>
代码清单 - run_api_test_result.html 显示结果页面代码
<em><!DOCTYPE html>
<html>
<head>
<title>{{.testCaseResp.Name}} - 测试接口</title>
<style type="text/css">
body,table{font-size:12px}h1{font-size:1.4em;color:#2d2d2d}table{table-layout:fixed;empty-cells:show;border-collapse:collapse;width:100%}.table{color:#444;border-top:1px solid #ccc}.table th{background-repeat:repeat-x}.table td,.table th{border-bottom:1px solid #ccc;padding:0.8em 0.6em;word-break:break-all}.table tr.alter{background-color:#eee}.table tr .title{width:130px;color:#555}.table tr .cont{color:#000}</style>
</head>
<body>
<h1>请求的接口:{{.testCaseResp.URL}}</h1>
<table class="table">
<tr class="alter">
<td class="title">请求参数:</td>
<td class="cont">{{.testCaseResp.ReqJSON}}</td>
</tr>
<tr>
<td class="title">请求类型:</td>
<td class="cont">POST</td>
</tr>
<tr class="alter">
<td class="title">响应内容:</td>
<td class="cont">{{.testCaseResp.RespJSON}}</td>
</tr>
<tr>
<td class="title">总计耗时:</td>
<td class="cont">{{.testCaseResp.TimeMs}}</td>
</tr>
</table>
</body>
</html></em>
小结
本章节核心内容是案例测试数据的构建,其他实体结构,公共函数,HTML 这些代码相对非常固定,几乎不需要变动,所以我们要把主要精力放在数据构建上,多方面模拟不同的情况来测试接口。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 接口测试及常用接口测试工具
- itest(爱测试)接口测试&敏捷测试管理 7.7.7 发布,接口测试重大升级
- itest(爱测试)接口测试&敏捷测试管理 6.6.6 发布 ,新增接口 mock
- itest work(爱测试) 接口测试&敏捷测试管理平台 9.5.0 发布接口测试及脑图用例升级
- itest work(爱测试) 一站式接口测试&敏捷测试工作站 9.0.5.Rc4 接口测试升级
- python接口自动化测试之接口数据依赖
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python标准库
Doug Hellmann / 刘炽 / 机械工业出版社华章公司 / 2012-6-15 / 139.00元
本书由资深Python专家亲自执笔,Python语言的核心开发人员作序推荐,权威性毋庸置疑。 对于程序员而言,标准库与语言本身同样重要,它好比一个百宝箱,能为各种常见的任务提供完美的解决方案,所以本书是所有Python程序员都必备的工具书!本书以案例驱动的方式讲解了标准库中一百多个模块的使用方法(如何工作)和工作原理(为什么要这样工作),比标准库的官方文档更容易理解(一个简单的示例比一份手册......一起来看看 《Python标准库》 这本书的介绍吧!