【go项目01_学习记录12】

1 代码结构

所有的代码写在一个main.go文件里面,GO编译器也是可以正常执行的。但是当代码量很庞大时,很难进行维护。

Go Web 程序的代码组织

  1. 单文件——反模式
  2. 多文件——扁平模式
  3. 目录归类——分层模式

之前main.go文件里的内容:
4. 应用初始化 —— 数据库连接初始化、路由初始化、配置加载等…
5. 路由 —— 配置 URI 与控制器的对应关系
6. 控制器 —— 处理业务逻辑的 aboutHandler、homeHandler、articlesShowHandler 等
7. 数据库操作 —— 创建表、查询等
8. 数据模型 —— Article
9. 表单验证
10. 辅助函数 —— Int64ToString、RouteName2URL
11. 中间件
12. 错误处理等

2 重构与测试

2.1 安装测试功能

安装 stretchr/testify ,这是一个知名的第三方测试包,将用到它的断言(Assertion)功能。

go get github.com/stretchr/testify

编写测试文件tests/pages_test.go
后缀名 _test 是一个特殊标识,会告知 Go 编译器和工具链这是一个测试文件。Go 编译器在编译时会跳过这些文件,而工具 go test 在执行时默认会运行当前目录下所有拥有 _test 后缀名的文件。

package tests

import (
    "net/http"
    "testing"

    "github.com/stretchr/testify/assert"
)

func TestHomePage(t *testing.T) {
    baseURL := "http://localhost:3000"

    // 1. 请求 —— 模拟用户访问浏览器
    var (
        resp *http.Response
        err  error
    )
    resp, err = http.Get(baseURL + "/")

    // 2. 检测 —— 是否无错误且 200
    assert.NoError(t, err, "有错误发生,err 不为空")
    assert.Equal(t, 200, resp.StatusCode, "应返回状态码 200")
}

2.2 testify 的常用断言函数

 // 相等
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
// 是否为 nil
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
// 是否为空
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
// 是否存在错误
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool
// 是否为 0 值
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool
// 是否为布尔值
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool
// 断言长度一致
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool
// 断言包含、子集、非子集
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool)
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool)
// 断言文件和目录存在
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool

在这里插入图片描述
显示ok则成功

3 表组测试

Go 语言中,对于具备相同的测试逻辑的场景,可以使用简洁紧凑的 表组测试。
tests/pages_test.go

package tests

import (
	"net/http"
	"strconv"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestAllPages(t *testing.T){

	baseURL := "http://localhost:3000"

	// 1. 声明加初始化测试数据
	var tests = []struct {
		method string
		url		string
		expected int
	}{
		{"GET","/",200},
		{"GET","/notfound",404},
		{"GET","/about",200},
		{"GET","/articles",200},
		{"POST","/articles",200},
		{"GET","/articles/create",200},
		{"GET","/articles/3",200},
		{"POST","/articles/3",200},
		{"GET","/articles/3/edit",200},
		{"POST","/articles/4/delete",404},
	}

	// 2. 遍历所有测试
	for _, test := range tests {
		t.Logf("当前请求 URL :%v \n", test.url)
		var(
			resp * http.Response
			err error
		)
		// 2.1 请求以获取响应
		switch{
		case test.method == "POST":
			data := make(map[string][]string)
			resp,err = http.PostForm(baseURL + test.url, data)
		default:
			resp,err = http.Get(baseURL + test.url)
		}
		// 2.2 断言
		assert.NoError(t,err,"请求"+test.url+" 时报错")
		assert.Equal(t, test.expected, resp.StatusCode, test.url+" 应返回状态码"+strconv.Itoa(test.expected))
	}
}

标准库里的辅助方法打印出来的数据:

t.Logf("当前请求 URL: %v \n", test.url)

在这里插入图片描述
使用 go test ./tests或者点击函数旁边的运行,前者不会显示t.Logf()里的内容,前者需要添加**-v** 详细打印。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值