TDD golang实践上的部分个人经验谈

TDD

在我看来,使用TDD的一个好处是避免在程序中加入无关的代码。参考一个TDD的定义和TDD的开发feature的流程如下:

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
    https://www.ibm.com/garage/method/practices/code/practice_test_driven_development
    因此也就意味着当我们使用TDD的方式进行开发的时候,我们要首先将功能表述为代码的行为或者测试案例,然后将测试案例落实。此时我们的代码是无法通过测试的(红)。然后我们只需要写必要的代码使得测试通过(绿)。
    从而我们保证了:
  • 所编写的测试案例是最小的
  • 所编写的代码是最小的
  • 所有功能是通过的

测试的角度

我们接下来参考一个计算器实现来说举例一下。

范围 处理方式
接口 unit test
模拟使用 binary test
集成 integration test

Unit Test

对于指定功能如sum(a,b) 我们可以在接口层面进行测试。

test_sum
1,1,2, true
1,2,3, true
2,3,4, false // 错误/异常捕捉

如果可以,尽量包含错误/异常捕捉。

Binary Test 与 Mock

在这个层面,考虑用户如何使用我们的程序,比如

$./calculator sum 1 2
3

因此测试的结构为:

before() {
    
    
 compile() // binary
}

test_sum(){
    
    
// go_exec.binary.arg1,arg2,arg3
}

after() {
    
    
 cleanup()
}

Integration Test 与 CI

这时候我们考虑到需求变更,需要一个什么交互方式。比如把乘法计算放在服务器上跑,从而计费(每算一次收费xxx)
因此测试的结构为:

before() {
    
    
 start_server() //set up server with a specific version
 compile() // binary
}

test_sum(){
    
    
// go_exec.binary.arg1,arg2,arg3
}

after() {
    
    
 cleanup()
}

但是我们又不是很想把服务器安装设置的过程放在代码中,因此可以考虑通过ci环境来满足这部分的测试需求,逻辑上(伪代码)如下

before() {
    
    
if mock {
    
    
 compile_mock() //set up server with a specific version
 start_mock()
}
 compile() // binary
}

test_sum(){
    
    
// go_exec.binary.arg1,arg2,arg3
}

after() {
    
    
 cleanup()
}

技巧:我们可以把测试代码中目标server的地址写为127.0.0.1:xxx这时,无论是在继承测试环境,还是在mock环境下测试。都可以指向这个地址进行通讯,而mock只在mock过程中使用。从而实现测试代码复用。

参考链接
https://www.ibm.com/garage/method/practices/code/practice_test_driven_development
http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd

猜你喜欢

转载自blog.csdn.net/oe1019/article/details/124066550
TDD