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之应用测试的更多相关文章

  1. Golang项目的测试实践

    Golang项目的测试实践 最近有一个项目,链路涉及了4个服务.最核心的是一个配时服务.要如何对这个项目进行测试,保证输出质量,是最近思考和实践的重点.这篇就说下最近这个实践的过程总结. 测试金字塔 ...

  2. golang:interface{}类型测试

    在golang中空的interface即interface{}可以看作任意类型, 即C中的void *. 对interface{}进行类型测试有2种语法: 1. Comma-ok断言: value, ...

  3. [Go] golang连接redis测试

    go-redis的使用1.下载代码到GOPATH环境变量指定的目录比如我的是进入目录D:\golang\code\src\github.com\go-redis , 执行git clone https ...

  4. 关于swoole 和golang 的压力测试结果

    一.环境介绍 linux centos7 php7.1.18 go1.12.1 2核4G内存 二.代码 swoole代码 <?php $http = new swoole_http_server ...

  5. Golang 端口复用测试

    先给出结论: 同一个进程,使用一个端口,然后连接关闭,大约需要30s后才可再次使用这个端口. 测试 首先使用端口9001连接服务端,发送数据,然后关闭连接,接着再次使用端口9001连接服务端,如果连接 ...

  6. Golang 简单web测试

    // mhoso project main.go package main import ( "log" "net/http" "./controll ...

  7. Golang测试技术

    本篇文章内容来源于Golang核心开发组成员Andrew Gerrand在Google I/O 2014的一次主题分享“Testing Techniques”,即介绍使用Golang开发 时会使用到的 ...

  8. Golang 语言的单元测试和性能测试(也叫 压力测试)

    Golang单元测试对文件名和方法名,参数都有很严格的要求. 例如: 1.文件名必须以xx_test.go命名 2.方法必须是Test[^a-z]开头(T必须大写),func TestXxx (t * ...

  9. golang测试

    简述 Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试. go test [-c] [-i] [build flags] [packages] [f ...

随机推荐

  1. PHP+Ajax点击加载更多内容

    css样式: <style type="text/css"> #more{margin:10px auto;width: 560px; border: 1px soli ...

  2. 关于steam平台“wallpaper engine”软件出现界面黑屏,但壁纸能播放的问题

    前阵子重装电脑后,在使用wallpaper engine这款软件时发现了以下令人疑惑的画面: 点击"设置"和"壁纸选择"界面全是黑的......这还没完,更气人 ...

  3. Hadoop大数据平台之Kafka部署

    环境:CentOS 7.4 (1708  DVD) 工具:Xshell+Xftp 1. 使用xftp将kafka上传到/usr/local目录下,将kafka解压并重命名. 2. 编辑kafka/co ...

  4. Pinpoint 设置微信或者钉钉预警

    本文基于 Pinpoint 2.1.0 版本 本文大部分内容来自:侠梦的开发笔记 ,但是原文的版本和我的不一致,放在2.1.0是跑不起来的,但是大概逻辑和思路基本一致. 目录 一.接入预警大概思路 二 ...

  5. H5系列之canvas

    what is canvas?(什么是canvas) 其实他只是H5里面的一个标签而已,那么他作为一个标签,肯定有他的用途,他就像是一幅画布,等待着你来作画.可以说,他只是一个容器而已,需要配合着Ja ...

  6. python批量爬取猫咪图片

    不多说直接上代码 首先需要安装需要的库,安装命令如下 pip install BeautifulSoup pip install requests pip install urllib pip ins ...

  7. Centos7 安装python3 pip3

    Centos7 安装python3 pip3 安装python3.6 安装 python36   yum install python36 -y   查看版本 安装完成,查看一下python版本是否正 ...

  8. Map<String,Object>接收参数,Long类型降级为Integer,报类型转换异常

    前言 今天看群里小伙伴问了一个非常有意思的问题: 使用 Map<String,Object> 对象接收前端传递的参数,在后端取参时,因为接口文档中明确该字段类型为 Long ,所以对接收的 ...

  9. Vue+EasyPOI导出Excel(带图片)

    一.前言 平时的工作中,Excel 导入导出功能是非常常见的功能,无论是前端 Vue (js-xlsx) 还是 后端 Java (POI),如果让大家手动编码实现的话,恐怕就很麻烦了,尤其是一些定制化 ...

  10. JS代码下载百度文库纯文本文档

    下载百度文库纯文本文档流程 1.按 F12 或  Ctrl+Shift+I打开后台(或点击右键,在点击检查)[建议使用谷歌浏览器] 2.切换到控制台,赋值粘贴以下js代码,回车后,浏览器将自动下载保存 ...