golang BDD兼容的分支测试框架插件库biff的使用
Golang BDD兼容的分支测试框架插件库biff的使用
简介
Biff是一个基于嵌套用例或替代方案的分支框架(BIFurcation Framework)。您可以利用变量作用域使测试更简单、更易读。它是验收和用例测试的良好选择,提供BDD风格的输出。
快速开始
以下是一个完整的biff使用示例:
package main
import (
"github.com/fulldump/biff"
)
// 示例服务
type MyService struct {
users map[string]*User
}
type User struct {
Email string
Password string
}
func NewMyService() *MyService {
return &MyService{
users: make(map[string]*User),
}
}
func (s *MyService) RegisterUser(email, password string) *User {
user := &User{Email: email, Password: password}
s.users[email] = user
return user
}
func (s *MyService) Login(email, password string) *User {
user, exists := s.users[email]
if !exists || user.Password != password {
return nil
}
return user
}
func main() {
// Biff测试示例
biff.Alternative("Instance service", func(a *biff.A) {
s := NewMyService()
a.Alternative("Register user", func(a *biff.A) {
john := s.RegisterUser("john@email.com", "john-123")
a.AssertNotNil(john)
a.Alternative("Bad credentials", func(a *biff.A) {
user := s.Login(john.Email, "bad-password")
a.AssertNil(user)
}).Alternative("Login", func(a *biff.A) {
user := s.Login(john.Email, john.Password)
a.AssertEqual(user, john)
})
})
})
}
测试输出示例:
=== RUN TestExample
Case: Instance service
Case: Register user
john is &example.User{Email:"john@email.com", Password:"john-123"}
Case: Bad credentials
user is <nil>
-------------------------------
Case: Instance service
Case: Register user
john is &example.User{Email:"john@email.com", Password:"john-123"}
Case: Login
user is &example.User{Email:"john@email.com", Password:"john-123"}
-------------------------------
Case: Instance service
Case: Register user
john is &example.User{Email:"john@email.com", Password:"john-123"}
-------------------------------
Case: Instance service
-------------------------------
--- PASS: TestExample (0.00s)
PASS
错误定位
当出现错误时,Biff会直接定位到出错的行:
Case: Instance service
Case: Register user
john is &example.User{Email:"john@email.com", Password:"john-123"}
Case: Login
Expected: &example.User{Email:"maria@email.com", Password:"1234"}
Obtained: &example.User{Email:"john@email.com", Password:"john-123"}
at biff/example.TestExample.func1.1.2(0xc420096ac0
/home/fulldump/workspace/my-project/src/example/users_test.go:84 +0x12
特性
-
隔离的用例:所有可能的分支都以隔离的方式测试
-
动态BDD:不需要将测试行为翻译成自然语言。Biff会遍历执行堆栈并解析部分测试代码以漂亮地打印断言
-
利用Go函数作用域:避免使用测试助手和辅助方法来维护测试之间的状态,利用语言变量作用域本身编写强大、易写易读的测试
支持的断言
最常用的断言已实现:
AssertEqual
AssertEqualJson
AssertNil
AssertNotNil
AssertNotEqual
AssertInArray
AssertTrue
AssertFalse
贡献
欢迎fork、修改并向master分支提交pull request。如果您愿意,也可以创建新issue或通过电子邮件联系我获取新功能、问题或其他任何内容。
测试
目前还没有测试,但很快就会有了。
示例项目
该项目包含一个示例项目,包含一些简单的业务逻辑和一些Biff测试。
更多关于golang BDD兼容的分支测试框架插件库biff的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang BDD兼容的分支测试框架插件库biff的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang BDD兼容的分支测试框架插件库biff使用指南
biff是一个轻量级的Golang测试框架,它支持行为驱动开发(BDD)风格的分支测试,可以帮助开发者编写更清晰、更具表达力的测试代码。
安装biff
go get github.com/fulldump/biff
基本用法
1. 简单断言
package main
import (
"testing"
"github.com/fulldump/biff"
)
func TestAddition(t *testing.T) {
biff.AssertEqual(2+2, 4)
}
2. BDD风格测试
func TestCalculator(t *testing.T) {
biff.Describe("Calculator", func(a *biff.A) {
a.Describe("Addition", func(b *biff.A) {
b.It("should add two numbers correctly", func(c *biff.A) {
result := 2 + 3
c.AssertEqual(result, 5)
})
})
a.Describe("Subtraction", func(b *biff.A) {
b.It("should subtract two numbers correctly", func(c *biff.A) {
result := 5 - 3
c.AssertEqual(result, 2)
})
})
})
}
3. 表格驱动测试
func TestTableDriven(t *testing.T) {
testCases := []struct {
name string
input int
expected int
}{
{"case 1", 1, 1},
{"case 2", 2, 4},
{"case 3", 3, 9},
}
for _, tc := range testCases {
biff.Test(tc.name, func(a *biff.A) {
result := tc.input * tc.input
a.AssertEqual(result, tc.expected)
})
}
}
高级特性
1. 异步测试
func TestAsync(t *testing.T) {
biff.Describe("Async operations", func(a *biff.A) {
a.It("should handle async calls", func(b *biff.A) {
done := make(chan bool)
go func() {
// 模拟异步操作
time.Sleep(100 * time.Millisecond)
done <- true
}()
b.Await(done, true, "Expected async operation to complete")
})
})
}
2. 测试前后钩子
func TestWithHooks(t *testing.T) {
var db *someDatabase // 假设的数据库连接
biff.Describe("Database tests", func(a *biff.A) {
a.Before(func() {
// 测试前初始化
db = connectToDB()
})
a.After(func() {
// 测试后清理
db.Close()
})
a.It("should query data", func(b *biff.A) {
result, err := db.Query("SELECT * FROM users")
b.AssertNil(err)
b.AssertNotNil(result)
})
})
}
3. 自定义断言
func TestCustomAssertion(t *testing.T) {
biff.Describe("Custom assertions", func(a *biff.A) {
a.It("should validate email format", func(b *biff.A) {
email := "test@example.com"
b.Assert("email should contain @", strings.Contains(email, "@"))
})
})
}
最佳实践
- 描述性命名:使用清晰的描述来说明测试的目的
- 分层结构:利用Describe/It嵌套来组织测试
- 单一职责:每个测试用例只验证一件事
- 表格驱动:对相似测试用例使用表格驱动测试
- 清理资源:使用After/Before钩子管理测试资源
与其他测试框架比较
biff相比标准库的testing包和Ginkgo等BDD框架有以下特点:
- 更轻量级
- 更简单的API
- 内置断言库
- 支持BDD风格但不强制
- 良好的错误报告
总结
biff为Golang提供了一个简单而强大的BDD兼容测试解决方案。它的分层结构和丰富的断言方法使得测试代码更易读、更易维护。通过结合表格驱动测试和异步支持,biff可以满足从简单单元测试到复杂集成测试的各种需求。
希望这个指南能帮助你开始在Golang项目中使用biff进行测试!