From d89210dc3494631c7096634cdef9887f00059d1f Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 30 Jun 2013 14:13:32 +0200 Subject: [PATCH 01/26] New assertions and documentation New README.md Added assertmysql and its documentation --- README.md | 152 ++++++++++++++---- assert.go | 76 --------- assert/assert.go | 264 +++++++++++++++++++++++++++++++ assert/assert_test.go | 42 +++++ assert_test.go | 15 -- assertmysql/assertmysql.go | 171 ++++++++++++++++++++ assertmysql/assertmysql_test.go | 18 +++ example/point.go | 5 - example/point_test.go | 13 -- examples/assert_examples.go | 9 ++ examples/assert_examples_test.go | 29 ++++ 11 files changed, 658 insertions(+), 136 deletions(-) delete mode 100644 assert.go create mode 100644 assert/assert.go create mode 100644 assert/assert_test.go delete mode 100644 assert_test.go create mode 100644 assertmysql/assertmysql.go create mode 100644 assertmysql/assertmysql_test.go delete mode 100644 example/point.go delete mode 100644 example/point_test.go create mode 100644 examples/assert_examples.go create mode 100644 examples/assert_examples_test.go diff --git a/README.md b/README.md index 8b6b6fc..6c3f642 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,143 @@ -# Assert (c) Blake Mizerany and Keith Rarick -- MIT LICENCE - ## Assertions for Go tests -## Install +First of all this repository is a fork of http://github.com/bmizerany/assert that adds some new assertions and +more documentation. + +## Repository contains two packages: + +* **assert** - collection of assertion functions. +* **assertmysql** - collection of assertion functions to test programs using *github.com/ziutek/mymysql/mysql* mysql client. + +If you don't use *github.com/ziutek/mymysql/mysql* in your program you can still use just **assert** package. + +## Assertion functions + +* **assert.Assert** - internal function but exported so it can be used in other packages (like *assertmysql*). +* **assert.T**, **assert.Tf**, **assert.Tn**, **assert.Tnf** - helpers allowing you to write your own assertions. +* **assert.Equal**, **assert.Equalf** - asserts equality. +* **assert.NotEqual**, **NotEqualf** - asserts no equality. +* **assert.Panic** - asserts function is panicking. +* **assert.Error** - asserts error. +* **assert.NotError** - asserts no error. +* **assert.ErrorMsgContains** - asserts error and error message contains specific string. +* **assert.Nil** - asserts nil. +* **assert.NotNil** - asserts not nil. + +## MySQL assertions + +* **assertmysql.Error** - asserts MySQL error. +* **assertmysql.NotError** - asserts error is not MySQL error. +* **assertmysql.ErrorCode** - asserts error is MySQL error and has specific code. +* **assertmysql.RowExists** - asserts row exists in a table. +* **assertmysql.TableExists** - asserts table exists in database. +* **assertmysql.TableCount** - asserts database has x tables. +* **assertmysql.TableNotEmpty** - asserts table is not empty (has at least one row). - $ go get github.com/bmizerany/assert +## MySQL helper functions -## Use +* **assertmysql.GetMySQLError** - returns an error and returns *mysql.Error. +* **assertmysql.GetTableNames** - returns an array of database table names. +* **assertmysql.DropTable** - drops table from database. +* **assertmysql.DropAllTables** - drops all tables from database. + +## Example usage **point.go** - package point +```go +package point - type Point struct { - x, y int - } +type Point struct { + x, y int +} +``` **point_test.go** +```go +package point + +import ( + "testing" + "github.com/rzajac/assert/assert" +) - package point +func TestAsserts(t *testing.T) { + p1 := Point{1, 1} + p2 := Point{2, 1} - import ( - "testing" - "github.com/bmizerany/assert" - ) + assert.Equal(t, p1, p2) +} +``` +**output** - func TestAsserts(t *testing.T) { - p1 := Point{1, 1} - p2 := Point{2, 1} +``` +$ go test + --- FAIL: TestAsserts (0.00 seconds) + assert.go:15: /Users/flavio.barbosa/dev/stewie/src/point_test.go:12 + assert.go:24: ! X: 1 != 2 + FAIL +``` - assert.Equal(t, p1, p2) - } +## Documentation -**output** - $ go test - --- FAIL: TestAsserts (0.00 seconds) - assert.go:15: /Users/flavio.barbosa/dev/stewie/src/point_test.go:12 - assert.go:24: ! X: 1 != 2 - FAIL +* http://godoc.org/github.com/rzajac/assert/assert +* http://godoc.org/github.com/rzajac/assert/assertmysql + +## Installation + +To install assertions run: + + $ go get github.com/rzajac/assert + +## Import + +```go +package my_package + +import ( + "github.com/rzajac/assert/assert" + "github.com/rzajac/assert/assertmysql" +) +``` + +This imports both packages but you can use only one of them. + +## Setup MySQL assertions package + +**mydb_test.go** + +```go +package my_package + +import ( + "github.com/rzajac/assert/assert" + "github.com/rzajac/assert/assertmysql" + "testing" +) + +func init() { + assertmysql.InitMySqlAssertions("tcp", "", "localhost:3306", "test_user", "test_user_password", "test_database") +} + +func Test_createMasterTable(t *testing.T) { + dropAllSqlTables(t) + err := createMasterTable() + + assert.NotError(t, err) + assertmysql.TableExists(t, "master_table_name") + assertmysql.TableCount(t, 1) +} +``` + +**You need only one *init* function per package.** + +## More examples + +Go to https://github.com/rzajac/assert/blob/master/examples/assert_examples_test.go or look +at the code in **assert/assert.go**. The functions are very wall documented. -## Docs +## License - http://github.com/bmizerany/assert +Released under the MIT License. +Assert (c) Blake Mizerany, Keith Rarick and Rafal Zajac diff --git a/assert.go b/assert.go deleted file mode 100644 index 7409f98..0000000 --- a/assert.go +++ /dev/null @@ -1,76 +0,0 @@ -package assert -// Testing helpers for doozer. - -import ( - "github.com/kr/pretty" - "reflect" - "testing" - "runtime" - "fmt" -) - -func assert(t *testing.T, result bool, f func(), cd int) { - if !result { - _, file, line, _ := runtime.Caller(cd + 1) - t.Errorf("%s:%d", file, line) - f() - t.FailNow() - } -} - -func equal(t *testing.T, exp, got interface{}, cd int, args ...interface{}) { - fn := func() { - for _, desc := range pretty.Diff(exp, got) { - t.Error("!", desc) - } - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) - } - } - result := reflect.DeepEqual(exp, got) - assert(t, result, fn, cd+1) -} - -func tt(t *testing.T, result bool, cd int, args ...interface{}) { - fn := func() { - t.Errorf("! Failure") - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) - } - } - assert(t, result, fn, cd+1) -} - -func T(t *testing.T, result bool, args ...interface{}) { - tt(t, result, 1, args...) -} - -func Tf(t *testing.T, result bool, format string, args ...interface{}) { - tt(t, result, 1, fmt.Sprintf(format, args...)) -} - -func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { - equal(t, exp, got, 1, args...) -} - -func Equalf(t *testing.T, exp, got interface{}, format string, args ...interface{}) { - equal(t, exp, got, 1, fmt.Sprintf(format, args...)) -} - -func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { - fn := func() { - t.Errorf("! Unexpected: <%#v>", exp) - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) - } - } - result := !reflect.DeepEqual(exp, got) - assert(t, result, fn, 1) -} - -func Panic(t *testing.T, err interface{}, fn func()) { - defer func() { - equal(t, err, recover(), 3) - }() - fn() -} diff --git a/assert/assert.go b/assert/assert.go new file mode 100644 index 0000000..cb66d7d --- /dev/null +++ b/assert/assert.go @@ -0,0 +1,264 @@ +// Assertions for Go tests +// +// Assert (c) Blake Mizerany, Keith Rarick and Rafal Zajac +// http://github.com/rzajac/assert +// +// Licensed under the MIT license + +// Package provides assertions for testing +package assert + +import ( + "fmt" + "github.com/rzajac/pretty" + "reflect" + "runtime" + "strings" + "testing" +) + +// T asserts result is true. +func T(t *testing.T, result bool, args ...interface{}) { + tt(t, result, 1, args...) +} + +// T asserts result is true and allows you to pass format string +// and arguments the same way you do for fmt.Sprintf(). +func Tf(t *testing.T, result bool, format string, args ...interface{}) { + tt(t, result, 1, fmt.Sprintf(format, args...)) +} + +// Equal asserts equality. The exp and got can be of any type. +// +// Examples: +// +// assert.Equal(m1, m2) +// assert.Equal(m1, m2, "Some comment about the test") +// assert.Equal(m1, m2, "Some comment about the test", "Other comment") +// +func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { + equal(t, exp, got, 1, args...) +} + +// Equalf works the same way as Equal() but you can pass format string +// and arguments the same way you do for fmt.Sprintf(). +// +// Example: +// +// assert.Equal(m1, m2, "Expected '%s' got '%s'.", m1, m2) +// +// The assertion comments are relay helpful when you do table driven tests. +// See NotError() documentation. +// +func Equalf(t *testing.T, exp, got interface{}, format string, args ...interface{}) { + equal(t, exp, got, 1, fmt.Sprintf(format, args...)) +} + +// NotEqual asserts exp is not equal to got. +func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { + NotEqualn(t, exp, got, 1, args...) +} + +// NotEqualf works the same way as NotEqual() but you can pass format string +// and arguments the same way you do for fmt.Sprintf(). +// +// The assertion comments are relay helpful when you do table driven tests. +// See assert.NotError documentation. +// +func NotEqualf(t *testing.T, exp, got interface{}, format string, args ...interface{}) { + NotEqualfn(t, exp, got, 1, format, args...) +} + +// Panic tests if error passed to panic in panicking function fn equals to err. +func Panic(t *testing.T, err interface{}, fn func()) { + defer func() { + equal(t, err, recover(), 3) + }() + fn() +} + +// Error asserts that err is of type error. +func Error(t *testing.T, err interface{}, args ...interface{}) { + newArgs := []interface{}{"Expected an error."} + newArgs = append(newArgs, args...) + _, ok := err.(error) + tt(t, ok, 1, newArgs...) +} + +// NotError asserts err is not of type error. +// +// Example: +// +// var tests = []struct { +// expectedValue bool +// funcArg string +// }{ +// {false, "hello"}, +// {true, "HELLO"}, +// } +// +// func Test_doWork(t *testing.T) { +// for idx, test := range tests { +// gotValue, err := isUpperCase(test.funcArg) +// assert.NotError(t, err, "idx:", idx) +// assert.Equalf(t, test.expectedValue, gotValue, "Idx:", idx) +// } +// } +// +// The assertion comments are relay helpful when you do table driven tests. +// See https://code.google.com/p/go-wiki/wiki/TableDrivenTests +// +func NotError(t *testing.T, err interface{}, args ...interface{}) { + var e error + fn := func() { + t.Errorf("Did not expect error: %s", e.Error()) + t.Error(args...) + } + e, ok := err.(error) + Assert(t, !ok, fn, 1) +} + +// ErrorMsgContains asserts that err is of type error +// and error message contains specific string. +// +// Example: +// +// func Test_WTF(t *testing.T) { +// err := errors.New("WTF?") +// assert.ErrorMsgContains(t, err, "WTF") +// } +// +func ErrorMsgContains(t *testing.T, err interface{}, contains string, args ...interface{}) { + var ok bool + var e error + var wrongErrorMessage string + + fn := func() { + t.Errorf("Expected an error containing '%s'.", contains) + if wrongErrorMessage != "" { + t.Errorf("But got error: %s", wrongErrorMessage) + } + if len(args) > 0 { + t.Error("!", " -", fmt.Sprint(args...)) + } + } + + e, ok = err.(error) + if ok { + if !strings.Contains(e.Error(), contains) { + wrongErrorMessage = e.Error() + Assert(t, false, fn, 1) + } + } else { + Assert(t, false, fn, 1) + } +} + +// Nil asserts v is nil. +func Nil(t *testing.T, v interface{}, args ...interface{}) { + newArgs := []interface{}{"Expected nil value."} + newArgs = append(newArgs, args...) + result := fmt.Sprintf("%v", v) == "" + tt(t, result, 1, newArgs) +} + +// NotNil asserts v is not nil. +func NotNil(t *testing.T, v interface{}, args ...interface{}) { + newArgs := []interface{}{"Did not expect nil value."} + newArgs = append(newArgs, args...) + result := fmt.Sprintf("%v", v) != "" + tt(t, result, 1, newArgs) +} + +// Considered Internal + +// Assert is internal function but exported because it's used in other test packages. +func Assert(t *testing.T, result bool, f func(), nl int) { + if !result { + _, file, line, _ := runtime.Caller(nl + 1) + t.Errorf("%s:%d", file, line) + f() + t.FailNow() + } +} + +// Tn asserts result is true and allows you to pass nesting level. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func Tn(t *testing.T, result bool, nl int, args ...interface{}) { + tt(t, result, nl+1, args...) +} + +// T asserts result is true and allows you to pass nesting level, format +// string and arguments the same way fmt.Sprintf() does. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func Tnf(t *testing.T, result bool, nl int, format string, args ...interface{}) { + tt(t, result, nl+1, fmt.Sprintf(format, args...)) +} + +// Equaln works the same way as Equal() but allows you to pass nesting level. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func Equaln(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { + equal(t, exp, got, nl+1, args...) +} + +// Equalfn works the same way as Equalf() but allows you to pass nesting level, format +// string and arguments the same way fmt.Sprintf() does. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func Equalfn(t *testing.T, exp, got interface{}, nl int, format string, args ...interface{}) { + equal(t, exp, got, nl+1, fmt.Sprintf(format, args...)) +} + +// NotEqualn works the same way as NotEqual() but allows you to pass nesting level. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func NotEqualn(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { + fn := func() { + t.Errorf("! Unexpected: <%#v>", exp) + if len(args) > 0 { + t.Error("!", " -", fmt.Sprint(args...)) + } + } + result := !reflect.DeepEqual(exp, got) + Assert(t, result, fn, nl+1) +} + +// NotEqualfn works the same way as NotEqualf() but allows you to pass nesting level. +// Passing the nesting level is helpful when you write your own assertions and you want +// error messages to show correct line number and file where it failed. +func NotEqualfn(t *testing.T, exp, got interface{}, nl int, format string, args ...interface{}) { + fn := func() { + t.Errorf("! Unexpected: <%#v>", exp) + if len(args) > 0 { + t.Error("!", " -", fmt.Sprintf(format, args...)) + } + } + result := !reflect.DeepEqual(exp, got) + Assert(t, result, fn, nl+1) +} + +func equal(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { + fn := func() { + for _, desc := range pretty.Diff(exp, got) { + t.Error("!", desc) + } + if len(args) > 0 { + t.Error("!", " -", fmt.Sprint(args...)) + } + } + result := reflect.DeepEqual(exp, got) + Assert(t, result, fn, nl+1) +} + +func tt(t *testing.T, result bool, nl int, args ...interface{}) { + fn := func() { + t.Errorf("! Failure") + if len(args) > 0 { + t.Error("!", " -", fmt.Sprint(args...)) + } + } + Assert(t, result, fn, nl+1) +} diff --git a/assert/assert_test.go b/assert/assert_test.go new file mode 100644 index 0000000..dbccf1d --- /dev/null +++ b/assert/assert_test.go @@ -0,0 +1,42 @@ +package assert + +import ( + "errors" + "testing" +) + +func Test_LineNumbers(t *testing.T) { + Equal(t, "foo", "foo", "msg!") + // Equal(t, "foo", "bar", "this should blow up") +} + +func Test_NotEqual(t *testing.T) { + NotEqual(t, "foo", "bar", "msg!") + // NotEqual(t, "foo", "foo", "this should blow up") +} + +func Test_Nil(t *testing.T) { + var interf interface{} + Nil(t, nil) + Nil(t, interf) +} + +func Test_NotNil(t *testing.T) { + NotNil(t, 1) + NotNil(t, "string") +} + +func Test_Error(t *testing.T) { + err := errors.New("Test error.") + Error(t, err) +} + +func Test_NotError(t *testing.T) { + notError := "string" + NotError(t, notError) +} + +func Test_ErrorMsgContains(t *testing.T) { + err := errors.New("Wtf?") + ErrorMsgContains(t, err, "Wtf") +} diff --git a/assert_test.go b/assert_test.go deleted file mode 100644 index 162a590..0000000 --- a/assert_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package assert - -import ( - "testing" -) - -func TestLineNumbers(t *testing.T) { - Equal(t, "foo", "foo", "msg!") - //Equal(t, "foo", "bar", "this should blow up") -} - -func TestNotEqual(t *testing.T) { - NotEqual(t, "foo", "bar", "msg!") - //NotEqual(t, "foo", "foo", "this should blow up") -} diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go new file mode 100644 index 0000000..0e08d71 --- /dev/null +++ b/assertmysql/assertmysql.go @@ -0,0 +1,171 @@ +// Assertions and helper functions for testing applications using MySQL +// +// Assert (c) Rafal Zajac +// http://github.com/rzajac/assert +// +// Licensed under the MIT license + +// Assertions and helper functions for testing applications using MySQL +// MySQL driver used: http://github.com/ziutek/mymysql +package assertmysql + +import ( + "fmt" + "github.com/rzajac/assert/assert" + "github.com/ziutek/mymysql/mysql" + _ "github.com/ziutek/mymysql/thrsafe" + "testing" +) + +const ( + DUMMY_MYSQL_ERROR_CODE = 9999 +) + +// The database connection to use. +var dbcon mysql.Conn + +// InitMySqlAssertions initializes assertmysql package. +func InitMySqlAssertions(proto, laddr, raddr, user, passwd, db string) { + dbcon = mysql.New(proto, laddr, raddr, user, passwd, db) + err := dbcon.Connect() + if err != nil { + panic(err) + } +} + +// Error asserts err is MySql error. +func Error(t *testing.T, err error, args ...interface{}) { + fn := func() { + t.Error("Expected MySQL error.") + if len(args) > 0 { + t.Error(fmt.Sprint(args...)) + } + } + _, ok := err.(*mysql.Error) + assert.Assert(t, ok, fn, 1) +} + +// NotError asserts err is not MySql error. +func NotError(t *testing.T, err error, args ...interface{}) { + fn := func() { + t.Error("Did not expect MySQL error.") + if len(args) > 0 { + t.Error(fmt.Sprint(args...)) + } + } + _, ok := err.(*mysql.Error) + assert.Assert(t, !ok, fn, 1) +} + +// ErrorCode asserts err is *mysql.Error and has code. +func ErrorCode(t *testing.T, err error, errorCode uint16) { + merr := GetMySqlErorr(err) + fn := func() { + t.Error("Expected MySQL error but got some other error.") + t.Errorf("Got error: %s", err.Error()) + } + _, ok := err.(*mysql.Error) + assert.Assert(t, ok, fn, 1) + assert.Equalfn(t, errorCode, merr.Code, 1, "Expected error code %d got %d.", errorCode, merr.Code) +} + +// RowExists asserts row exists in a table. +func RowExists(t *testing.T, tableName, pkName, selectValue string) (mysql.Row, mysql.Result) { + row, res, err := dbcon.QueryFirst("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) + if err != nil { + assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) + } + return row, res +} + +// assertTableExists asserts MySQL table exists in the database. +func TableExists(t *testing.T, tableName string) { + var foundTable bool + sqlTables, _ := GetTableNames() + for _, dbTableName := range sqlTables { + if dbTableName == tableName { + foundTable = true + break + } + } + assert.Tnf(t, foundTable, 1, "Table '%s' is not present in the database.", tableName) +} + +// TableCount asserts number of tables in the database. +func TableCount(t *testing.T, expectedCount int) { + sqlTables, _ := GetTableNames() + assert.Equalfn(t, expectedCount, len(sqlTables), 1, "Expected %d tables but got %d.", expectedCount, len(sqlTables)) +} + +// TableRowCount asserts tableName has expectedRowCount rows. +func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { + row, _, err := dbcon.QueryFirst("SELECT count(1) FROM %s", tableName) + if err != nil { + assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) + } + assert.Equalfn(t, row.Int(0), expectedRowCount, 1, "Expected %d rows got %d.", expectedRowCount, row.Int(0)) +} + +// TableNotEmpty asserts tableName is not empty. +func TableNotEmpty(t *testing.T, tableName string) { + row, _, err := dbcon.QueryFirst("SELECT * FROM %s LIMIT 1", tableName) + if err != nil { + assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) + } + assert.NotEqualn(t, row, nil, 1, "Expected table to have data.") +} + +// helper functions + +// GetMySqlErorr helper function casts error to *mysql.Error. +// If err is not *mysql.Error it still returns *mysql.Error but +// with invalid (not used) MySQL error code 9999. +func GetMySqlErorr(err error) *mysql.Error { + var ok bool + var mysqle *mysql.Error + + mysqle, ok = err.(*mysql.Error) + + if !ok { + mysqle = new(mysql.Error) + mysqle.Msg = []byte(err.Error()) + mysqle.Code = DUMMY_MYSQL_ERROR_CODE + } + return mysqle +} + +// GetTableNames gets all MySQL table names. +func GetTableNames() ([]string, error) { + tables := make([]string, 0, 10) + rows, _, err := dbcon.Query("SHOW TABLES") + if err != nil { + return tables, err + } + for _, row := range rows { + tables = append(tables, row.Str(0)) + } + return tables, err +} + +// DropTable drops MySQL table by name. +func DropTable(tableName string) error { + _, _, err := dbcon.Query("DROP TABLE IF EXISTS %s", tableName) + return err +} + +// DropAllTables drops all MySQL tables in selected database. +func DropAllTables() error { + var err error + var tableNames []string + tableNames, err = GetTableNames() + if err != nil { + return err + } + for _, tableName := range tableNames { + err = DropTable(tableName) + if err != nil { + return err + } + } + return err +} diff --git a/assertmysql/assertmysql_test.go b/assertmysql/assertmysql_test.go new file mode 100644 index 0000000..c9a0d90 --- /dev/null +++ b/assertmysql/assertmysql_test.go @@ -0,0 +1,18 @@ +package assertmysql + +import ( + "errors" + "github.com/ziutek/mymysql/mysql" + "testing" +) + +func Test_NotError(t *testing.T) { + err1 := errors.New("Test1") + NotError(t, err1) +} + +func Test_Error(t *testing.T) { + err1 := new(mysql.Error) + err1.Msg = []byte("Test1") + Error(t, err1) +} diff --git a/example/point.go b/example/point.go deleted file mode 100644 index 15789fe..0000000 --- a/example/point.go +++ /dev/null @@ -1,5 +0,0 @@ -package point - -type Point struct { - X, Y int -} diff --git a/example/point_test.go b/example/point_test.go deleted file mode 100644 index 34e791a..0000000 --- a/example/point_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package point - -import ( - "testing" - "assert" -) - -func TestAsserts(t *testing.T) { - p1 := Point{1, 1} - p2 := Point{2, 1} - - assert.Equal(t, p1, p2) -} diff --git a/examples/assert_examples.go b/examples/assert_examples.go new file mode 100644 index 0000000..b68e584 --- /dev/null +++ b/examples/assert_examples.go @@ -0,0 +1,9 @@ +package assert_example + +type Point struct { + X, Y int +} + +func AddNumbers(x, y int) int { + return x + y +} diff --git a/examples/assert_examples_test.go b/examples/assert_examples_test.go new file mode 100644 index 0000000..9195d4b --- /dev/null +++ b/examples/assert_examples_test.go @@ -0,0 +1,29 @@ +package assert_example + +import ( + "github.com/rzajac/assert/assert" + "testing" +) + +func Test_AssertEqual(t *testing.T) { + p1 := Point{1, 1} + p2 := Point{2, 1} + assert.Equal(t, p1, p2) +} + +func Test_AddNumbers(t *testing.T) { + var tests = []struct { + x, y int + expResult int + }{ + {1, 2, 3}, + {0, 0, 0}, + {2, 3, 6}, // Intentional error + } + var gotValue int + + for idx, test := range tests { + gotValue = addNumbers(test.x, test.y) + assert.Equalf(t, test.expResult, gotValue, "For idx: %s", idx) + } +} From 3dfedf250703769c1fd8dcbe8b14018bca5b5614 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Tue, 2 Jul 2013 08:45:43 +0200 Subject: [PATCH 02/26] RowExists returns multiple rows --- assertmysql/assertmysql.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 0e08d71..eba895d 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -70,12 +70,13 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { } // RowExists asserts row exists in a table. -func RowExists(t *testing.T, tableName, pkName, selectValue string) (mysql.Row, mysql.Result) { - row, res, err := dbcon.QueryFirst("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) +func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row, mysql.Result) { + rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) if err != nil { assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) } - return row, res + assert.Tn(t, len(rows) > 0, 1) + return rows, res } // assertTableExists asserts MySQL table exists in the database. From e586fc809147263d070f87b35b80e6effc203c0f Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sat, 6 Jul 2013 21:48:30 +0200 Subject: [PATCH 03/26] Add TruncateTable helper --- assertmysql/assertmysql.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index eba895d..7bf4251 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -154,6 +154,12 @@ func DropTable(tableName string) error { return err } +// TruncateTable truncates MySQL table by name. +func TruncateTable(tableName string) error { + _, _, err := dbcon.Query("TRUNCATE %s", tableName) + return err +} + // DropAllTables drops all MySQL tables in selected database. func DropAllTables() error { var err error From 495e5489e7bf2d587fc2cf34ebaff0de36fb1577 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 7 Jul 2013 15:35:06 +0200 Subject: [PATCH 04/26] Add assertmysql.TruncateTable, assertmysql.GetTableRowCount and update docs --- README.md | 2 ++ assertmysql/assertmysql.go | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6c3f642..2e8db1c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,9 @@ If you don't use *github.com/ziutek/mymysql/mysql* in your program you can still * **assertmysql.GetMySQLError** - returns an error and returns *mysql.Error. * **assertmysql.GetTableNames** - returns an array of database table names. +* **assertmysql.GetTableRowCount** - returns a number of rows in a table. * **assertmysql.DropTable** - drops table from database. +* **assertmysql.TruncateTable** - truncates table. * **assertmysql.DropAllTables** - drops all tables from database. ## Example usage diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 7bf4251..beb918d 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -100,11 +100,11 @@ func TableCount(t *testing.T, expectedCount int) { // TableRowCount asserts tableName has expectedRowCount rows. func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { - row, _, err := dbcon.QueryFirst("SELECT count(1) FROM %s", tableName) + rowCount, err := GetTableRowCount(tableName) if err != nil { assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) } - assert.Equalfn(t, row.Int(0), expectedRowCount, 1, "Expected %d rows got %d.", expectedRowCount, row.Int(0)) + assert.Equalfn(t, rowCount, expectedRowCount, 1, "Expected %d rows got %d.", expectedRowCount, rowCount) } // TableNotEmpty asserts tableName is not empty. @@ -148,6 +148,15 @@ func GetTableNames() ([]string, error) { return tables, err } +// GetTableRowCount returns number of rows in a table. +func GetTableRowCount(tableName string) (int, error) { + row, _, err := dbcon.QueryFirst("SELECT count(1) FROM %s", tableName) + if err != nil { + return 0, err + } + return row.Int(0), err +} + // DropTable drops MySQL table by name. func DropTable(tableName string) error { _, _, err := dbcon.Query("DROP TABLE IF EXISTS %s", tableName) From 92c20f89ba2c96b49701b4d1fff5521b36fd6017 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 10 Jul 2013 21:10:04 +0200 Subject: [PATCH 05/26] Check for nil error --- assertmysql/assertmysql.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index beb918d..b5c8629 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -59,6 +59,12 @@ func NotError(t *testing.T, err error, args ...interface{}) { // ErrorCode asserts err is *mysql.Error and has code. func ErrorCode(t *testing.T, err error, errorCode uint16) { + + if err == nil { + assert.Tn(t, false, 1, "Expected error but got nil.") + return + } + merr := GetMySqlErorr(err) fn := func() { t.Error("Expected MySQL error but got some other error.") From 0677f7065a89f8978f49b4731c2f90096cb1115a Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Tue, 16 Jul 2013 11:44:31 +0200 Subject: [PATCH 06/26] Error reason --- assertmysql/assertmysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index beb918d..d3c2cbe 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -75,7 +75,7 @@ func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row if err != nil { assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) } - assert.Tn(t, len(rows) > 0, 1) + assert.Tn(t, len(rows) > 0, 1, "0 rows returned.") return rows, res } From 9896ed103a684c14d5121ebd21547897e270a189 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Tue, 16 Jul 2013 18:12:34 +0200 Subject: [PATCH 07/26] New asserts wip --- assert/assert.go | 303 +++++++++++++++--------------------------- assert/assert_test.go | 81 +++++++---- 2 files changed, 161 insertions(+), 223 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index cb66d7d..60ddd10 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -17,248 +17,161 @@ import ( "testing" ) -// T asserts result is true. -func T(t *testing.T, result bool, args ...interface{}) { - tt(t, result, 1, args...) -} +const ( + FAIL_FAST = true + FAIL_SLOW = false +) -// T asserts result is true and allows you to pass format string -// and arguments the same way you do for fmt.Sprintf(). -func Tf(t *testing.T, result bool, format string, args ...interface{}) { - tt(t, result, 1, fmt.Sprintf(format, args...)) -} +const ( + NESTING_1 = iota + 1 + NESTING_2 + NESTING_3 + NESTING_4 + NESTING_5 + NESTING_6 + NESTING_7 + NESTING_8 + NESTING_9 +) -// Equal asserts equality. The exp and got can be of any type. -// -// Examples: -// -// assert.Equal(m1, m2) -// assert.Equal(m1, m2, "Some comment about the test") -// assert.Equal(m1, m2, "Some comment about the test", "Other comment") -// -func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { - equal(t, exp, got, 1, args...) +var DEF_FAIL_STRATEGY bool = false + +func SetFailFast(failFast bool) { + DEF_FAIL_STRATEGY = failFast } -// Equalf works the same way as Equal() but you can pass format string -// and arguments the same way you do for fmt.Sprintf(). -// -// Example: -// -// assert.Equal(m1, m2, "Expected '%s' got '%s'.", m1, m2) -// -// The assertion comments are relay helpful when you do table driven tests. -// See NotError() documentation. -// -func Equalf(t *testing.T, exp, got interface{}, format string, args ...interface{}) { - equal(t, exp, got, 1, fmt.Sprintf(format, args...)) +func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { + equal(t, exp, got, args...) } -// NotEqual asserts exp is not equal to got. func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { - NotEqualn(t, exp, got, 1, args...) + nesting, failFast, errorMsg := decodeArgs(args...) + fn := func() { + t.Errorf("! Unexpected: <%#v> == <%#v>", exp, got) + if len(args) > 0 { + t.Error("!", " -", errorMsg) + } + } + result := !reflect.DeepEqual(exp, got) + Assert(t, result, nesting, failFast, fn) } -// NotEqualf works the same way as NotEqual() but you can pass format string -// and arguments the same way you do for fmt.Sprintf(). -// -// The assertion comments are relay helpful when you do table driven tests. -// See assert.NotError documentation. -// -func NotEqualf(t *testing.T, exp, got interface{}, format string, args ...interface{}) { - NotEqualfn(t, exp, got, 1, format, args...) +func T(t *testing.T, result bool, args ...interface{}) { + equal(t, true, result, args...) } -// Panic tests if error passed to panic in panicking function fn equals to err. -func Panic(t *testing.T, err interface{}, fn func()) { - defer func() { - equal(t, err, recover(), 3) - }() - fn() +func F(t *testing.T, result bool, args ...interface{}) { + equal(t, false, result, args...) } // Error asserts that err is of type error. func Error(t *testing.T, err interface{}, args ...interface{}) { - newArgs := []interface{}{"Expected an error."} - newArgs = append(newArgs, args...) _, ok := err.(error) - tt(t, ok, 1, newArgs...) + equal(t, false, ok, args...) } -// NotError asserts err is not of type error. -// -// Example: -// -// var tests = []struct { -// expectedValue bool -// funcArg string -// }{ -// {false, "hello"}, -// {true, "HELLO"}, -// } -// -// func Test_doWork(t *testing.T) { -// for idx, test := range tests { -// gotValue, err := isUpperCase(test.funcArg) -// assert.NotError(t, err, "idx:", idx) -// assert.Equalf(t, test.expectedValue, gotValue, "Idx:", idx) -// } -// } -// -// The assertion comments are relay helpful when you do table driven tests. -// See https://code.google.com/p/go-wiki/wiki/TableDrivenTests -// func NotError(t *testing.T, err interface{}, args ...interface{}) { var e error + nesting, failFast, errorMsg := decodeArgs(args...) fn := func() { t.Errorf("Did not expect error: %s", e.Error()) - t.Error(args...) - } - e, ok := err.(error) - Assert(t, !ok, fn, 1) -} - -// ErrorMsgContains asserts that err is of type error -// and error message contains specific string. -// -// Example: -// -// func Test_WTF(t *testing.T) { -// err := errors.New("WTF?") -// assert.ErrorMsgContains(t, err, "WTF") -// } -// -func ErrorMsgContains(t *testing.T, err interface{}, contains string, args ...interface{}) { - var ok bool - var e error - var wrongErrorMessage string - - fn := func() { - t.Errorf("Expected an error containing '%s'.", contains) - if wrongErrorMessage != "" { - t.Errorf("But got error: %s", wrongErrorMessage) - } - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) } } - - e, ok = err.(error) - if ok { - if !strings.Contains(e.Error(), contains) { - wrongErrorMessage = e.Error() - Assert(t, false, fn, 1) - } - } else { - Assert(t, false, fn, 1) - } -} - -// Nil asserts v is nil. -func Nil(t *testing.T, v interface{}, args ...interface{}) { - newArgs := []interface{}{"Expected nil value."} - newArgs = append(newArgs, args...) - result := fmt.Sprintf("%v", v) == "" - tt(t, result, 1, newArgs) -} - -// NotNil asserts v is not nil. -func NotNil(t *testing.T, v interface{}, args ...interface{}) { - newArgs := []interface{}{"Did not expect nil value."} - newArgs = append(newArgs, args...) - result := fmt.Sprintf("%v", v) != "" - tt(t, result, 1, newArgs) + e, ok := err.(error) + Assert(t, !ok, nesting, failFast, fn) } // Considered Internal // Assert is internal function but exported because it's used in other test packages. -func Assert(t *testing.T, result bool, f func(), nl int) { +func Assert(t *testing.T, result bool, nesting int, failFast bool, f func()) { if !result { - _, file, line, _ := runtime.Caller(nl + 1) + _, file, line, _ := runtime.Caller(nesting + 1) t.Errorf("%s:%d", file, line) f() - t.FailNow() - } -} - -// Tn asserts result is true and allows you to pass nesting level. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func Tn(t *testing.T, result bool, nl int, args ...interface{}) { - tt(t, result, nl+1, args...) -} - -// T asserts result is true and allows you to pass nesting level, format -// string and arguments the same way fmt.Sprintf() does. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func Tnf(t *testing.T, result bool, nl int, format string, args ...interface{}) { - tt(t, result, nl+1, fmt.Sprintf(format, args...)) -} - -// Equaln works the same way as Equal() but allows you to pass nesting level. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func Equaln(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { - equal(t, exp, got, nl+1, args...) -} - -// Equalfn works the same way as Equalf() but allows you to pass nesting level, format -// string and arguments the same way fmt.Sprintf() does. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func Equalfn(t *testing.T, exp, got interface{}, nl int, format string, args ...interface{}) { - equal(t, exp, got, nl+1, fmt.Sprintf(format, args...)) -} - -// NotEqualn works the same way as NotEqual() but allows you to pass nesting level. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func NotEqualn(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { - fn := func() { - t.Errorf("! Unexpected: <%#v>", exp) - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) - } - } - result := !reflect.DeepEqual(exp, got) - Assert(t, result, fn, nl+1) -} - -// NotEqualfn works the same way as NotEqualf() but allows you to pass nesting level. -// Passing the nesting level is helpful when you write your own assertions and you want -// error messages to show correct line number and file where it failed. -func NotEqualfn(t *testing.T, exp, got interface{}, nl int, format string, args ...interface{}) { - fn := func() { - t.Errorf("! Unexpected: <%#v>", exp) - if len(args) > 0 { - t.Error("!", " -", fmt.Sprintf(format, args...)) + if failFast { + t.FailNow() } } - result := !reflect.DeepEqual(exp, got) - Assert(t, result, fn, nl+1) } -func equal(t *testing.T, exp, got interface{}, nl int, args ...interface{}) { +func equal(t *testing.T, exp, got interface{}, args ...interface{}) { + nesting, failFast, errorMsg := decodeArgs(args...) fn := func() { for _, desc := range pretty.Diff(exp, got) { t.Error("!", desc) } - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) } } result := reflect.DeepEqual(exp, got) - Assert(t, result, fn, nl+1) + Assert(t, result, nesting+1, failFast, fn) } -func tt(t *testing.T, result bool, nl int, args ...interface{}) { +func tt(t *testing.T, result bool, nesting int, args ...interface{}) { + nesting, failFast, errorMsg := decodeArgs(args...) fn := func() { t.Errorf("! Failure") - if len(args) > 0 { - t.Error("!", " -", fmt.Sprint(args...)) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) } } - Assert(t, result, fn, nl+1) + Assert(t, result, nesting+1, failFast, fn) +} + +func decodeArgs(args ...interface{}) (int, bool, string) { + var str string + nesting := 1 // Default nesting + failFast := DEF_FAIL_STRATEGY // Fail fast by default + message := "" // Default error message + parsingMsg := false // Set to true when nesting and failFast already parsed + format := "" + msgArgs := make([]interface{}, 0) + + for _, arg := range args { + switch arg.(type) { + case string: + if parsingMsg { + msgArgs = append(msgArgs, arg) + } else { + str, _ = arg.(string) + if isFormat(str) { + format = str + } else { + msgArgs = append(msgArgs, arg) + } + } + parsingMsg = true + break + case int: + if parsingMsg { + msgArgs = append(msgArgs, arg) + } else { + nesting, _ = arg.(int) + } + break + case bool: + if parsingMsg { + msgArgs = append(msgArgs, arg) + } else { + failFast, _ = arg.(bool) + } + break + } + } + + if format != "" { + message = fmt.Sprintf(format, msgArgs...) + } else { + message = fmt.Sprint(msgArgs...) + } + + return nesting, failFast, message +} + +func isFormat(format string) bool { + return strings.Contains(format, "%") } diff --git a/assert/assert_test.go b/assert/assert_test.go index dbccf1d..993ab24 100644 --- a/assert/assert_test.go +++ b/assert/assert_test.go @@ -1,42 +1,67 @@ package assert import ( - "errors" + // "errors" "testing" ) -func Test_LineNumbers(t *testing.T) { - Equal(t, "foo", "foo", "msg!") - // Equal(t, "foo", "bar", "this should blow up") -} +func Test_decodeArgs(t *testing.T) { -func Test_NotEqual(t *testing.T) { - NotEqual(t, "foo", "bar", "msg!") - // NotEqual(t, "foo", "foo", "this should blow up") -} + var tests = []struct { + nesting int + failFast bool + errorMsg string + args []interface{} + }{ + {1, false, "", []interface{}{}}, + {1, false, "", []interface{}{1}}, + {1, false, "", []interface{}{false}}, + {1, true, "", []interface{}{true}}, + {2, false, "", []interface{}{2}}, + {2, false, "", []interface{}{2, false}}, + {2, false, "", []interface{}{false, 2}}, + {1, false, "msg", []interface{}{"msg"}}, + {1, false, "msg a", []interface{}{"msg %s", "a"}}, + {1, false, "msg1", []interface{}{"msg%d", 1}}, + {1, false, "msg", []interface{}{false, "msg"}}, + {3, false, "msg", []interface{}{false, 3, "msg"}}, + {3, false, "msg", []interface{}{3, false, "msg"}}, + {3, true, "msg true", []interface{}{3, true, "msg %t", true}}, + } -func Test_Nil(t *testing.T) { - var interf interface{} - Nil(t, nil) - Nil(t, interf) -} + for idx, test := range tests { + nesting, failFast, errorMsg := decodeArgs(test.args...) -func Test_NotNil(t *testing.T) { - NotNil(t, 1) - NotNil(t, "string") -} + if test.nesting != nesting { + t.Fatalf("Test: %d. Expected nesting %d got %d", idx, test.nesting, nesting) + } -func Test_Error(t *testing.T) { - err := errors.New("Test error.") - Error(t, err) -} + if test.failFast != failFast { + t.Fatalf("Test: %d. Expected failFast %t got %t", idx, test.failFast, failFast) + } -func Test_NotError(t *testing.T) { - notError := "string" - NotError(t, notError) + if test.errorMsg != errorMsg { + t.Fatalf("Test: %d. Expected errorMsg '%s' got '%s'", idx, test.errorMsg, errorMsg) + } + } } -func Test_ErrorMsgContains(t *testing.T) { - err := errors.New("Wtf?") - ErrorMsgContains(t, err, "Wtf") +func Test_isFormat(t *testing.T) { + + var tests = []struct { + exp bool + format string + }{ + {false, "abc"}, + {true, "abc %s"}, + {true, "abc %d"}, + {true, "abc %t"}, + } + + for idx, test := range tests { + got := isFormat(test.format) + if test.exp != got { + t.Fatalf("Expected %t got %t for test %d", test.exp, got, idx) + } + } } From c31b1652132a40e0c0d99bb5b774389ed3da465d Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 17 Jul 2013 10:01:50 +0200 Subject: [PATCH 08/26] Add new assertions --- assert/assert.go | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index 60ddd10..7474b87 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -47,8 +47,9 @@ func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { nesting, failFast, errorMsg := decodeArgs(args...) fn := func() { - t.Errorf("! Unexpected: <%#v> == <%#v>", exp, got) - if len(args) > 0 { + t.Error("! Unexpected, values are equal.") + t.Errorf("! %#v", exp) + if len(errorMsg) > 0 { t.Error("!", " -", errorMsg) } } @@ -70,6 +71,33 @@ func Error(t *testing.T, err interface{}, args ...interface{}) { equal(t, false, ok, args...) } +func ErrorMsgContains(t *testing.T, err interface{}, contains string, args ...interface{}) { + var ok bool + var e error + var wrongErrorMessage string + nesting, failFast, errorMsg := decodeArgs(args...) + + fn := func() { + t.Errorf("Expected an error containing '%s'.", contains) + if wrongErrorMessage != "" { + t.Errorf("But got error: %s", wrongErrorMessage) + } + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } + + e, ok = err.(error) + if ok { + if !strings.Contains(e.Error(), contains) { + wrongErrorMessage = e.Error() + Assert(t, false, nesting, failFast, fn) + } + } else { + Assert(t, false, nesting, failFast, fn) + } +} + func NotError(t *testing.T, err interface{}, args ...interface{}) { var e error nesting, failFast, errorMsg := decodeArgs(args...) @@ -83,6 +111,12 @@ func NotError(t *testing.T, err interface{}, args ...interface{}) { Assert(t, !ok, nesting, failFast, fn) } +func Nil(t *testing.T, v interface{}, args ...interface{}) { + newArgs := []interface{}{"Expected nil value."} + newArgs = append(newArgs, args...) + equal(t, "", fmt.Sprintf("%v", v), newArgs) +} + // Considered Internal // Assert is internal function but exported because it's used in other test packages. From 14b1fc15c4688fade91fc79518356d6ac33fba63 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 17 Jul 2013 15:54:56 +0200 Subject: [PATCH 09/26] New assertions, documentation --- README.md | 177 ++++++++++++++++++++++---------- assert/assert.go | 107 ++++++++++++++++--- assert/assert_test.go | 47 ++++++++- assertmysql/assertmysql.go | 48 ++++----- assertmysql/assertmysql_test.go | 9 ++ 5 files changed, 287 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 2e8db1c..d858efd 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,134 @@ -## Assertions for Go tests +## Simple assertions for Go tests -First of all this repository is a fork of http://github.com/bmizerany/assert that adds some new assertions and -more documentation. +This is a small collection of assertions to make Go tests more concise and readable. ## Repository contains two packages: * **assert** - collection of assertion functions. -* **assertmysql** - collection of assertion functions to test programs using *github.com/ziutek/mymysql/mysql* mysql client. +* **assertmysql** - collection of assertion functions to test programs that are using *github.com/ziutek/mymysql/mysql* mysql client but not only. If you don't use *github.com/ziutek/mymysql/mysql* in your program you can still use just **assert** package. -## Assertion functions +## Assertions -* **assert.Assert** - internal function but exported so it can be used in other packages (like *assertmysql*). -* **assert.T**, **assert.Tf**, **assert.Tn**, **assert.Tnf** - helpers allowing you to write your own assertions. -* **assert.Equal**, **assert.Equalf** - asserts equality. -* **assert.NotEqual**, **NotEqualf** - asserts no equality. -* **assert.Panic** - asserts function is panicking. -* **assert.Error** - asserts error. -* **assert.NotError** - asserts no error. -* **assert.ErrorMsgContains** - asserts error and error message contains specific string. -* **assert.Nil** - asserts nil. -* **assert.NotNil** - asserts not nil. +**assert.Equal** -## MySQL assertions +Asserts parameters are equal. -* **assertmysql.Error** - asserts MySQL error. -* **assertmysql.NotError** - asserts error is not MySQL error. -* **assertmysql.ErrorCode** - asserts error is MySQL error and has specific code. -* **assertmysql.RowExists** - asserts row exists in a table. -* **assertmysql.TableExists** - asserts table exists in database. -* **assertmysql.TableCount** - asserts database has x tables. -* **assertmysql.TableNotEmpty** - asserts table is not empty (has at least one row). +```go +func Test_add(t *testing.T) { + exp := 3 + got := add(1, 3) + + assert.Equal(t, exp, got) + + // Test with optional comment + assert.Equal(t, exp, got, "Add function is broken.") +} +``` -## MySQL helper functions +Parameters **exp** and **got** could be of any type. -* **assertmysql.GetMySQLError** - returns an error and returns *mysql.Error. -* **assertmysql.GetTableNames** - returns an array of database table names. -* **assertmysql.GetTableRowCount** - returns a number of rows in a table. -* **assertmysql.DropTable** - drops table from database. -* **assertmysql.TruncateTable** - truncates table. -* **assertmysql.DropAllTables** - drops all tables from database. +**assert.NotEqual** + +Works the same way as *assert.Equal()* but asserts parameters are not equal. -## Example usage +**assert.Error** -**point.go** +Asserts parameter is an instance of *error*. ```go -package point +func Test_Error(t *testing.T) { + file, err := getFile("/file/path") -type Point struct { - x, y int + assert.Error(err) + + // Test with optional comment + assert.Error(t, err, "Expected file error.") } ``` -**point_test.go** +**assert.NotError** + +Works the same way as *assert.Error()* but asserts parameter is not an *error*. + +**assert.Nil** + +Asserts parameter is nil. ```go -package point +func Test_nil(t *testing.T) { + nilValue := doWork() -import ( - "testing" - "github.com/rzajac/assert/assert" -) + assert.Nil(nilValue) + + // Test with optional comment + assert.Nil(t, nilValue, "Some comment") +} +``` -func TestAsserts(t *testing.T) { - p1 := Point{1, 1} - p2 := Point{2, 1} +**assert.ErrorMsgContains** - assert.Equal(t, p1, p2) +```go +func Test_WTF(t *testing.T) { + err := errors.New("WTF?") + assert.ErrorMsgContains(t, err, "WTF") } ``` -**output** +**assert.NotNil** + +Works the same way as *assert.Nil()* but asserts parameter is not a *nil* value. + +**assert.T** + +Asserts parameter is *true*. + +**assert.F** + +Asserts parameter is *false*. + +## Assertion comments + +You may pass as many comments to assertions as you want. You can even use formating: + +```go +assert.Equal(t, exp, got, "Add function is broken for input (%d,%d).", 1, 2) ``` -$ go test - --- FAIL: TestAsserts (0.00 seconds) - assert.go:15: /Users/flavio.barbosa/dev/stewie/src/point_test.go:12 - assert.go:24: ! X: 1 != 2 - FAIL + +## Failing fast / slow + +By default all the tests are failing slow. Meaning all the assertions in the test case are run. But sometimes you need to fail the test case on first error. This is how you are doing it: + +```go +gotValue, err := doWork() +assert.Equal(t, someTestStruct, gotValue, assert.FAIL_FAST, "Did not expect this.") +assert.Equal(t, "expected", gotValue.field1) ``` +In this case if first assertion fails the the whole test case fails and second assertions will never be run. + +## Example output + + --- FAIL: Test_add (0.00 seconds) + assert.go:199: /golang/src/a/a_test.go:9 + assert.go:212: ! 5 != 4 + --- FAIL: Test_notEqual (0.00 seconds) + assert.go:199: /golang/src/a/a_test.go:14 + assert.go:66: ! Values not supposed to be equal. + assert.go:67: ! 1 + --- FAIL: Test_nil (0.00 seconds) + assert.go:199: /golang/src/a/a_test.go:35 + assert.go:166: Expected nil got "asdads" + assert.go:168: ! - aaaaaaaaaa + assert.go:199: /golang/src/a/a_test.go:36 + assert.go:179: Did not expect nil + assert.go:181: ! - aaaaaaaaaa + +## Writing your own tests helpers or assertions + +See the code for **assertmysql** package which uses the **assert** package to implement its assertions. + ## Documentation * http://godoc.org/github.com/rzajac/assert/assert @@ -105,6 +153,26 @@ import ( This imports both packages but you can use only one of them. +## MySQL assertions + +* **assertmysql.Error** - asserts MySQL error. +* **assertmysql.NotError** - asserts error is not MySQL error. +* **assertmysql.ErrorCode** - asserts error is MySQL error and has specific code. +* **assertmysql.RowExists** - asserts row exists in a table. +* **assertmysql.TableExists** - asserts table exists in database. +* **assertmysql.TableCount** - asserts database has x tables. +* **assertmysql.TableRowCount** - asserts database table has x rows. +* **assertmysql.TableNotEmpty** - asserts table is not empty (has at least one row). + +## MySQL helper functions + +* **assertmysql.GetMySqlError** - returns an error and returns *mysql.Error. +* **assertmysql.GetTableNames** - returns an array of database table names. +* **assertmysql.GetTableRowCount** - returns a number of rows in a table. +* **assertmysql.DropTable** - drops table from database. +* **assertmysql.TruncateTable** - truncates table. +* **assertmysql.DropAllTables** - drops all tables from database. + ## Setup MySQL assertions package **mydb_test.go** @@ -128,17 +196,12 @@ func Test_createMasterTable(t *testing.T) { assert.NotError(t, err) assertmysql.TableExists(t, "master_table_name") - assertmysql.TableCount(t, 1) + assertmysql.TableCount(t, 0) } ``` **You need only one *init* function per package.** -## More examples - -Go to https://github.com/rzajac/assert/blob/master/examples/assert_examples_test.go or look -at the code in **assert/assert.go**. The functions are very wall documented. - ## License Released under the MIT License. diff --git a/assert/assert.go b/assert/assert.go index 7474b87..1ce00a9 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -23,7 +23,8 @@ const ( ) const ( - NESTING_1 = iota + 1 + NESTING_0 = iota + NESTING_1 NESTING_2 NESTING_3 NESTING_4 @@ -36,18 +37,33 @@ const ( var DEF_FAIL_STRATEGY bool = false -func SetFailFast(failFast bool) { +// SetFailStrategy sets test failing strategy. Set it to true for tests to +// fail fast. Failing fast means that test case will run s only till the first +// failing assertion. By default the strategy is to fail slow. +func SetFailStrategy(failFast bool) { DEF_FAIL_STRATEGY = failFast } +// Equal asserts equality. The exp and got can be of any type. +// +// Examples: +// +// assert.Equal(m1, m2) +// assert.Equal(m1, m2, "Some comment about the test") +// assert.Equal(m1, m2, "Some comment %s", myVar.someString) +// assert.Equal(m1, m2, assert.NESTING_1, "Some comment %s", myVar.someString) +// assert.Equal(m1, m2, assert.NESTING_1, assert.FAIL_FAST, "Some comment %s", myVar.someString) +// assert.Equal(m1, m2, assert.FAIL_FAST, assert.NESTING_1, "Some comment %s", myVar.someString) +// func Equal(t *testing.T, exp, got interface{}, args ...interface{}) { equal(t, exp, got, args...) } +// NotEqual asserts exp is not equal to got. It works the same way as assert.Equal() func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { - nesting, failFast, errorMsg := decodeArgs(args...) + nesting, failFast, errorMsg := DecodeArgs(args...) fn := func() { - t.Error("! Unexpected, values are equal.") + t.Error("! Values not supposed to be equal.") t.Errorf("! %#v", exp) if len(errorMsg) > 0 { t.Error("!", " -", errorMsg) @@ -57,10 +73,12 @@ func NotEqual(t *testing.T, exp, got interface{}, args ...interface{}) { Assert(t, result, nesting, failFast, fn) } +// T asserts result is true. func T(t *testing.T, result bool, args ...interface{}) { equal(t, true, result, args...) } +// F asserts result is false. func F(t *testing.T, result bool, args ...interface{}) { equal(t, false, result, args...) } @@ -68,14 +86,24 @@ func F(t *testing.T, result bool, args ...interface{}) { // Error asserts that err is of type error. func Error(t *testing.T, err interface{}, args ...interface{}) { _, ok := err.(error) - equal(t, false, ok, args...) + equal(t, false, !ok, args...) } +// ErrorMsgContains asserts that err is of type error +// and error message contains specific string. +// +// Example: +// +// func Test_WTF(t *testing.T) { +// err := errors.New("WTF?") +// assert.ErrorMsgContains(t, err, "WTF") +// } +// func ErrorMsgContains(t *testing.T, err interface{}, contains string, args ...interface{}) { var ok bool var e error var wrongErrorMessage string - nesting, failFast, errorMsg := decodeArgs(args...) + nesting, failFast, errorMsg := DecodeArgs(args...) fn := func() { t.Errorf("Expected an error containing '%s'.", contains) @@ -98,9 +126,29 @@ func ErrorMsgContains(t *testing.T, err interface{}, contains string, args ...in } } +// NotError asserts err is not of type error. +// +// Example: +// +// var tests = []struct { +// expectedValue bool +// funcArg string +// }{ +// {false, "hello"}, +// {true, "HELLO"}, +// } +// +// func Test_doWork(t *testing.T) { +// for idx, test := range tests { +// gotValue, err := isUpperCase(test.funcArg) +// assert.NotError(t, err, "idx:%d", idx) +// assert.Equal(t, test.expectedValue, gotValue, "Idx:%d", idx) +// } +// } +// func NotError(t *testing.T, err interface{}, args ...interface{}) { var e error - nesting, failFast, errorMsg := decodeArgs(args...) + nesting, failFast, errorMsg := DecodeArgs(args...) fn := func() { t.Errorf("Did not expect error: %s", e.Error()) if len(errorMsg) > 0 { @@ -111,10 +159,30 @@ func NotError(t *testing.T, err interface{}, args ...interface{}) { Assert(t, !ok, nesting, failFast, fn) } +// Nil asserts v is nil. func Nil(t *testing.T, v interface{}, args ...interface{}) { - newArgs := []interface{}{"Expected nil value."} - newArgs = append(newArgs, args...) - equal(t, "", fmt.Sprintf("%v", v), newArgs) + nesting, failFast, errorMsg := DecodeArgs(args...) + fn := func() { + t.Errorf("Expected nil got %#v", v) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } + result := "" == fmt.Sprintf("%v", v) + Assert(t, result, nesting, failFast, fn) +} + +// Nil asserts v is not nil. +func NotNil(t *testing.T, v interface{}, args ...interface{}) { + nesting, failFast, errorMsg := DecodeArgs(args...) + fn := func() { + t.Errorf("Did not expect nil") + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } + result := "" != fmt.Sprintf("%v", v) + Assert(t, result, nesting, failFast, fn) } // Considered Internal @@ -122,8 +190,14 @@ func Nil(t *testing.T, v interface{}, args ...interface{}) { // Assert is internal function but exported because it's used in other test packages. func Assert(t *testing.T, result bool, nesting int, failFast bool, f func()) { if !result { - _, file, line, _ := runtime.Caller(nesting + 1) - t.Errorf("%s:%d", file, line) + nesting++ + for n := 0; n <= nesting; n++ { + _, file, line, _ := runtime.Caller(n) + if strings.Contains(file, "github.com/rzajac/assert/assert") { + continue + } + t.Errorf("%s:%d", file, line) + } f() if failFast { t.FailNow() @@ -132,7 +206,7 @@ func Assert(t *testing.T, result bool, nesting int, failFast bool, f func()) { } func equal(t *testing.T, exp, got interface{}, args ...interface{}) { - nesting, failFast, errorMsg := decodeArgs(args...) + nesting, failFast, errorMsg := DecodeArgs(args...) fn := func() { for _, desc := range pretty.Diff(exp, got) { t.Error("!", desc) @@ -146,7 +220,7 @@ func equal(t *testing.T, exp, got interface{}, args ...interface{}) { } func tt(t *testing.T, result bool, nesting int, args ...interface{}) { - nesting, failFast, errorMsg := decodeArgs(args...) + nesting, failFast, errorMsg := DecodeArgs(args...) fn := func() { t.Errorf("! Failure") if len(errorMsg) > 0 { @@ -156,7 +230,9 @@ func tt(t *testing.T, result bool, nesting int, args ...interface{}) { Assert(t, result, nesting+1, failFast, fn) } -func decodeArgs(args ...interface{}) (int, bool, string) { +// DecodeArgs decodes additional test arguments. +// Returns nesting, fail strategy and error message. +func DecodeArgs(args ...interface{}) (int, bool, string) { var str string nesting := 1 // Default nesting failFast := DEF_FAIL_STRATEGY // Fail fast by default @@ -206,6 +282,7 @@ func decodeArgs(args ...interface{}) (int, bool, string) { return nesting, failFast, message } +// isFormat returns true if sting is format string. func isFormat(format string) bool { return strings.Contains(format, "%") } diff --git a/assert/assert_test.go b/assert/assert_test.go index 993ab24..844fc63 100644 --- a/assert/assert_test.go +++ b/assert/assert_test.go @@ -1,6 +1,7 @@ package assert import ( + "errors" // "errors" "testing" ) @@ -30,7 +31,7 @@ func Test_decodeArgs(t *testing.T) { } for idx, test := range tests { - nesting, failFast, errorMsg := decodeArgs(test.args...) + nesting, failFast, errorMsg := DecodeArgs(test.args...) if test.nesting != nesting { t.Fatalf("Test: %d. Expected nesting %d got %d", idx, test.nesting, nesting) @@ -65,3 +66,47 @@ func Test_isFormat(t *testing.T) { } } } + +func Test_Error(t *testing.T) { + err := errors.New("Test Error") + Error(t, err) +} + +func Test_NotError(t *testing.T) { + NotError(t, 1) + NotError(t, nil) + NotError(t, "aaa") +} + +func Test_ErrorMsgContains(t *testing.T) { + err := errors.New("WTF") + ErrorMsgContains(t, err, "WTF") +} + +func Test_F(t *testing.T) { + F(t, false) +} + +func Test_T(t *testing.T) { + T(t, true) +} + +func Test_Nil(t *testing.T) { + Nil(t, nil) +} + +func Test_NotNil(t *testing.T) { + NotNil(t, 1) +} + +func Test_Equal(t *testing.T) { + Equal(t, 1, 1) + Equal(t, nil, nil) + Equal(t, "aaa", "aaa") +} + +func Test_NotEqual(t *testing.T) { + NotEqual(t, 1, 2) + NotEqual(t, nil, 1) + NotEqual(t, "aaa", 1) +} diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 92a476a..33363f4 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -10,7 +10,6 @@ package assertmysql import ( - "fmt" "github.com/rzajac/assert/assert" "github.com/ziutek/mymysql/mysql" _ "github.com/ziutek/mymysql/thrsafe" @@ -35,35 +34,33 @@ func InitMySqlAssertions(proto, laddr, raddr, user, passwd, db string) { // Error asserts err is MySql error. func Error(t *testing.T, err error, args ...interface{}) { + nesting, failFast, errorMsg := assert.DecodeArgs(args...) fn := func() { t.Error("Expected MySQL error.") - if len(args) > 0 { - t.Error(fmt.Sprint(args...)) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) } } _, ok := err.(*mysql.Error) - assert.Assert(t, ok, fn, 1) + assert.Assert(t, ok, nesting+1, failFast, fn) } // NotError asserts err is not MySql error. func NotError(t *testing.T, err error, args ...interface{}) { + nesting, failFast, errorMsg := assert.DecodeArgs(args...) fn := func() { t.Error("Did not expect MySQL error.") - if len(args) > 0 { - t.Error(fmt.Sprint(args...)) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) } } _, ok := err.(*mysql.Error) - assert.Assert(t, !ok, fn, 1) + assert.Assert(t, !ok, nesting, failFast, fn) } // ErrorCode asserts err is *mysql.Error and has code. func ErrorCode(t *testing.T, err error, errorCode uint16) { - - if err == nil { - assert.Tn(t, false, 1, "Expected error but got nil.") - return - } + assert.Error(t, err, assert.NESTING_2, assert.FAIL_SLOW, "Expected error but got nil.") merr := GetMySqlErorr(err) fn := func() { @@ -71,17 +68,15 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { t.Errorf("Got error: %s", err.Error()) } _, ok := err.(*mysql.Error) - assert.Assert(t, ok, fn, 1) - assert.Equalfn(t, errorCode, merr.Code, 1, "Expected error code %d got %d.", errorCode, merr.Code) + assert.Assert(t, ok, assert.NESTING_2, assert.FAIL_FAST, fn) + assert.Equal(t, errorCode, merr.Code, assert.NESTING_2, "Expected error code %d got %d.", errorCode, merr.Code) } // RowExists asserts row exists in a table. func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row, mysql.Result) { rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) - if err != nil { - assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) - } - assert.Tn(t, len(rows) > 0, 1, "0 rows returned.") + assert.NotError(t, err, assert.NESTING_1, assert.FAIL_FAST) + assert.T(t, len(rows) > 0, assert.NESTING_1, assert.FAIL_FAST, "0 rows returned.") return rows, res } @@ -95,31 +90,28 @@ func TableExists(t *testing.T, tableName string) { break } } - assert.Tnf(t, foundTable, 1, "Table '%s' is not present in the database.", tableName) + assert.T(t, foundTable, assert.NESTING_1, "Table '%s' is not present in the database.", tableName) } // TableCount asserts number of tables in the database. func TableCount(t *testing.T, expectedCount int) { sqlTables, _ := GetTableNames() - assert.Equalfn(t, expectedCount, len(sqlTables), 1, "Expected %d tables but got %d.", expectedCount, len(sqlTables)) + tablesCount := len(sqlTables) + assert.Equal(t, expectedCount, tablesCount, assert.NESTING_1, "Expected %d tables but got %d.", expectedCount, tablesCount) } // TableRowCount asserts tableName has expectedRowCount rows. func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { rowCount, err := GetTableRowCount(tableName) - if err != nil { - assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) - } - assert.Equalfn(t, rowCount, expectedRowCount, 1, "Expected %d rows got %d.", expectedRowCount, rowCount) + assert.NotError(t, err) + assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_1, "Expected %d rows got %d.", expectedRowCount, rowCount) } // TableNotEmpty asserts tableName is not empty. func TableNotEmpty(t *testing.T, tableName string) { row, _, err := dbcon.QueryFirst("SELECT * FROM %s LIMIT 1", tableName) - if err != nil { - assert.Tnf(t, false, 1, "Didn't expect error: %s.", err.Error()) - } - assert.NotEqualn(t, row, nil, 1, "Expected table to have data.") + assert.NotError(t, err) + assert.NotEqual(t, nil, row, assert.NESTING_1, "Expected table to have data.") } // helper functions diff --git a/assertmysql/assertmysql_test.go b/assertmysql/assertmysql_test.go index c9a0d90..5a5dd48 100644 --- a/assertmysql/assertmysql_test.go +++ b/assertmysql/assertmysql_test.go @@ -2,6 +2,7 @@ package assertmysql import ( "errors" + "fmt" "github.com/ziutek/mymysql/mysql" "testing" ) @@ -16,3 +17,11 @@ func Test_Error(t *testing.T) { err1.Msg = []byte("Test1") Error(t, err1) } + +func Test_ErrorCode(t *testing.T) { + err1 := new(mysql.Error) + err1.Code = 123 + err1.Msg = []byte("Test1") + fmt.Println(err1) + ErrorCode(t, err1, 123) +} From d73466e3da75a8fe84834ecabe65cf5275c4fd00 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 17 Jul 2013 16:54:44 +0200 Subject: [PATCH 10/26] Typo --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d858efd..d8873c7 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ assert.Equal(t, someTestStruct, gotValue, assert.FAIL_FAST, "Did not expect this assert.Equal(t, "expected", gotValue.field1) ``` -In this case if first assertion fails the the whole test case fails and second assertions will never be run. +In this case if first assertion fails the the whole test case fails and second assertion will never be run. ## Example output @@ -120,10 +120,10 @@ In this case if first assertion fails the the whole test case fails and second a --- FAIL: Test_nil (0.00 seconds) assert.go:199: /golang/src/a/a_test.go:35 assert.go:166: Expected nil got "asdads" - assert.go:168: ! - aaaaaaaaaa + assert.go:168: ! - Test comment assert.go:199: /golang/src/a/a_test.go:36 assert.go:179: Did not expect nil - assert.go:181: ! - aaaaaaaaaa + assert.go:181: ! - Some other test comment ## Writing your own tests helpers or assertions From 3ac703e4dbd92d959a2bdeac4bbc1585ff8d72e5 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 17 Jul 2013 17:19:14 +0200 Subject: [PATCH 11/26] Correct nesting for assertmysql --- assert/assert.go | 2 +- assertmysql/assertmysql.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index 1ce00a9..2bffe5e 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -194,7 +194,7 @@ func Assert(t *testing.T, result bool, nesting int, failFast bool, f func()) { for n := 0; n <= nesting; n++ { _, file, line, _ := runtime.Caller(n) if strings.Contains(file, "github.com/rzajac/assert/assert") { - continue + // continue } t.Errorf("%s:%d", file, line) } diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 33363f4..e5b8ac0 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -75,8 +75,8 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { // RowExists asserts row exists in a table. func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row, mysql.Result) { rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) - assert.NotError(t, err, assert.NESTING_1, assert.FAIL_FAST) - assert.T(t, len(rows) > 0, assert.NESTING_1, assert.FAIL_FAST, "0 rows returned.") + assert.NotError(t, err, assert.NESTING_2, assert.FAIL_FAST) + assert.T(t, len(rows) > 0, assert.NESTING_2, assert.FAIL_FAST, "0 rows returned.") return rows, res } @@ -90,28 +90,28 @@ func TableExists(t *testing.T, tableName string) { break } } - assert.T(t, foundTable, assert.NESTING_1, "Table '%s' is not present in the database.", tableName) + assert.T(t, foundTable, assert.NESTING_2, "Table '%s' is not present in the database.", tableName) } // TableCount asserts number of tables in the database. func TableCount(t *testing.T, expectedCount int) { sqlTables, _ := GetTableNames() tablesCount := len(sqlTables) - assert.Equal(t, expectedCount, tablesCount, assert.NESTING_1, "Expected %d tables but got %d.", expectedCount, tablesCount) + assert.Equal(t, expectedCount, tablesCount, assert.NESTING_2, "Expected %d tables but got %d.", expectedCount, tablesCount) } // TableRowCount asserts tableName has expectedRowCount rows. func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { rowCount, err := GetTableRowCount(tableName) assert.NotError(t, err) - assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_1, "Expected %d rows got %d.", expectedRowCount, rowCount) + assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_2, "Expected %d rows got %d.", expectedRowCount, rowCount) } // TableNotEmpty asserts tableName is not empty. func TableNotEmpty(t *testing.T, tableName string) { row, _, err := dbcon.QueryFirst("SELECT * FROM %s LIMIT 1", tableName) assert.NotError(t, err) - assert.NotEqual(t, nil, row, assert.NESTING_1, "Expected table to have data.") + assert.NotEqual(t, nil, row, assert.NESTING_2, "Expected table to have data.") } // helper functions From 708e5ba8e201d694e5d94aaa07e5ea811612028b Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 21 Jul 2013 13:33:21 +0200 Subject: [PATCH 12/26] Add FileExist() assertion --- README.md | 22 +++++++++++++++++----- assert/assert.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d8873c7..ae53ac7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Simple assertions for Go tests -This is a small collection of assertions to make Go tests more concise and readable. +This is a small collection of assertions to make Go tests more concise and readable. ## Repository contains two packages: @@ -21,13 +21,13 @@ func Test_add(t *testing.T) { got := add(1, 3) assert.Equal(t, exp, got) - + // Test with optional comment assert.Equal(t, exp, got, "Add function is broken.") } ``` -Parameters **exp** and **got** could be of any type. +Parameters **exp** and **got** could be of any type. **assert.NotEqual** @@ -42,7 +42,7 @@ func Test_Error(t *testing.T) { file, err := getFile("/file/path") assert.Error(err) - + // Test with optional comment assert.Error(t, err, "Expected file error.") } @@ -61,7 +61,7 @@ func Test_nil(t *testing.T) { nilValue := doWork() assert.Nil(nilValue) - + // Test with optional comment assert.Nil(t, nilValue, "Some comment") } @@ -88,6 +88,18 @@ Asserts parameter is *true*. Asserts parameter is *false*. +**assert.FileExists** + +Asserts file exists and is accessible. + +```go +func Test_WTF(t *testing.T) { + testLog := "/some/path/testlog.log" + createLogFile(testLog) + assert.FileExists(t, testLog) +} +``` + ## Assertion comments You may pass as many comments to assertions as you want. You can even use formating: diff --git a/assert/assert.go b/assert/assert.go index 2bffe5e..fa9a370 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -11,6 +11,7 @@ package assert import ( "fmt" "github.com/rzajac/pretty" + "os" "reflect" "runtime" "strings" @@ -185,6 +186,38 @@ func NotNil(t *testing.T, v interface{}, args ...interface{}) { Assert(t, result, nesting, failFast, fn) } +// FileExists asserts file exists. +func FileExists(t *testing.T, filePath string, args ...interface{}) { + var err error + exists := true + otherError := false + nesting, failFast, errorMsg := DecodeArgs(args...) + + if _, err = os.Stat(filePath); err != nil { + if os.IsNotExist(err) { + // file does not exist + exists = false + } else { + // other error + exists = false + otherError = true + } + } + + fn := func() { + if otherError { + t.Errorf("File %s exists but we got error: %s", filePath, err.Error()) + } else { + t.Errorf("File %s does not exist.", filePath) + } + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } + + Assert(t, exists, nesting, failFast, fn) +} + // Considered Internal // Assert is internal function but exported because it's used in other test packages. From 0ccf285f70fea3ce87ec1f9cec32a0c0eb887780 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 21 Jul 2013 15:08:16 +0200 Subject: [PATCH 13/26] Fix assertion nesting in assertmysql --- assertmysql/assertmysql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index e5b8ac0..db493a9 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -103,14 +103,14 @@ func TableCount(t *testing.T, expectedCount int) { // TableRowCount asserts tableName has expectedRowCount rows. func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { rowCount, err := GetTableRowCount(tableName) - assert.NotError(t, err) + assert.NotError(t, err, assert.NESTING_2) assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_2, "Expected %d rows got %d.", expectedRowCount, rowCount) } // TableNotEmpty asserts tableName is not empty. func TableNotEmpty(t *testing.T, tableName string) { row, _, err := dbcon.QueryFirst("SELECT * FROM %s LIMIT 1", tableName) - assert.NotError(t, err) + assert.NotError(t, err, assert.NESTING_2) assert.NotEqual(t, nil, row, assert.NESTING_2, "Expected table to have data.") } From f41d3467622b67e2908eda73b8596e38b666590d Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 21 Jul 2013 15:30:27 +0200 Subject: [PATCH 14/26] Show unexpected MySQL error message in assertmysql.NotError() --- assertmysql/assertmysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index db493a9..41fc4ca 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -49,7 +49,7 @@ func Error(t *testing.T, err error, args ...interface{}) { func NotError(t *testing.T, err error, args ...interface{}) { nesting, failFast, errorMsg := assert.DecodeArgs(args...) fn := func() { - t.Error("Did not expect MySQL error.") + t.Errorf("Did not expect MySQL error: %s", err.Error()) if len(errorMsg) > 0 { t.Error("!", " -", errorMsg) } From f55463659011b84e38abbc53d466b8c3a3a0c099 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Thu, 25 Jul 2013 18:15:19 +0200 Subject: [PATCH 15/26] Add assertions EqualFuncPtr, FuncPtr, Panic --- README.md | 47 ++++++++++++++++++++++++++++++++ assert/assert.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/README.md b/README.md index ae53ac7..eeb7e29 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,53 @@ func Test_WTF(t *testing.T) { } ``` +**assert.EqualFuncPtr** + +Asserts two function pointers are pointing to the same function. + +```go +func A() string { + return "A" +} + +type T struct{ + fn1: func() string + fn2: func() string +} + +func Test_Ptr(t *testing.T) { + t := &T{A, A} + assert.EqualFuncPtr(t, t.fn1, t.fn2) + + assert.FuncPtr(t, t.fn1) + assert.FuncPtr(t, t.fn2) +} +``` + +**assert.FuncPtr** + +Asserts pointer is a function pointer. See previous example. + +**assert.Panic** + +Asserts function panics. + +```go +func A() string { + panic("Not implemented") +} + + +func Test_Panic(t *testing.T) { + + fn := func() { + A() + } + + assert.Panic(t, fn, "Not implemented") +} +``` + ## Assertion comments You may pass as many comments to assertions as you want. You can even use formating: diff --git a/assert/assert.go b/assert/assert.go index fa9a370..ce844a1 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -218,6 +218,76 @@ func FileExists(t *testing.T, filePath string, args ...interface{}) { Assert(t, exists, nesting, failFast, fn) } +// EqualFuncPtr asserts exp and got point to the same function. +func EqualFuncPtr(t *testing.T, exp, got interface{}, args ...interface{}) { + var nameExp, nameGot string + expV := reflect.ValueOf(exp) + expKind := expV.Kind() + gotV := reflect.ValueOf(got) + gotKind := gotV.Kind() + + if !(expKind == reflect.Func || exp == nil || gotKind == reflect.Func || got == nil) { + nesting, failFast, _ := DecodeArgs(args...) + fn := func() { + if expKind != reflect.Func { + t.Error("exp must be a function or nil") + } + if gotKind != reflect.Func { + t.Error("got must be a function or nil") + } + } + Assert(t, false, nesting, failFast, fn) + return + } + + if expV.IsValid() { + fExp := runtime.FuncForPC(expV.Pointer()) + if fExp != nil { + nameExp = fExp.Name() + } + } + + if gotV.IsValid() { + fGot := runtime.FuncForPC(gotV.Pointer()) + if fGot != nil { + nameGot = fGot.Name() + } + } + + equal(t, nameExp, nameGot, args...) +} + +// FuncPtr asserts exp is a pointer to function. +func FuncPtr(t *testing.T, exp interface{}, args ...interface{}) { + expV := reflect.ValueOf(exp) + expKind := expV.Kind() + + nesting, failFast, errorMsg := DecodeArgs(args...) + fn := func() { + t.Error("Expected function.") + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } + + Assert(t, expKind == reflect.Func, nesting, failFast, fn) +} + +// Panic asserts that calling fn will panic. +func Panic(t *testing.T, fn func(), errorMsg string, args ...interface{}) { + nesting, failFast, _ := DecodeArgs(args...) + defer func() { + eMsg := recover() + var msg string + msg, ok := eMsg.(string) + if ok && !strings.Contains(msg, errorMsg) { + Equal(t, errorMsg, msg, nesting+1, failFast, errorMsg) + } + }() + fn() + T(t, false, nesting+1, failFast, "Expected panic") +} + // Considered Internal // Assert is internal function but exported because it's used in other test packages. From d5fac389aa0d0da43287122e02d3e322026ec65b Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sat, 27 Jul 2013 12:37:09 +0200 Subject: [PATCH 16/26] Better error messages for assertmysql, filter assert files in stack trace --- assert/assert.go | 4 ++-- assertmysql/assertmysql.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index ce844a1..7ee0fb1 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -296,8 +296,8 @@ func Assert(t *testing.T, result bool, nesting int, failFast bool, f func()) { nesting++ for n := 0; n <= nesting; n++ { _, file, line, _ := runtime.Caller(n) - if strings.Contains(file, "github.com/rzajac/assert/assert") { - // continue + if strings.Contains(file, "rzajac/assert/") { + continue } t.Errorf("%s:%d", file, line) } diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 41fc4ca..b4240dc 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -76,7 +76,7 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row, mysql.Result) { rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) assert.NotError(t, err, assert.NESTING_2, assert.FAIL_FAST) - assert.T(t, len(rows) > 0, assert.NESTING_2, assert.FAIL_FAST, "0 rows returned.") + assert.T(t, len(rows) > 0, assert.NESTING_2, assert.FAIL_FAST, "Expected row with %s = %s to exist in the database.", pkName, selectValue) return rows, res } @@ -104,7 +104,7 @@ func TableCount(t *testing.T, expectedCount int) { func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { rowCount, err := GetTableRowCount(tableName) assert.NotError(t, err, assert.NESTING_2) - assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_2, "Expected %d rows got %d.", expectedRowCount, rowCount) + assert.Equal(t, rowCount, expectedRowCount, assert.NESTING_2, "Expected %d rows in %s table but got %d.", expectedRowCount, tableName, rowCount) } // TableNotEmpty asserts tableName is not empty. From 01f39d1dc7732e02b74a4194f6b28c2e8f0cf420 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sun, 28 Jul 2013 18:31:53 +0200 Subject: [PATCH 17/26] ApproximatelyEqual --- assert/assert.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/assert/assert.go b/assert/assert.go index 7ee0fb1..041f0af 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -11,6 +11,7 @@ package assert import ( "fmt" "github.com/rzajac/pretty" + "math" "os" "reflect" "runtime" @@ -288,6 +289,28 @@ func Panic(t *testing.T, fn func(), errorMsg string, args ...interface{}) { T(t, false, nesting+1, failFast, "Expected panic") } +func ApproximatelyEqual(t *testing.T, exp, got, epsilon float64, args ...interface{}) { + var relativeError float64 + + if math.Abs(exp-got) < epsilon { + return + } + + expAbs := math.Abs(exp) + gotAbs := math.Abs(got) + + if gotAbs > expAbs { + relativeError = math.Abs((exp - got) / got) + } else { + relativeError = math.Abs((exp - got) / exp) + } + + result := relativeError <= epsilon + nesting, failFast, errorMsg := DecodeArgs(args...) + errorMsg = fmt.Sprintf("Expected %v to be approximately equal to %v (relative error: %v, epsilon %v)", exp, got, relativeError, epsilon) + T(t, result, nesting+1, failFast, errorMsg) +} + // Considered Internal // Assert is internal function but exported because it's used in other test packages. From b6b42f6fc79d0cc54837b91e317caac58ce1dcb7 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 31 Jul 2013 21:58:23 +0200 Subject: [PATCH 18/26] Add ApproximatelyEqual - wip --- assert/assert.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index 041f0af..40a65be 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -305,10 +305,16 @@ func ApproximatelyEqual(t *testing.T, exp, got, epsilon float64, args ...interfa relativeError = math.Abs((exp - got) / exp) } - result := relativeError <= epsilon nesting, failFast, errorMsg := DecodeArgs(args...) - errorMsg = fmt.Sprintf("Expected %v to be approximately equal to %v (relative error: %v, epsilon %v)", exp, got, relativeError, epsilon) - T(t, result, nesting+1, failFast, errorMsg) + fn := func() { + t.Errorf("Expected %f to be approximately equal to %f (relative error: %f, epsilon %f)", exp, got, relativeError, epsilon) + if len(errorMsg) > 0 { + t.Error(errorMsg) + } + } + + result := relativeError <= epsilon + Assert(t, result, nesting+1, failFast, fn) } // Considered Internal From e55165e66ac2f636c84d16a00b600c6234bb1105 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 31 Jul 2013 21:59:04 +0200 Subject: [PATCH 19/26] RowExists takes interface{} as selectValue --- assertmysql/assertmysql.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index b4240dc..65bc0de 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -10,6 +10,7 @@ package assertmysql import ( + "fmt" "github.com/rzajac/assert/assert" "github.com/ziutek/mymysql/mysql" _ "github.com/ziutek/mymysql/thrsafe" @@ -73,10 +74,14 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { } // RowExists asserts row exists in a table. -func RowExists(t *testing.T, tableName, pkName, selectValue string) ([]mysql.Row, mysql.Result) { - rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, dbcon.Escape(selectValue)) +func RowExists(t *testing.T, tableName, pkName, selectValue interface{}) ([]mysql.Row, mysql.Result) { + value := fmt.Sprintf("%v", selectValue) + if _, ok := selectValue.(string); ok { + value = "'" + dbcon.Escape(value) + "'" + } + rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, value) assert.NotError(t, err, assert.NESTING_2, assert.FAIL_FAST) - assert.T(t, len(rows) > 0, assert.NESTING_2, assert.FAIL_FAST, "Expected row with %s = %s to exist in the database.", pkName, selectValue) + assert.T(t, len(rows) > 0, assert.NESTING_2, assert.FAIL_FAST, "Expected row with %s = %s to exist in the database.", pkName, value) return rows, res } From b1d33fafeca08473daf206414b838b62a48f19d2 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Mon, 5 Aug 2013 11:06:31 +0200 Subject: [PATCH 20/26] Display message when panic did not occure --- assert/assert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assert/assert.go b/assert/assert.go index 40a65be..8d88054 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -276,7 +276,7 @@ func FuncPtr(t *testing.T, exp interface{}, args ...interface{}) { // Panic asserts that calling fn will panic. func Panic(t *testing.T, fn func(), errorMsg string, args ...interface{}) { - nesting, failFast, _ := DecodeArgs(args...) + nesting, failFast, tstMsg := DecodeArgs(args...) defer func() { eMsg := recover() var msg string @@ -286,7 +286,7 @@ func Panic(t *testing.T, fn func(), errorMsg string, args ...interface{}) { } }() fn() - T(t, false, nesting+1, failFast, "Expected panic") + T(t, false, nesting+1, failFast, "Expected panic: "+tstMsg) } func ApproximatelyEqual(t *testing.T, exp, got, epsilon float64, args ...interface{}) { From 71eae2cd02656ace1f2ad820ad6b3fcf3c916e89 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Tue, 6 Aug 2013 10:35:44 +0200 Subject: [PATCH 21/26] Add RowDoesNotExist --- README.md | 1 + assertmysql/assertmysql.go | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/README.md b/README.md index eeb7e29..d1dea9c 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,7 @@ This imports both packages but you can use only one of them. * **assertmysql.NotError** - asserts error is not MySQL error. * **assertmysql.ErrorCode** - asserts error is MySQL error and has specific code. * **assertmysql.RowExists** - asserts row exists in a table. +* **assertmysql.RowDoesNotExist** - asserts row does not exists in a table. * **assertmysql.TableExists** - asserts table exists in database. * **assertmysql.TableCount** - asserts database has x tables. * **assertmysql.TableRowCount** - asserts database table has x rows. diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 65bc0de..cb7410e 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -85,6 +85,18 @@ func RowExists(t *testing.T, tableName, pkName, selectValue interface{}) ([]mysq return rows, res } +// RowExists asserts row exists in a table. +func RowDoesNotExists(t *testing.T, tableName, pkName, selectValue interface{}) ([]mysql.Row, mysql.Result) { + value := fmt.Sprintf("%v", selectValue) + if _, ok := selectValue.(string); ok { + value = "'" + dbcon.Escape(value) + "'" + } + rows, res, err := dbcon.Query("SELECT * FROM %s WHERE %s = %s", tableName, pkName, value) + assert.NotError(t, err, assert.NESTING_2, assert.FAIL_FAST) + assert.T(t, len(rows) == 0, assert.NESTING_2, assert.FAIL_FAST, "Did not expect row with %s = %s to exist in the database.", pkName, value) + return rows, res +} + // assertTableExists asserts MySQL table exists in the database. func TableExists(t *testing.T, tableName string) { var foundTable bool From ad7ac2d47d8526baa27010de597f885e5a583f91 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Sat, 10 Aug 2013 11:13:55 +0200 Subject: [PATCH 22/26] Fix panic in assertmysql.ErrorCode when err == nil --- assertmysql/assertmysql.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index cb7410e..0d5bfc1 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -66,7 +66,11 @@ func ErrorCode(t *testing.T, err error, errorCode uint16) { merr := GetMySqlErorr(err) fn := func() { t.Error("Expected MySQL error but got some other error.") - t.Errorf("Got error: %s", err.Error()) + if err == nil { + t.Errorf("Got error: nil") + } else { + t.Errorf("Got error: %s", err.Error()) + } } _, ok := err.(*mysql.Error) assert.Assert(t, ok, assert.NESTING_2, assert.FAIL_FAST, fn) @@ -144,7 +148,11 @@ func GetMySqlErorr(err error) *mysql.Error { if !ok { mysqle = new(mysql.Error) - mysqle.Msg = []byte(err.Error()) + if err == nil { + mysqle.Msg = []byte("") + } else { + mysqle.Msg = []byte(err.Error()) + } mysqle.Code = DUMMY_MYSQL_ERROR_CODE } return mysqle From f64f4db8aa37a86401205a6b31844807ea5cb408 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Mon, 19 Aug 2013 00:13:04 +0200 Subject: [PATCH 23/26] Better error message in assert.Error() --- assert/assert.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/assert/assert.go b/assert/assert.go index 8d88054..90782eb 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -87,8 +87,16 @@ func F(t *testing.T, result bool, args ...interface{}) { // Error asserts that err is of type error. func Error(t *testing.T, err interface{}, args ...interface{}) { + nesting, failFast, errorMsg := DecodeArgs(args...) + fn := func() { + t.Error("Expected error.") + t.Errorf("Got: %v", err) + if len(errorMsg) > 0 { + t.Error("!", " -", errorMsg) + } + } _, ok := err.(error) - equal(t, false, !ok, args...) + Assert(t, ok, nesting, failFast, fn) } // ErrorMsgContains asserts that err is of type error From 9ad1bc7eefb55e6299bca9d7120e5e27cbf2fc95 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Mon, 23 Sep 2013 00:28:26 +0200 Subject: [PATCH 24/26] Doc strings update --- assertmysql/assertmysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 0d5bfc1..0c28065 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -89,7 +89,7 @@ func RowExists(t *testing.T, tableName, pkName, selectValue interface{}) ([]mysq return rows, res } -// RowExists asserts row exists in a table. +// RowDoesNotExists asserts row exists in a table. func RowDoesNotExists(t *testing.T, tableName, pkName, selectValue interface{}) ([]mysql.Row, mysql.Result) { value := fmt.Sprintf("%v", selectValue) if _, ok := selectValue.(string); ok { From cdf611f118f10e90a7189916da6850a7e3858624 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Mon, 23 Sep 2013 00:30:50 +0200 Subject: [PATCH 25/26] Add assertmysql.TableDoesNotExists --- README.md | 1 + assertmysql/assertmysql.go | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d1dea9c..ad68ce7 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,7 @@ This imports both packages but you can use only one of them. * **assertmysql.RowExists** - asserts row exists in a table. * **assertmysql.RowDoesNotExist** - asserts row does not exists in a table. * **assertmysql.TableExists** - asserts table exists in database. +* **assertmysql.TableDoesNotExists** - asserts table does not exist in database. * **assertmysql.TableCount** - asserts database has x tables. * **assertmysql.TableRowCount** - asserts database table has x rows. * **assertmysql.TableNotEmpty** - asserts table is not empty (has at least one row). diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 0c28065..10a35bc 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -101,7 +101,7 @@ func RowDoesNotExists(t *testing.T, tableName, pkName, selectValue interface{}) return rows, res } -// assertTableExists asserts MySQL table exists in the database. +// TableExists asserts MySQL table exists in the database. func TableExists(t *testing.T, tableName string) { var foundTable bool sqlTables, _ := GetTableNames() @@ -114,6 +114,19 @@ func TableExists(t *testing.T, tableName string) { assert.T(t, foundTable, assert.NESTING_2, "Table '%s' is not present in the database.", tableName) } +// TableDoesNotExists asserts MySQL table does not exists in the database. +func TableDoesNotExists(t *testing.T, tableName string) { + var foundTable bool + sqlTables, _ := GetTableNames() + for _, dbTableName := range sqlTables { + if dbTableName == tableName { + foundTable = true + break + } + } + assert.T(t, !foundTable, assert.NESTING_2, "Table '%s' is present in the database.", tableName) +} + // TableCount asserts number of tables in the database. func TableCount(t *testing.T, expectedCount int) { sqlTables, _ := GetTableNames() From aaf332118870c892e498309e389b334fed8b397a Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Mon, 23 Sep 2013 09:21:10 +0200 Subject: [PATCH 26/26] Cleanup --- assertmysql/assertmysql.go | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/assertmysql/assertmysql.go b/assertmysql/assertmysql.go index 10a35bc..422e63a 100644 --- a/assertmysql/assertmysql.go +++ b/assertmysql/assertmysql.go @@ -103,27 +103,13 @@ func RowDoesNotExists(t *testing.T, tableName, pkName, selectValue interface{}) // TableExists asserts MySQL table exists in the database. func TableExists(t *testing.T, tableName string) { - var foundTable bool - sqlTables, _ := GetTableNames() - for _, dbTableName := range sqlTables { - if dbTableName == tableName { - foundTable = true - break - } - } + foundTable := tableExists(tableName) assert.T(t, foundTable, assert.NESTING_2, "Table '%s' is not present in the database.", tableName) } // TableDoesNotExists asserts MySQL table does not exists in the database. func TableDoesNotExists(t *testing.T, tableName string) { - var foundTable bool - sqlTables, _ := GetTableNames() - for _, dbTableName := range sqlTables { - if dbTableName == tableName { - foundTable = true - break - } - } + foundTable := tableExists(tableName) assert.T(t, !foundTable, assert.NESTING_2, "Table '%s' is present in the database.", tableName) } @@ -143,9 +129,22 @@ func TableRowCount(t *testing.T, tableName string, expectedRowCount int) { // TableNotEmpty asserts tableName is not empty. func TableNotEmpty(t *testing.T, tableName string) { - row, _, err := dbcon.QueryFirst("SELECT * FROM %s LIMIT 1", tableName) + rowCount, err := GetTableRowCount(tableName) assert.NotError(t, err, assert.NESTING_2) - assert.NotEqual(t, nil, row, assert.NESTING_2, "Expected table to have data.") + assert.T(t, rowCount > 0, assert.NESTING_2, "Expected table to have data.") +} + +// tableExists returns true if table exists in database. +func tableExists(tableName string) bool { + var foundTable bool + sqlTables, _ := GetTableNames() + for _, dbTableName := range sqlTables { + if dbTableName == tableName { + foundTable = true + break + } + } + return foundTable } // helper functions