一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - golang分層測試之http接口測試入門教程

golang分層測試之http接口測試入門教程

2020-05-21 10:50周學習的名字被占了 Golang

這篇文章主要介紹了golang分層測試之http接口測試入門教程,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

前幾話主要講解關于使用golang進行單元測試,在單元測試的上一層就是接口測試,本節主要講使用golang進行接口測試,其中主要以http協議的接口測試來講解

golang中的http請求

golang中擁有一個原生的http依賴庫:net/http,http服務器的建立還是http客戶端的開發,都會使用到這個依賴庫,這里主要講解時client部分,作為請求發起方應用于日常的接口測試,例示代碼如下:

get請求

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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))
}

返回結果

?
1
2
3
4
5
6
7
E:\go_project>go run testget.go
{
 "code": 200,
 "data": "",
 "msg": "online",
 "state": "success"
}

post請求:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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的方式,最后會返回一個頁面

這里說明一下以下這行代碼

?
1
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請求體

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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))
 
}

執行結果響應

?
1
2
3
4
5
6
7
8
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之后我們得到了以下的腳本:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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") //模擬成功的斷言
}

最后的輸出內容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://studygolang.com/articles/16742

延伸 · 閱讀

精彩推薦
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
主站蜘蛛池模板: 日韩欧美亚洲一区二区综合 | 女同69式互添在线观看免费 | 插鸡网站| 国产欧美成人不卡视频 | 色综合亚洲天天综合网站 | a毛片在线免费观看 | 亚洲国产AV无码综合在线 | 亚洲一卡2卡4卡5卡6卡残暴在线 | 天堂a免费视频在线观看 | 成人国产在线视频 | 成人福利免费在线观看 | 国产精品免费看久久久香蕉 | 国产一区日韩二区欧美三 | 美女视频在线观看视频 | 国产欧美另类久久精品91 | 欧美成人香蕉在线观看 | 天天综合天天色 | 色播导航 | 国产成人高清精品免费观看 | 日韩在线观看免费 | 成人福利网站含羞草 | 和老外3p爽粗大免费视频 | 久久精品成人免费看 | 色多多影院 | 精品视频在线播放 | 万域之王动漫在线观看全集免费播放 | 饭冈加奈子在线播放观看 | 精品夜夜澡人妻无码AV蜜桃 | 男人使劲躁女人小视频 | 波多野结衣亚洲一区 | 男人使劲躁女人小视频 | bt7086新片速递亚洲最新合集 | 免费抽搐一进一出印度 | 肥奶丰熟肥妇 | 女暴露狂校园裸露小说 | caoporn草棚在线视频 | 日本成人免费在线视频 | 俄罗斯一级毛片免费播放 | 天堂在线中文无弹窗全文阅读 | 久久精品视频免费 | 亚洲色欲色欲综合网站 |