九、Golang测试和性能

news/2024/10/17 16:20:24/

一、单元测试
单元测试是用来测试包或者程序的一部分代码或者一组代码的函数。
在Golang中有几种方法写单元测试,基础测试只使用一组参数和结果来测试一段代码。
表组测试也会测试一段代码,但是会使用多组参数和结果进行测试。也可以使用一些方法来模仿测试代码需要使用到的外部资源。
下面是一个单元测试的例子
listing01_test.go

package mainimport ("net/http""testing"
)const checkMark = "\u2713"
const ballotX = "\u2717"//用来确认http包的Get函数可以下载内容
func TestDownload(t *testing.T) {url := "http://www.goinggo.net/index.xml"statusCode := 200t.Log("Given the need to test downloading content."){t.Logf("\tWhen checking \"%s\" for status code \"%d\"", url, statusCode){resp, err := http.Get(url)if err != nil {t.Fatal("Should be able to make the Get call.", ballotX, err )}t.Log("Should be able to make the Get call.", checkMark)defer resp.Body.Close()if resp.statusCode == statusCode {t.Logf("xxx")}else {t.Errorf("xxx")}}}
}

1、可以运行go test -v来运行这个测试
2、Go语言的测试工具只会认为以test.go结尾的文件是测试文件。
3、一个测试函数必须是公开的函数,并且以Test单词开头。
4、不但函数名字要以Test开头,而且函数的签名必须接收一个指向testing.T类型的指针,并且不返回任何值。
5、如果没有遵守这些约定,测试框架就不会认为这个函数是一个测试函数,也不会让测试工具去执行它。
6、使用t.Log来输出测试的消息。这个方法还有一个名为t.Logf的版本可以格式化消息
7、t.Fatal方法不但报告这个单元测试已经失败,而且会向测试输出写一些消息,而后立刻停止这个测试函数的执行
8、如果状态码匹配,我们就使用t.Logf方法输出信息,否则就使用t.Errorf方法。t.Errorf方法不会停止当前测试函数的执行,所以,如果在第三行之后还有测试,单元测试就会继续执行。
9、如果测试函数执行时没有调用过t.Fatal或者t.Error方法,就会认为测试通过了

二、表组测试
如果测试可以接收一组不同的输入并产生不同的输出的代码,那么应该使用表组测试的方法进行测试。表组测试除了会有一组不同的输入值和期望结果之外,其余部分都很像基础单元测试。测试会依次迭代不同的代码的值,来运行要测试的代码。每次迭代的时候,都会检测返回的结果。这便于在一个函数里测试不同的输入值和条件。

// Sample test to show how to write a basic unit table test.
package listing08import ("net/http""testing"
)const checkMark = "\u2713"
const ballotX = "\u2717"// TestDownload validates the http Get function can download
// content and handles different status conditions properly.
func TestDownload(t *testing.T) {var urls = []struct {url        stringstatusCode int}{{"http://www.goinggo.net/feeds/posts/default?alt=rss",http.StatusOK,},{"http://rss.cnn.com/rss/cnn_topstbadurl.rss",http.StatusNotFound,},}t.Log("Given the need to test downloading different content."){for _, u := range urls {t.Logf("\tWhen checking \"%s\" for status code \"%d\"",u.url, u.statusCode){resp, err := http.Get(u.url)if err != nil {t.Fatal("\t\tShould be able to Get the url.",ballotX, err)}t.Log("\t\tShould be able to Get the url.",checkMark)defer resp.Body.Close()if resp.StatusCode == u.statusCode {t.Logf("\t\tShould have a \"%d\" status. %v",u.statusCode, checkMark)} else {t.Errorf("\t\tShould have a \"%d\" status. %v %v",u.statusCode, ballotX, resp.StatusCode)}}}}
}

三、模仿调用
模仿是一个很常用的技术手段,用来在运行测试时模拟访问不可用的资源,包httptest可以让你能够模仿互联网资源的请求和响应。在我们的单元测试中,通过模仿http.Get的响应,保证在没有网络的情况下测试也不会失败。

