golang分层测试之http接口测试入门教程

前言

前几话主要讲解关于使用golang进行单元测试,在单元测试的上一层就是接口测试,本节主要讲使用golang进行接口测试,其中主要以http协议的接口测试来讲解

golang中的http请求

golang中拥有一个原生的http依赖库:net/http,http服务器的建立还是http客户端的开发,都会使用到这个依赖库,这里主要讲解时client部分,作为请求发起方应用于日常的接口测试,例示代码如下:

get请求

package main

import (
 "fmt"
 "io/ioutil"
 "net/http"
)

func main() {
 //模拟一个get提交请求
 resp, err := http.Get("http://127.0.0.1:12345/checkon")
 if err != nil {
  panic(err)
 }
 defer resp.Body.Close() //关闭连接
 body, err := ioutil.ReadAll(resp.Body) //读取body的内容
 fmt.Println(string(body))
}

返回结果

E:\go_project>go run testget.go
{
 "code": 200,
 "data": "",
 "msg": "online",
 "state": "success"
}

post请求:

package main

import (
 "fmt"
 "io/ioutil"
 "net/http"
 "strings"
)

func main() {
 //模拟一个post提交请求
 resp, err := http.Post("http://www.baidu.com", "application/x-www-form-urlencoded", strings.NewReader("id=1"))
 if err != nil {
  panic(err)
 }
 //关闭连接
 defer resp.Body.Close()
 //读取报文中所有内容
 body, err := ioutil.ReadAll(resp.Body)
 //输出内容
 fmt.Println(string(body))
}

上面的post请求以form的方式,最后会返回一个页面

这里说明一下以下这行代码

defer resp.Body.Close()

首先是defer, Go的defer语句用来调度一个函数调用(被延期的函数),使其在执行defer的函数即将返回之前才被运行,被延期执行的函数,它的参数(包括接受者)实在defer执行的时候被求值的,而不是在调用执行的时候。也就是说被延期执行的函数的参数是按正常顺序被求值的,简单理解为,无论defer对应的代码行放在代码段的哪个位置,defer是在return前执行的代码行,但defer代码行中的参数是需要先声明再调用的,对应响应中的处理,golang的Response.Body需要被关闭的,body实际上是一个嵌套了多层的net.TCPConn:

  • bufio.Reader,这层尝试将多次小的读操作替换为一次大的读操作,减少系统调用的次数,提高性能;
  • io.LimitedReader,tcp连接在读取完body后不会关闭,继续读会导致阻塞,所以需要LimitedReader在body读完后发出eof终止读取;
  • chunkedReader,解析chunked格式编码(如果不是chunked略过);
  • bodyEOFSignal,在读到eof,或者是提前关闭body时会对readLoop发出回收连接的通知;
  • gzipReader,解析gzip压缩(如果不是gizp压缩略过);

从上面可以看出如果body既没有被完全读取,也没有被关闭,那么这次http事务就没有完成,除非连接因超时终止了,否则相关资源无法被回收,所以需要我们进行关闭连接的操作,这个是很多golang新手会忽略的一个点,作为client端处理response的时候,body一定要close,否则会造成GC回收不到,继而产生内存泄露

带json的post请求

我们大部分应用到的restful接口都是用json格式的请求体,对应的golang的http请求也会有相关的方式post json请求体

package main

import (
 "fmt"
 "io/ioutil"
 "net/http"
  "bytes"
 "encoding/json"
)

type HttpData struct {

 Flag int `json:"flag"`
 Msg string `json:"msg"`

}

func main() {

 url := "http://127.0.0.1:12345/postdata"
 contentType := "application/json;charset=utf-8"

 var httpdata HttpData
 httpdata.Flag = 1
 httpdata.Msg = "terrychow"

 b ,err := json.Marshal(httpdata)
 if err != nil {
  fmt.Println("json format error:", err)
  return
 }

 body := bytes.NewBuffer(b)

 resp, err := http.Post(url, contentType, body)
 if err != nil {
  fmt.Println("Post failed:", err)
  return
 }

 defer resp.Body.Close()

 content, err := ioutil.ReadAll(resp.Body)
 if err != nil {
  fmt.Println("Read failed:", err)
  return
 }

 fmt.Println("header:", resp.Header)
 fmt.Println("content:", string(content))

}

执行结果响应

E:\go_project>go run gohttptest.go
header: map[Content-Type:[application/json] Content-Length:[78] Server:[Werkzeug/0.14.1 Python/2.7.15] Date:[Thu, 06 Dec 2018 16:35:11 GMT]]
content: {
 "code": 200,
 "data": 1,
 "msg": "terrychow",
 "state": "success"
}

对于常用的get和post请求基本上就以照上面的版本执行,当然我们现在需要做的是http接口的测试,那就需要引入测试框架进行相关的校验,本文先讲解用之前提到的gocheck来进行断言

golang中的http接口测试

引入gocheck之后我们得到了以下的脚本:

