Golang之应用测试
Go 应用测试
测试的覆盖率
命令:
go test ./ -v -cover
在《Go Web
编程》一书中,有以下结论:
这并不是绝对的,测试文件可以在不同的包,进行测试也是不会出现问题的。
但是这样的说法引起了我的兴趣。
果然,执行测试的时候添加参数-cover
的时候,如果不在同一个包,将会输出以下内容:
coverage: [no statements]
是没有办法得到,相关测试代码覆盖率的数据的。
如果测试文件和被测试文件处于同一包下,才可以得到测试代码覆盖率相关数据的输出。
coverage: 95.0% of statements
并行测试
命令:
go test ./ -v -cover -parallel 3
-parallel 3
表示最多希望 3
个测试并行执行。
并发测试,利用多核优势,使用 Parallel
方法的函数必须 > 1
,否则无法使用并发优势只有一个测试函数使用 Parallel
是没有效果的。
可通过运行以下代码,并对比测试时间即可验证结论:
package main
import (
"testing"
"time"
)
func TestParallel_1(t *testing.T) {
t.Parallel()
time.Sleep(1 * time.Second)
}
func TestParallel_2(t *testing.T) {
t.Parallel()
time.Sleep(2 * time.Second)
}
func TestParallel_3(t *testing.T) {
t.Parallel()
time.Sleep(3 * time.Second)
}
基准测试
命令:
go test -v -cover -bench="BenchmarkQueryUser" -run x
上面的命令既运行了基准测试,也运行了功能测试。如果需要,用户也可以通过运行标志
-run
来忽略功能测试。-run
标志用于指定需要被执行的功能测试用例,如果用户把一个不存在的功能测试名字用作-run
标志的参数,那么所有功能测试都将被忽略。上面的命令中使用
-run x
,如果测试中不存在任何名字为x
的功能测试用例,因此所有功能测试都不会被运行。
基准测试函数格式为:
func BenchmarkXX×(*testing. B){ ... }
举例:
//基准测试
func BenchmarkQueryUser(b *testing.B) {
for i := 0; i < b.N; i++ {
user,err := userinfo.QueryUserById(1)
if err != nil{
b.Fatal("测试不通过,出现异常,err :",err)
}else {
fmt.Println("查询到数据:Result User=",*user)
}
}
}
输出如下:
BenchmarkQueryUser-8 4711 282508 ns/op
PASS
coverage: 0.0% of statements
ok Go_test/src/unitTest 1.416s
注意for
循环里的 b.N
表示循环块内的语句将执行b.N
次。
在进行基准测试时,测试用例的迭代次数是由Go自行决定的,虽然用户可以通过限制基准测试的运行时间达到限制迭代次数的目
的,但用户是无法直接指定迭代次数的——测试程序将进行足够多次的迭代,直到获得一个准确的测量值为止。
HTTP 测试
Go
不经为单元测试提供了包,还为Go Web
应用提供了专有的包--testing-httptest
包。
对Go Web
应用的单元测试可以通过testing/httptest
包来完成。这个包提供了模拟一个Web
服务器所需的设施,用户可以利用net/http
包中的客户端函数向这个服务器发送HTTP
请求,然后获取模拟服务器返回的HTTP
响应。
例子:
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestHandleGet(t *testing.T) {
mux := http.NewServeMux() //创建一个多路复用器,用于运行测试
mux.HandleFunc("/post/", handleRequest) //绑定需要测试的处理器
writer := httptest.NewRecorder() //创建记录器,用于获取HTTP响应
request, _ := http.NewRequest("GET", "/post/1", nil) //为被测试的处理器创建相应的请求
mux.ServeHTTP(writer, request) //发送测试请求
//对请求返回的响应结果进行检查处理
if writer.Code != 200 {
t.Errorf("Response code is %v", writer.Code)
}
var post Post
json.Unmarshal(writer.Body.Bytes(), &post)
if post.Id != 1 {
t.Errorf("Cannot retrieve JSON post")
}
}
//与上面的测试方法同理
func TestHandlePut(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("/post/", handleRequest)
writer := httptest.NewRecorder()
json := strings.NewReader(`{"content":"Updated post","author":"Sau Sheong"}`)
request, _ := http.NewRequest("PUT", "/post/1", json)
mux.ServeHTTP(writer, request)
if writer.Code != 200 {
t.Errorf("Response code is %v", writer.Code)
}
}
以上例子中,每个测试用例都会独立运行并启动各自独立的用于测试的Web
服务器。
程序需要创建一个多路复用器并将handleRequest
处理器与其进行绑定。除此之外,为了获取服务器返回的HTTP
响应,程序使用httptest.New Recorder
函数创建了一个 ResponseRecorder
结构,这个结构可以把响应存储起来以便进行后续的检查。
Go 的testing
包允许用户通过TestMain
函数,在进行测试时执行相应的预设( setup
)操作或者拆卸( teardown
)操作。一个典型的TestMain
函数看上去是下面这个样子的:
func TestMain (m *testing.M){
setUp ()
code := m. Run ( )tearDown ()
os.Exit (code)
}
setUp
函数和tearDown
函数分别定义了测试在预设阶段以及拆卸阶段需要执行的工作。需要注意的是,setUp
函数和tearDown
函数是为所有测试用例设置的,它们在整个测试过程中只会被执行一次,其中setup
函数会在所有测试用例被执行之前执行,而tearDown
函数则会在所有测试用例都被执行完毕之后执行。至于测试程序中的各个测试用例,则由testing.M
结构的Run
方法负责调用,该方法在执行之后将返回一个退出码( exit code
),用户可以把这个退出码传递给os.Exit
函数。
测试替身、依赖注入
测试替身(
test double
)是一种能够让单元测试用例变得更为独立的常用方法。当测试不方便使用实际的对象、结构或者函数时,我们就可以使用测试替身来模拟它们。因为测试替身能够提高被测试代码的独立性,所以自动单元测试环境经常会使用这种技术。
实现测试替身的一种设计方法是使用依赖注入(
dependency injection
)设计模式。这种模式迪过向被调用的对象、结构或者函数传人依赖关系,然后由依赖关系代替被调用者执行实际的操作,以此来解耦软件中的两个或多个层(layer
),而在Go
语言当中,(被传入的依赖关系通常会是一种接口类型。接下来,就让我们来看看,如何在第7章介绍的简单Web
服务中使用依赖注入设计模式。
具体看图内的解耦过程:
原流程:
自顶向下进行解耦依赖关系:
Golang之应用测试的更多相关文章
- Golang项目的测试实践
Golang项目的测试实践 最近有一个项目,链路涉及了4个服务.最核心的是一个配时服务.要如何对这个项目进行测试,保证输出质量,是最近思考和实践的重点.这篇就说下最近这个实践的过程总结. 测试金字塔 ...
- golang:interface{}类型测试
在golang中空的interface即interface{}可以看作任意类型, 即C中的void *. 对interface{}进行类型测试有2种语法: 1. Comma-ok断言: value, ...
- [Go] golang连接redis测试
go-redis的使用1.下载代码到GOPATH环境变量指定的目录比如我的是进入目录D:\golang\code\src\github.com\go-redis , 执行git clone https ...
- 关于swoole 和golang 的压力测试结果
一.环境介绍 linux centos7 php7.1.18 go1.12.1 2核4G内存 二.代码 swoole代码 <?php $http = new swoole_http_server ...
- Golang 端口复用测试
先给出结论: 同一个进程,使用一个端口,然后连接关闭,大约需要30s后才可再次使用这个端口. 测试 首先使用端口9001连接服务端,发送数据,然后关闭连接,接着再次使用端口9001连接服务端,如果连接 ...
- Golang 简单web测试
// mhoso project main.go package main import ( "log" "net/http" "./controll ...
- Golang测试技术
本篇文章内容来源于Golang核心开发组成员Andrew Gerrand在Google I/O 2014的一次主题分享“Testing Techniques”,即介绍使用Golang开发 时会使用到的 ...
- Golang 语言的单元测试和性能测试(也叫 压力测试)
Golang单元测试对文件名和方法名,参数都有很严格的要求. 例如: 1.文件名必须以xx_test.go命名 2.方法必须是Test[^a-z]开头(T必须大写),func TestXxx (t * ...
- golang测试
简述 Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试. go test [-c] [-i] [build flags] [packages] [f ...
随机推荐
- HDU100题简要题解(2070~2079)
HDU2070 Fibbonacci Number 题目链接 Problem Description Your objective for this question is to develop a ...
- webug第五关:一个优点小小的特殊的注入
第五关:一个优点小小的特殊的注入 既然是头部注入,首先想到xff注入 出现数据库报错,而且他是直接将xff后的内容带入数据库查询
- 如何使用iMindMap制作更专业的时间计划
时间计划无论是在日常生活中,还是在工作中,都显得极为重要.小到每周的购物时间规划,大到大型项目的时间管理,时间计划都会如影随形.虽然时间计划很重要,但很多人都会忽视这种重要性,可能只会在台本日历上作一 ...
- 如何使用OCR编辑器检查和识别文本
ABBYY FineReader 15(Windows系统)中的OCR编辑器能帮助用户对扫描仪或者数码相机获取的图像文件进行自动文本识别,OCR区域绘制等,使这些图像文件能进一步转换为可编辑的格式.其 ...
- iMindMap组织结构视图在工作上的应用体现在哪些方面
iMindMap的组织结构图视图,可以将信息.想法和流程整合起来.本文,我们将讲述iMindMap组织结构图视图的3个实例应用. iMindMap组织结构视图 简化您的工作流程 通过在工作中构建组织结 ...
- 美食vlog如何剪辑?用什么视频制作软件剪辑比较好?
是不是发现自己拍摄的美食永远没有美食博主拍出来的好看?那么美食vlog如何剪辑?用什么视频制作软件剪辑比较好呢?下面小编就教大家用视频编辑软件会声会影强大的颜色分级功能就能拯救你的美食vlog. 接下 ...
- jQuery 第一章 $()选择器
jquery 是什么? jquery 其实就是一堆的js函数(js库),也是普通的js而已. 有点像我们封装一个函数,把他放到单独的js 文件,等待有需要的时候调用它. 那么使用它有啥好处呢? jqu ...
- 到底为什么不要用SELECT *
SELECT * 无论工作还是面试,说到sql优化,比说的一个问题就是,代码中sql不要出现 SELECT *,之前一直也没有深入去研究研究,为什么,只是记住了,代码中注意了,但是就在今天逛某某论坛时 ...
- python字节自适应转化单位KB、MB、GB
文件存储或者传输的过程中,经常需要展示传输文件的大小,或者传输量的大小,为了方便给人展示和阅读,编写一个简单的单位转换器. 1 def hum_convert(value): 2 units = [& ...
- Let's Do 本地开发智能合约
上篇文章我们发了个币,有人抱怨在线(remix)写代码不爽,好吧,那就来看下怎么在本地开发智能合约? 一.安装开发环境 1.安装Node,Node v8.9.4或更高版本 我安装的是: 2.集成开发框 ...