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

代码组织

  • 1 代码结构
  • 2 重构与测试
    • 2.1 安装测试功能
    • 2.2 testify 的常用断言函数
  • 3 表组测试

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** 详细打印。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626731.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C51 单片机编程模板及编码规范

文章目录 一、C51 单片机模板创建1. 新建工程及选型2. 创建主程序文件3. 创建主程序的头文件4. 编译配置5. 其他 二、C51 的编码规范 在查阅了很多关于 C51 单片机的程序后,个人感觉目前网上有关 C51 单片机程序的质量参差不齐,很多程序的代码风格及其糟…

Kubernetes——CNI网络组件

目录 一、Kubernetes三种接口 二、Kubernetes三种网络 三、VLAN与VXLAN 1.VLAN 2.VXLAN 3.区别 3.1作用不同 3.2vxlan支持更多的二层网络 3.3已有的网络路径利用效率更高 3.4防止物理交换机Mac表耗尽 3.5相对VLAN技术,VXLAN技术具有以下优势 四、CNI网…

设计模式-动态代理

目录 定义 代理模式的优缺点 优点 缺点 应用场景 静态代理 动态代理 相关资料 定义 代理模式(Proxy Pattern)是一种结构型设计模式,它的概念很简单,它通过创建一个代理对象来控制对原始对象的访问。代理模式主要涉及两个…

分布式搜索-elaticsearch基础 概念

什么是elaticsearch: 倒排索引:就是将要查询的内容分成一个个词条,在将词条文档id存入,词条是唯一的。 文档词条总结: mysql和Elasticsearch概念对比: 架构: 基本概念总结:

uniapp 实现下拉刷新 下滑更新

效果图 在app或者小程序中向下滑动 会出现刷新数据 ,而上拉到底 需要更新数据 功能实现 主要俩种方式 依赖生命周期 在page.json中开启 page.json "style" : {"navigationBarTitleText" : "小小练习","backgroundTextStyle": &qu…

Transformer模型详解05-Decoder 结构

文章目录 简介结构原理第一个 Multi-Head Attention第二个 Multi-Head AttentionSoftmax 预测输出单词 简介 Transformer 模型由编码器(Encoder)和解码器(Decoder)两部分组成。这里我会着重描述解码器的结构以及在预训练、输入输…

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读 Abstract1 Introduction2 Related Work3 Proposed Approach4 Experiments5 Conclusion 文章信息: 原文链接:https://ojs.aaai.org/index.php/AAAI/article/view/4…

期权(1):基本概念,权利金,定金,买方,卖方,零和游戏,对赌协议

期权是合约,权利金就是定金! 合约到期时 买方可以选择行权,也可以选择不行权。代价就是定金损失。因此亏损封顶,但盈利无限。卖方赚的就是买方的定金,盈利封顶,但亏损无限。 从这里,我们看出…

短视频拍摄+直播间搭建视觉艺术实战课:手把手场景演绎 从0-1短视频-8节课

抖音短视频和直播间你是否遇到这些问题? 短视频是用手机拍还是相机拍?画面怎么拍都没有质感 短视频产量低,拍的素材可用率低 看到别人用手机就能把短视频拍好自己却无从下手 明明已经打了好几盏灯了,但是画面还是比较暗 直播软件参数不会设置,电脑…

【Python探索之旅】列表

目录 特点 入门 访问元素 新增元素 修改元素 插入元素 删除元素 完结撒花 前言 在Python中,列表(List)是最常用的数据结构之一,类似于其他语言,如Java,与其不同啊Python中不需要声明数据类型。它提供了一种灵活且高效的方式…

MySQL创建索引报错 Specified key was too long;max key length is 1000 bytes.

MySQL对创建索引的大小有限制,一般索引键最大长度总和不能超过1000个字节。 问题描述 MySQL创建索引时报错 Specified key was too long;max key length is 1000 bytes. 解决办法 (1) 修改存储引擎 InnoDB的索引字段长度限制大于MyISAM,可以尝试改成…

ansible利用playbook 部署lamp架构

搭建参考:ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…

【windows小知识#1】ISO镜像,OEM、Retail这些到底是什么意思

汇总一下每个版本windows会衍生哪些镜像出来,以windows7为例 这些文件名代表的是不同版本和不同语言的Windows 7操作系统的安装光盘映像(ISO文件)。这些文件主要区分为以下几个方面: 语言:这些文件都是中文版&#x…

平地惊雷,GPT-4o 凌晨震撼发布

GPT-4o 今日凌晨,OpenAI 2024 年春季发布会召开,OpenAI 通过短短 28 分钟的发布会,发布了「再次震惊世界」的 GPT-4o,其中 o 是指 omni(全能)的意思。 一款「全新交互(支持 文本/音频/视频 组合…

【AI学习】聊两句昨夜OpenAI的GPT-4o

蹭个热点,聊两句昨夜的大事件——OpenAI发布GPT-4o,我看到和想到的一点东西。 首先是端到端方法,前面关于深度学习的文章,对端到端的重要性做了一些学习,对端到端这个概念有了一些理解。正如Richard Sutton在《苦涩的…

直播预约丨《袋鼠云大数据实操指南》No.2:实时开发,如何成为数据智能化的有效驱动力

近年来,新质生产力、数据要素及数据资产入表等新兴概念犹如一股强劲的浪潮,持续冲击并革新着企业数字化转型的观念视野,昭示着一个以数据为核心驱动力的新时代正稳步启幕。 面对这些引领经济转型的新兴概念,为了更好地服务于客户…

C语言中的混合运算

1 混合运算 类型强制转换场景 整型数进行除法运算时&#xff0c;如果运算结果为小数&#xff0c;那么存储浮点数时一定要进行强制转换。例子&#xff1a; #include <stdio.h> //运算强制转换 int main(void) {int i5;//整型float ji/2;//这里做的是整型运算&#xff0…

【Linux取经路】进程通信之匿名管道

文章目录 一、进程间通信介绍1.1 进程间通信是什么&#xff1f;1.2 进程间通信的目的1.3 进程通信该如何实现 二、管道2.1 匿名管道2.1.1 站在文件描述符角度深入理解管道2.1.2 接口使用2.1.3 PIPE_BUFFER 和 Pipe capacity2.1.4 管道中的四种情况2.1.5 管道特征总结 2.2 匿名管…

PDF文件转换为CAD的方法

有时候我们收到一个PDF格式的设计图纸&#xff0c;但还需要进行编辑或修改时&#xff0c;就必须先将PDF文件转换回CAD格式。分享两个将PDF转换回CAD的方法&#xff0c;一个用到在线网站&#xff0c;一个用到PC软件&#xff0c;大家根据情况选择就可以了。 ☞在线CAD网站转换 …

STM32 CANFD 基础知识留档

讲得比较细的文章但可能有问题自行判定 附1 附2 前言 CAN2.0 协议中数据段波特率和仲裁段波特率默认是一致&#xff0c;因此只需要关注传输波特率即可 CANFD 协议是向下兼容 CAN2.0 的数据通讯&#xff0c;因此实际使用中需要配置 STM32H7 系列支持的标准是 Compliant with …