package hello_test

import (
 "testing"
 "fmt"
 "strconv"
 "io/ioutil"
 "net/http"
  "bytes"
 "encoding/json"
 . "gopkg.in/check.v1"
)

var a int =1

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type MySuite struct{}

type HttpData struct {

 Flag int `json:"flag"`
 Msg string `json:"msg"`

}

var _ = Suite(&MySuite{})

var testurl string ="http://127.0.0.1:12345"

func (s *MySuite) SetUpSuite(c *C) {
 str3:="第1次套件开始执行"
 fmt.Println(str3)
 //c.Skip("Skip TestSutie")
}

func (s *MySuite) TearDownSuite(c *C) {
 str4:="第1次套件执行完成"
 fmt.Println(str4)
}

func (s *MySuite) SetUpTest(c *C) {
 str1:="第"+strconv.Itoa(a)+"条用例开始执行"
 fmt.Println(str1)

}

func (s *MySuite) TearDownTest(c *C) {
 str2:="第"+strconv.Itoa(a)+"条用例执行完成"
 fmt.Println(str2)
 a=a+1
}

func (s *MySuite) TestHttpGet(c *C) {
 geturl := fmt.Sprintf("%v/checkon", testurl)
 respget, err := http.Get(geturl)
 if err != nil {
  panic(err)
 }
 defer respget.Body.Close() //关闭连接

 body, err := ioutil.ReadAll(respget.Body) //读取body的内容
 var gdat map[string]interface{} //定义map用于解析resp.body的内容
 if err := json.Unmarshal([]byte(string(body)), &gdat); err == nil {
  fmt.Println(gdat)
 } else {
  fmt.Println(err)
 }
 var gmsg=gdat["msg"]
 c.Assert(gmsg, Equals, "terrychow") //模拟失败的断言

}

func (s *MySuite) TestHttpPost(c *C) {

 url := fmt.Sprintf("%v/postdata", testurl)
 contentType := "application/json;charset=utf-8"

 var httpdata HttpData
 httpdata.Flag = 1
 httpdata.Msg = "terrychow"

 b ,err := json.Marshal(httpdata)
 if err != nil {
  fmt.Println("json format error:", err)
  return
 }

 body := bytes.NewBuffer(b)

 resp, err := http.Post(url, contentType, body)
 if err != nil {
  fmt.Println("Post failed:", err)
  return
 }

 defer resp.Body.Close()

 content, err := ioutil.ReadAll(resp.Body)
 if err != nil {
  fmt.Println("Read failed:", err)
  return
 }
 var dat map[string]interface{} //定义map用于解析resp.body的内容
 if err := json.Unmarshal([]byte(string(content)), &dat); err == nil {
  fmt.Println(dat)
 } else {
  fmt.Println(err)
 }
 var msg=dat["msg"]
 c.Assert(msg, Equals, "terrychow") //模拟成功的断言
}

最后的输出内容:

E:\go_project>go test -v gocheckhttp_test.go
=== RUN Test
第1次套件开始执行
第1条用例开始执行
map[code:200 data: msg:online state:success]
第1条用例执行完成

----------------------------------------------------------------------
FAIL: gocheckhttp_test.go:56: MySuite.TestHttpGet

gocheckhttp_test.go:72:
 c.Assert(gmsg, Equals, "terrychow")
... obtained string = "online"
... expected string = "terrychow"

第2条用例开始执行
map[msg:terrychow state:success code:200 data:1]
第2条用例执行完成
第1次套件执行完成
OOPS: 1 passed, 1 FAILED
--- FAIL: Test (0.02s)
FAIL
FAIL command-line-arguments 0.613s

输出的结果符合预期,这也是比较基本的http接口测试

小结

