-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,282 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,3 +22,6 @@ _testmain.go | |
*.exe | ||
*.test | ||
*.prof | ||
|
||
# vim | ||
*.swp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
language: go | ||
go: | ||
- tip | ||
- 1.4 | ||
- 1.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
// Copyright 2014 by caixw, All rights reserved. | ||
// Use of this source code is governed by a MIT | ||
// license that can be found in the LICENSE file. | ||
|
||
package assert | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path" | ||
"runtime" | ||
"strconv" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
// 获取某个pc寄存器中的函数名,并去掉函数名之前的路径信息。 | ||
func funcName(pc uintptr) string { | ||
if pc == 0 { | ||
return "<无法获取函数信息>" | ||
} | ||
|
||
name := runtime.FuncForPC(pc).Name() | ||
arr := strings.Split(name, "/") | ||
return arr[len(arr)-1] | ||
} | ||
|
||
// 获取调用者的信息。 | ||
// | ||
// 输出错误信息在*_test.go中的位置,方便调试时定位错误位置。 | ||
// 若测试包中的函数是嵌套调用的,则输出内容可能不正确。 | ||
func getCallerInfo() string { | ||
for i := 0; ; i++ { | ||
pc, file, line, ok := runtime.Caller(i) | ||
if !ok { | ||
return "<无法获取调用者信息>" | ||
} | ||
|
||
basename := path.Base(file) | ||
|
||
// 定位以_test.go结尾的文件,认定为起始调用的测试包。 | ||
// 8 == len("_test.go") | ||
l := len(basename) | ||
if l < 8 || (basename[l-8:l] != "_test.go") { | ||
continue | ||
} | ||
|
||
return " @ " + funcName(pc) + "(" + basename + ":" + strconv.Itoa(line) + ")" | ||
} | ||
|
||
return "<无法获取调用者信息>" | ||
} | ||
|
||
// 格式化错误提示信息。 | ||
// | ||
// msg1中的所有参数将依次被传递给fmt.Sprintf()函数, | ||
// 所以msg1[0]必须可以转换成string(如:string, []byte, []rune, fmt.Stringer) | ||
// | ||
// msg2参数格式与msg1完全相同,在msg1为空的情况下,会使用msg2的内容, | ||
// 否则msg2不会启作用。 | ||
func formatMessage(msg1 []interface{}, msg2 []interface{}) string { | ||
if len(msg1) == 0 { | ||
msg1 = msg2 | ||
} | ||
|
||
if len(msg1) == 0 { | ||
return "<未提供任何错误信息>" | ||
} | ||
|
||
format := "" | ||
switch v := msg1[0].(type) { | ||
case []byte: | ||
format = string(v) | ||
case []rune: | ||
format = string(v) | ||
case string: | ||
format = v | ||
case fmt.Stringer: | ||
format = v.String() | ||
default: | ||
return "<无法正确转换错误提示信息>" | ||
} | ||
|
||
return fmt.Sprintf(format, msg1[1:]...) | ||
} | ||
|
||
// 当expr条件不成立时,输出错误信息。 | ||
// | ||
// expr 返回结果值为bool类型的表达式; | ||
// msg1,msg2输出的错误信息,之所以提供两组信息,是方便在用户没有提供的情况下, | ||
// 可以使用系统内部提供的信息,优先使用msg1中的信息,若不存在,则使用msg2的内容。 | ||
func assert(t *testing.T, expr bool, msg1 []interface{}, msg2 []interface{}) { | ||
if !expr { | ||
t.Error(formatMessage(msg1, msg2) + getCallerInfo()) | ||
} | ||
} | ||
|
||
// 断言表达式expr为true,否则输出错误信息。 | ||
// | ||
// args对应fmt.Printf()函数中的参数,其中args[0]对应第一个参数format,依次类推, | ||
// 具体可参数getCallerInfo()函数的介绍。 | ||
// 其它断言函数的args参数,功能与此相同。 | ||
func True(t *testing.T, expr bool, args ...interface{}) { | ||
assert(t, expr, args, []interface{}{"True失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言表达式expr为false,否则输出错误信息 | ||
func False(t *testing.T, expr bool, args ...interface{}) { | ||
assert(t, !expr, args, []interface{}{"False失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言表达式expr为nil,否则输出错误信息 | ||
func Nil(t *testing.T, expr interface{}, args ...interface{}) { | ||
assert(t, IsNil(expr), args, []interface{}{"Nil失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言表达式expr为非nil值,否则输出错误信息 | ||
func NotNil(t *testing.T, expr interface{}, args ...interface{}) { | ||
assert(t, !IsNil(expr), args, []interface{}{"NotNil失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言v1与v2两个值相等,否则输出错误信息 | ||
func Equal(t *testing.T, v1, v2 interface{}, args ...interface{}) { | ||
assert(t, IsEqual(v1, v2), args, []interface{}{"Equal失败,实际值为v1=[%T:%v];v2=[%T:%v]", v1, v1, v2, v2}) | ||
} | ||
|
||
// 断言v1与v2两个值不相等,否则输出错误信息 | ||
func NotEqual(t *testing.T, v1, v2 interface{}, args ...interface{}) { | ||
assert(t, !IsEqual(v1, v2), args, []interface{}{"NotEqual失败,实际值为v1=[%T:%v];v2=[%T:%v]", v1, v1, v2, v2}) | ||
} | ||
|
||
// 断言expr的值为空(nil,"",0,false),否则输出错误信息 | ||
func Empty(t *testing.T, expr interface{}, args ...interface{}) { | ||
assert(t, IsEmpty(expr), args, []interface{}{"Empty失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言expr的值为非空(除nil,"",0,false之外),否则输出错误信息 | ||
func NotEmpty(t *testing.T, expr interface{}, args ...interface{}) { | ||
assert(t, !IsEmpty(expr), args, []interface{}{"NotEmpty失败,实际值为[%T:%v]", expr, expr}) | ||
} | ||
|
||
// 断言有错误发生,否则输出错误信息。 | ||
// 传递未初始化的error值(var err error = nil),将断言失败 | ||
func Error(t *testing.T, expr interface{}, args ...interface{}) { | ||
if IsNil(expr) { // 空值,必定没有错误 | ||
assert(t, false, args, []interface{}{"Error失败,实际类型为[%T]", expr}) | ||
} else { | ||
_, ok := expr.(error) | ||
assert(t, ok, args, []interface{}{"Error失败,实际类型为[%T]", expr}) | ||
} | ||
} | ||
|
||
// 断言没有错误发生,否则输出错误信息 | ||
func NotError(t *testing.T, expr interface{}, args ...interface{}) { | ||
if IsNil(expr) { // 空值必定没有错误 | ||
assert(t, true, args, []interface{}{"NotError失败,实际类型为[%T]", expr}) | ||
} else { | ||
err, ok := expr.(error) | ||
assert(t, !ok, args, []interface{}{"NotError失败,错误信息为[%v]", err}) | ||
} | ||
} | ||
|
||
// 断言文件存在,否则输出错误信息 | ||
func FileExists(t *testing.T, path string, args ...interface{}) { | ||
_, err := os.Stat(path) | ||
|
||
if err != nil && !os.IsExist(err) { | ||
assert(t, false, args, []interface{}{"FileExists发生以下错误:%v", err.Error()}) | ||
} | ||
} | ||
|
||
// 断言文件不存在,否则输出错误信息 | ||
func FileNotExists(t *testing.T, path string, args ...interface{}) { | ||
_, err := os.Stat(path) | ||
assert(t, os.IsNotExist(err), args, []interface{}{"FileExists发生以下错误:%v", err.Error()}) | ||
} | ||
|
||
// 断言函数会发生panic,否则输出错误信息。 | ||
func Panic(t *testing.T, fn func(), args ...interface{}) { | ||
has, _ := HasPanic(fn) | ||
assert(t, has, args, []interface{}{"并未发生panic"}) | ||
} | ||
|
||
// 断言函数会发生panic,否则输出错误信息。 | ||
func NotPanic(t *testing.T, fn func(), args ...interface{}) { | ||
has, msg := HasPanic(fn) | ||
assert(t, !has, args, []interface{}{"发生了panic,其信息为[%]", msg}) | ||
} | ||
|
||
// 断言container包含item的或是包含item中的所有项 | ||
// 具体函数说明可参考IsContains() | ||
func Contains(t *testing.T, container, item interface{}, args ...interface{}) { | ||
assert(t, IsContains(container, item), args, | ||
[]interface{}{"container:[%v]并未包含item[%v]", container, item}) | ||
} | ||
|
||
// 断言container不包含item的或是不包含item中的所有项 | ||
func NotContains(t *testing.T, container, item interface{}, args ...interface{}) { | ||
assert(t, !IsContains(container, item), args, | ||
[]interface{}{"container:[%v]包含item[%v]", container, item}) | ||
} | ||
|
||
// 判断两个字符串相等。 | ||
// | ||
// StringEqual()与Equal()的不同之处在于: | ||
// StringEqual()可以以相对宽松的条件来比较字符串是否相等, | ||
// 比如忽略大小写;忽略多余的空格等,比较方式由style参数指定。 | ||
// 若style值指定为StyleStrit,则和Equal()完全相等。 | ||
func StringEqual(t *testing.T, s1, s2 string, style int, args ...interface{}) { | ||
assert(t, StringIsEqual(s1, s2, style), args, | ||
[]interface{}{"在[%v]比较方式中s1[%v] != s2[%v]", styleString(style), s1, s2}) | ||
} | ||
|
||
// 判断两个字符串不相等。 | ||
func StringNotEqual(t *testing.T, s1, s2 string, style int, args ...interface{}) { | ||
assert(t, !StringIsEqual(s1, s2, style), args, | ||
[]interface{}{"在[%v]比较方式中s1[%v] == s2[%v]", styleString(style), s1, s2}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// Copyright 2014 by caixw, All rights reserved. | ||
// Use of this source code is governed by a MIT | ||
// license that can be found in the LICENSE file. | ||
|
||
package assert | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
) | ||
|
||
func TestGetCallerInfo(t *testing.T) { | ||
str := getCallerInfo() | ||
if len(str) == 0 { | ||
t.Error("getCallerInfo()无法正确返回信息") | ||
} else { | ||
t.Logf("getCallerInfo()返回的内容为:[%v]", str) | ||
} | ||
} | ||
|
||
func TestFormatMsg(t *testing.T) { | ||
msg1 := []interface{}{} | ||
msg2 := []interface{}{[]rune("msg:%v"), 2} | ||
msg3 := []interface{}{"msg:%v", 3} | ||
|
||
str := formatMessage(msg1, msg2) | ||
if str != "msg:2" { | ||
t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str) | ||
} | ||
|
||
str = formatMessage(nil, msg2) | ||
if str != "msg:2" { | ||
t.Errorf("formatMessage(msg1,msg2)返回信息错误:[%v]", str) | ||
} | ||
|
||
str = formatMessage(msg2, msg3) | ||
if str != "msg:2" { | ||
t.Errorf("formatMessage(msg2,msg3)返回信息错误:[%v]", str) | ||
} | ||
} | ||
|
||
func TestTrue(t *testing.T) { | ||
True(t, true) | ||
True(t, 1 == 1, "True(1==1) falid") | ||
} | ||
|
||
func TestFalse(t *testing.T) { | ||
False(t, false, "False falid") | ||
False(t, 1 == 2, "False(1==2) falid") | ||
} | ||
|
||
func TestNil(t *testing.T) { | ||
Nil(t, nil, "Nil falid") | ||
|
||
var v interface{} | ||
Nil(t, v, "Nil(v) falid") | ||
} | ||
|
||
func TestNotNil(t *testing.T) { | ||
NotNil(t, 5, "NotNil falid") | ||
|
||
var v interface{} = 5 | ||
NotNil(t, v, "NotNil falid") | ||
} | ||
|
||
func TestEqual(t *testing.T) { | ||
Equal(t, 5, 5, "Equal(5,5) falid") | ||
|
||
var v1, v2 interface{} | ||
v1 = 5 | ||
v2 = 5 | ||
|
||
Equal(t, 5, v1) | ||
Equal(t, v1, v2, "Equal(v1,v2) falid") | ||
Equal(t, int8(126), 126) | ||
Equal(t, int64(126), int8(126)) | ||
Equal(t, uint(7), int(7)) | ||
} | ||
|
||
func TestNotEqual(t *testing.T) { | ||
NotEqual(t, 5, 6, "NotEqual(5,6) falid") | ||
|
||
var v1, v2 interface{} = 5, 6 | ||
|
||
NotEqual(t, 5, v2, "NotEqual(5,v2) falid") | ||
NotEqual(t, v1, v2, "NotEqual(v1,v2) falid") | ||
NotEqual(t, 128, int8(127)) | ||
} | ||
|
||
func TestEmpty(t *testing.T) { | ||
Empty(t, 0, "Empty(0) falid") | ||
Empty(t, "", "Empty(``) falid") | ||
Empty(t, false, "Empty(false) falid") | ||
Empty(t, []string{}, "Empty(slice{}) falid") | ||
Empty(t, []int{}, "Empty(slice{}) falid") | ||
} | ||
|
||
func TestNotEmpty(t *testing.T) { | ||
NotEmpty(t, 1, "NotEmpty(1) falid") | ||
NotEmpty(t, true, "NotEmpty(true) falid") | ||
NotEmpty(t, []string{"ab"}, "NotEmpty(slice(abc)) falid") | ||
} | ||
|
||
func TestError(t *testing.T) { | ||
err := errors.New("test") | ||
Error(t, err, "Error(err) falid") | ||
} | ||
|
||
func TestNotError(t *testing.T) { | ||
NotError(t, "123", "NotError(123) falid") | ||
|
||
var err1 error = nil | ||
NotError(t, err1, "var err1 error falid") | ||
} | ||
|
||
func TestFileExists(t *testing.T) { | ||
FileExists(t, "./assert.go", "FileExists() falid") | ||
} | ||
|
||
func TestFileNotExists(t *testing.T) { | ||
FileNotExists(t, "c:/win", "FileNotExists() falid") | ||
} | ||
|
||
func TestPanic(t *testing.T) { | ||
f1 := func() { | ||
panic("panic") | ||
} | ||
|
||
Panic(t, f1) | ||
} | ||
|
||
func TestNotPanic(t *testing.T) { | ||
f1 := func() { | ||
} | ||
|
||
NotPanic(t, f1) | ||
} | ||
|
||
func TestContains(t *testing.T) { | ||
Contains(t, []int{1, 2, 3}, []int8{1, 2}) | ||
} | ||
|
||
func TestNotContains(t *testing.T) { | ||
NotContains(t, []int{1, 2, 3}, []int8{1, 3}) | ||
} | ||
|
||
func TestStringEqual(t *testing.T) { | ||
StringEqual(t, "abc", "aBc", StyleCase) | ||
} | ||
|
||
func TestStringNotEqual(t *testing.T) { | ||
StringNotEqual(t, "abc", "aBc", StyleStrit) | ||
} |
Oops, something went wrong.