// Sample test to show how to mock an HTTP GET call internally.
// Differs slightly from the book to show more.
package listing12import ("encoding/xml""fmt""net/http""net/http/httptest""testing"
)const checkMark = "\u2713"
const ballotX = "\u2717"// feed is mocking the XML document we except to receive.
var feed = `<?xml version="1.0" encoding="UTF-8"?>
<rss>
<channel><title>Going Go Programming</title><description>Golang : https://github.com/goinggo</description><link>http://www.goinggo.net/</link><item><pubDate>Sun, 15 Mar 2015 15:04:00 +0000</pubDate><title>Object Oriented Programming Mechanics</title><description>Go is an object oriented language.</description><link>http://www.goinggo.net/2015/03/object-oriented</link></item>
</channel>
</rss>`// mockServer returns a pointer to a server to handle the get call.
func mockServer() *httptest.Server {f := func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(200)w.Header().Set("Content-Type", "application/xml")fmt.Fprintln(w, feed)}return httptest.NewServer(http.HandlerFunc(f))
}// TestDownload validates the http Get function can download content
// and the content can be unmarshaled and clean.
func TestDownload(t *testing.T) {statusCode := http.StatusOKserver := mockServer()defer server.Close()t.Log("Given the need to test downloading content."){t.Logf("\tWhen checking \"%s\" for status code \"%d\"",server.URL, statusCode){resp, err := http.Get(server.URL)if err != nil {t.Fatal("\t\tShould be able to make the Get call.",ballotX, err)}t.Log("\t\tShould be able to make the Get call.",checkMark)defer resp.Body.Close()if resp.StatusCode != statusCode {t.Fatalf("\t\tShould receive a \"%d\" status. %v %v",statusCode, ballotX, resp.StatusCode)}t.Logf("\t\tShould receive a \"%d\" status. %v",statusCode, checkMark)var d Documentif err := xml.NewDecoder(resp.Body).Decode(&d); err != nil {t.Fatal("\t\tShould be able to unmarshal the response.",ballotX, err)}t.Log("\t\tShould be able to unmarshal the response.",checkMark)if len(d.Channel.Items) == 1 {t.Log("\t\tShould have \"1\" item in the feed.",checkMark)} else {t.Error("\t\tShould have \"1\" item in the feed.",ballotX, len(d.Channel.Items))}}}
}// Item defines the fields associated with the item tag in
// the buoy RSS document.
type Item struct {XMLName     xml.Name `xml:"item"`Title       string   `xml:"title"`Description string   `xml:"description"`Link        string   `xml:"link"`
}// Channel defines the fields associated with the channel tag in
// the buoy RSS document.
type Channel struct {XMLName     xml.Name `xml:"channel"`Title       string   `xml:"title"`Description string   `xml:"description"`Link        string   `xml:"link"`PubDate     string   `xml:"pubDate"`Items       []Item   `xml:"item"`
}// Document defines the fields associated with the buoy RSS document.
type Document struct {XMLName xml.Name `xml:"rss"`Channel Channel  `xml:"channel"`URI     string
}

四、测试服务端点
服务端点是指与服务宿主信息无关,用来分辨某个服务的地址,一般是不包含宿主的一个路径


http://www.ppmy.cn/news/51168.html

相关文章

Vue3 + TS4.8踩坑之配置husky问题env: sh\r: No such file or directory

一、基本情况&#xff1a; 硬件环境&#xff1a;MacOS 10.14.6 背景&#xff1a; 1&#xff0c;用vue3官方npm init vuelatest初始化创建的vue3 ts4.8项目&#xff0c;IDE是 VS Cde 1.77.3版本 2&#xff0c;初始化项目之后给项目配置了.editorconfig&#xff0c;方便团队…

基于ansible初始化linux服务器基础环境。

大家好&#xff0c;今天我要和大家分享一个关于搭建centos环境的新方法。 以前我们经常会看到一些文章介绍如何搭建centos环境&#xff0c;但很多时候都会出现一些问题。不过现在有了一种新的方法&#xff0c;就是使用ansible脚本来实现。 虽然这种方法仅适用于centos7&#…

Redis 快速上手 Java 增删改查(包含 RedisTemplateConfig 的编写)

一&#xff1a;Redis 数据类型 先了解 redis 的五种基本数据类型。 String 字符串类型&#xff1a;name: "value1"List 列表&#xff1a;names: ["value1", "value2", "value2"]Set 集合&#xff1a;names: ["value1", &qu…

shell编程规范与变量

shell脚本编程规范 shell脚本概述 将要执行的命令按顺序保存到一个文本文件给该文件可执行权限可结合各种Shell控制语句以完成更复杂的操作 Shell脚本应用场景 重复性操作交互性任务批量事务处理服务运行状态监控定时任务执行 什么是Shell 就是与内核沟通的界面、应用程序等…

logback日志框架集成方式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、logback是什么&#xff1f;二、使用步骤1.使用方式控制台输出配置文件输出配置html输出配置定期删除配置方式 总结 前言 提示&#xff1a;这里可以添加本文…

【C++】右值引用(极详细版)

在讲右值引用之前&#xff0c;我们要了解什么是右值&#xff1f;那提到右值&#xff0c;就会想到左值&#xff0c;那左值又是什么呢&#xff1f; 我们接下来一起学习&#xff01; 目录 1.左值引用和右值引用 1.左值和右值的概念 2.左值引用和右值引用的概念 2.左值引用和右…

达梦数据迁移问题罗列

目录 一、前言 二、问题罗列 一、前言 最近小编接触到国产的数据库达梦数据库&#xff0c;然后在用达梦数据迁移工具MySQL迁移至达梦的时候遇到了一系列的问题现在罗列一下在这里。目前关于国产的数据库达梦这些资料比较少&#xff0c;希望能够帮到有需要的同志们&#xff01…

Java面试题面向对象部分

面向对象 面向对象概述 面向对象和面向过程的区别 面向过程&#xff1a; 优点&#xff1a;性能比面向对象高&#xff0c;因为类调用时需要实例化&#xff0c;开销比较大&#xff0c;比较消耗资源;比如单片机、嵌入式 开发、Linux/Unix等一般采用面向过程开发&#xf…