就上文来说,我们基本可以通过本文掌握如何做http接口测试,其核心还是使用http依赖库发出请求获取响应,利用gocheck进行断言,当然还可以用testing,下一节继续讲一下http接口测试,但会重点讲专门做http接口测试的测试框架httpexpect以及用于mock的httptest,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 深入理解Golang的单元测试和性能测试

    前言 大家做开发的应该都知道,在开发程序中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早暴露,便于问题的定位解决,而性能测试的重点在于发现程序设计上的一些问题,让线上的程序能够在高并发的情况下还能保持稳定.本小节将带着这一连串的问题来讲解Go语言中如何来实现单元测试和性能测试. go语言中自带有一个轻量级的测试框架testing和自带的go test命令来

  • golang分层测试之http接口测试入门教程

    前言 前几话主要讲解关于使用golang进行单元测试,在单元测试的上一层就是接口测试,本节主要讲使用golang进行接口测试,其中主要以http协议的接口测试来讲解 golang中的http请求 golang中拥有一个原生的http依赖库:net/http,http服务器的建立还是http客户端的开发,都会使用到这个依赖库,这里主要讲解时client部分,作为请求发起方应用于日常的接口测试,例示代码如下: get请求 package main import ( "fmt" "

  • golang特有程序结构入门教程

    Go语言的由来 ​ Go语言亦叫Golong语言,是由谷歌Goggle公司推出.Go语言的主要开发者有:肯.汤姆逊(Ken Thompson).罗布.派克(Rob Pike)和罗伯特.格里泽默(Robert Griesemer).这三个都是大神,稍介绍一下他们的贡献: ​ 肯.汤姆逊(Ken Thompson):图灵奖得主,Uinx发明人,B语言作者(C语言前身),还做飞行员,后来被谷歌挖走. ​ 罗布.派克(Rob Pike):Unix团队和Plan 9操作系统计划的成员,与Ken老爷子共事多

  • 全网最全最细的jmeter接口测试教程以及接口测试流程(入门教程)

    目录 一.Jmeter简介 二.Jmeter安装 三.设置Jmeter语言为中文环境 四.Jmeter主要元件 五.Jmeter元件的作用域和执行顺序 六.Jmeter进行接口测试流程 七.Jmeter进行接口测试流程步骤详解 八.Jmeter接口测试必定用到的扩展阅读 九.总结 一.Jmeter简介 Jmeter是由Apache公司开发的一个纯Java的开源项目,即可以用于做接口测试也可以用于做性能测试. Jmeter具备高移植性,可以实现跨平台运行. Jmeter可以实现分布式负载. Jme

  • Golang中Gin框架的使用入门教程

    目录 安装与简单测试 常见请求与分组请求 获取参数 与 参数合法性验证 获得query中参数 获得multipart/urlencoded form中的参数 模型绑定和参数验证 自定义参数验证 项目结构参考 Gin框架运行模式 Gin如何获取客户ip Gin处理请求结果 以String类型响应请求 以Json格式响应请求 以文件形式响应请求 设置http响应头 Gin处理html模板 Gin访问静态资源文件 Gin处理Cookie操作 Gin文件上传 Gin中间件 官方地址:gin-gonic.

  • ABP(现代ASP.NET样板开发框架)系列之二、ABP入门教程详解

    ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate ABP 的由来 "DRY--避免重复

  • Go语言七篇入门教程五文件及包

    目录 1. 文件处理 1.1 JSON文件 1.1.1 已知JSON结构 1.1.2 未知JSON结构 1.1.3 Encoder & Decoder 1.2 XML文件 1.3 二进制文件 1.4 zip文件 1.4.1 创建zip 1.4.2 读取zip文件 2. 包管理 2.1 包路径 2.2 包声明 如何学习Go 1. 文件处理 1.1 JSON文件 什么是json? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 也是在web开发中的前后

  • Go语言七篇入门教程四通道及Goroutine

    目录 1. 前言 2. 通道简介 2.1 声明 2.1 读写 2.3 通道详解 2.3.1 例子 2.3.2 死锁 2.3.3 关闭通道 2.3.4 缓冲区 2.3.5 通道的长度和容量 2.3.6 单向通道 2.3.7 Select 2.3.8 default case 块 2.3.9 空 select 2.3.10 Deadlock 2.3.11 nil通道 2.4 多协程协同工作 2.5 WaitGroup 2.5.1 简介 2.5.2工作池 2.5.3 Mutex 3. 结语 如何学习G

  • Go语言七篇入门教程三函数方法及接口

    目录 1. 函数 2. 方法 3. 接口 如何学习Go 参考书籍: <go语言程序设计> 1. 函数 每个函数声明都包含一个名字,一个形参列表,一个可选的返回列表以及函数体: func name(parameter-list)(result-list){ body } 形参列表:指定另一组变量的参数名和参数类型,这些局部变量都由调用者提供的提供的实参传递而来的. 返回列表:指定了函数返回值的类型.当函数返回一个未命名的返回值或者没有返回值的时候,返回列表的圆括号可以忽略. func FanOn

  • Go语言七篇入门教程一简介初识

    目录 简介 为什么是Go Go应用 Web Cloud 云 BlockChain 区块链 如何学习Go 其实我自己接触Go语言也还不到一年,20年的10月我才开始学Go的. 我自己也并不是很懂,但是我希望我能帮助到你学习Go语言,我们可以一起学习交流~ Go语言的吉祥物-金花鼠我一直以为是土拨鼠 在某搜索引擎上一搜golang一堆表情包. 简介 Go语言亦叫Golong语言,是由谷歌Goggle公司推出.Go语言的主要开发者有:肯.汤姆逊(Ken Thompson).罗布.派克(Rob Pike

  • Jmeter入门教程

    目录 jemter简介 优点 一.下载 二.安装 三.运行 四.一个简单的压测实例 五.如何查看系统负载何性能瓶颈 jemter简介 jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简 单.因为jmeter是java开发的,所以运行的时候必须先要安装jdk才可以.jmeter是免安装的,拿到安装包之后直接解压就可以使用,同时它在 linux/windows/macos上都可以使用.    jmeter可以做接

随机推荐