From 32b009025db84e12e105b094a26dc2e07be496ba Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Sat, 22 Nov 2014 07:44:24 +0800 Subject: [PATCH] Update testify dependency. --- Godeps/Godeps.json | 4 +- .../stretchr/testify/assert/assertions.go | 147 ++++++++++++- .../testify/assert/assertions_test.go | 200 ++++++++++++++++++ .../github.com/stretchr/testify/assert/doc.go | 8 +- .../testify/assert/forward_assertions.go | 28 ++- .../testify/assert/forward_assertions_test.go | 138 ++++++++++++ .../testify/assert/http_assertions.go | 157 ++++++++++++++ .../testify/assert/http_assertions_test.go | 86 ++++++++ .../github.com/stretchr/testify/mock/mock.go | 11 +- 9 files changed, 755 insertions(+), 24 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go create mode 100644 Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e2b19edb..6c3f4d67 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -92,11 +92,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "ed6ea184117f7ae3168d1c05dbdbde1a86e2be68" + "Rev": "8ce79b9f0b77745113f82c17d0756771456ccbd3" }, { "ImportPath": "github.com/stretchr/testify/mock", - "Rev": "ed6ea184117f7ae3168d1c05dbdbde1a86e2be68" + "Rev": "8ce79b9f0b77745113f82c17d0756771456ccbd3" } ] } diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go index 95dc6759..8af3157c 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go @@ -1,8 +1,11 @@ package assert import ( + "bufio" + "bytes" "fmt" "reflect" + "regexp" "runtime" "strings" "time" @@ -73,7 +76,7 @@ func CallerInfo() string { parts := strings.Split(file, "/") dir := parts[len(parts)-2] file = parts[len(parts)-1] - if (dir != "assert" && dir != "mock") || file == "mock_test.go" { + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { break } } @@ -109,15 +112,48 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { return "" } +// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's +// test printing (see inner comment for specifics) +func indentMessageLines(message string, tabs int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + if i != 0 { + outBuf.WriteRune('\n') + } + for ii := 0; ii < tabs; ii++ { + outBuf.WriteRune('\t') + // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter + // by 1 prematurely. + if ii == 0 && i > 0 { + ii++ + } + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { message := messageFromMsgAndArgs(msgAndArgs...) if len(message) > 0 { - t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r\tMessages:\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage, message) + t.Errorf("\r%s\r\tLocation:\t%s\n"+ + "\r\tError:%s\n"+ + "\r\tMessages:\t%s\n\r", + getWhitespaceString(), + CallerInfo(), + indentMessageLines(failureMessage, 2), + message) } else { - t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage) + t.Errorf("\r%s\r\tLocation:\t%s\n"+ + "\r\tError:%s\n\r", + getWhitespaceString(), + CallerInfo(), + indentMessageLines(failureMessage, 2)) } return false @@ -156,7 +192,8 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqual(expected, actual) { - return Fail(t, fmt.Sprintf("Not equal: %#v != %#v", expected, actual), msgAndArgs...) + return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ + " != %#v (actual)", expected, actual), msgAndArgs...) } return true @@ -349,7 +386,7 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but have %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } @@ -399,14 +436,48 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{ } -// Contains asserts that the specified string contains the specified substring. +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + elementValue := reflect.ValueOf(element) + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if reflect.TypeOf(list).Kind() == reflect.String { + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string or list(array, slice...) contains the +// specified substring or element. // // assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'") +// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") // // Returns whether the assertion was successful (true) or not (false). -func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool { +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if !strings.Contains(s, contains) { + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) } @@ -414,14 +485,20 @@ func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool { } -// NotContains asserts that the specified string does NOT contain the specified substring. +// NotContains asserts that the specified string or list(array, slice...) does NOT contain the +// specified substring or element. // // assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") +// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). -func NotContains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool { +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if strings.Contains(s, contains) { + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) } @@ -655,3 +732,51 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte return Equal(t, theError.Error(), errString, s, errString, theError.Error(), message) } + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func Regexp(t TestingT, rx interface{}, str interface{}) bool { + + match := matchRegexp(rx, str) + + if !match { + Fail(t, "Expect \"%s\" to match \"%s\"") + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func NotRegexp(t TestingT, rx interface{}, str interface{}) bool { + match := matchRegexp(rx, str) + + if match { + Fail(t, "Expect \"%s\" to NOT match \"%s\"") + } + + return !match + +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go index 4f91c215..bb63be26 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go @@ -2,6 +2,7 @@ package assert import ( "errors" + "regexp" "testing" "time" ) @@ -195,11 +196,38 @@ func TestNotEqual(t *testing.T) { if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) { t.Error("NotEqual should return true") } + + if NotEqual(mockT, "Hello World", "Hello World") { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, 123, 123) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, 123.5, 123.5) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { + t.Error("NotEqual should return false") + } +} + +type A struct { + Name, Value string } func TestContains(t *testing.T) { mockT := new(testing.T) + list := []string{"Foo", "Bar"} + complexList := []*A{ + &A{"b", "c"}, + &A{"d", "e"}, + &A{"g", "h"}, + &A{"j", "k"}, + } if !Contains(mockT, "Hello World", "Hello") { t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") @@ -208,11 +236,24 @@ func TestContains(t *testing.T) { t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") } + if !Contains(mockT, list, "Bar") { + t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"") + } + if Contains(mockT, list, "Salut") { + t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") + } + if !Contains(mockT, complexList, &A{"g", "h"}) { + t.Error("Contains should return true: complexList contains {\"g\", \"h\"}") + } + if Contains(mockT, complexList, &A{"g", "e"}) { + t.Error("Contains should return false: complexList contains {\"g\", \"e\"}") + } } func TestNotContains(t *testing.T) { mockT := new(testing.T) + list := []string{"Foo", "Bar"} if !NotContains(mockT, "Hello World", "Hello!") { t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") @@ -221,6 +262,69 @@ func TestNotContains(t *testing.T) { t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") } + if !NotContains(mockT, list, "Foo!") { + t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") + } + if NotContains(mockT, list, "Foo") { + t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + +} + +func Test_includeElement(t *testing.T) { + + list1 := []string{"Foo", "Bar"} + list2 := []int{1, 2} + + ok, found := includeElement("Hello World", "World") + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Foo") + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Bar") + True(t, ok) + True(t, found) + + ok, found = includeElement(list2, 1) + True(t, ok) + True(t, found) + + ok, found = includeElement(list2, 2) + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Foo!") + True(t, ok) + False(t, found) + + ok, found = includeElement(list2, 3) + True(t, ok) + False(t, found) + + ok, found = includeElement(list2, "1") + True(t, ok) + False(t, found) + + ok, found = includeElement(1433, "1") + False(t, ok) + False(t, found) + +} + +func TestCondition(t *testing.T) { + mockT := new(testing.T) + + if !Condition(mockT, func() bool { return true }, "Truth") { + t.Error("Condition should return true") + } + + if Condition(mockT, func() bool { return false }, "Lie") { + t.Error("Condition should return false") + } + } func TestDidPanic(t *testing.T) { @@ -482,6 +586,29 @@ func TestLen(t *testing.T) { for _, c := range cases { True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) } + + cases = []struct { + v interface{} + l int + }{ + {[]int{1, 2, 3}, 4}, + {[...]int{1, 2, 3}, 2}, + {"ABC", 2}, + {map[int]int{1: 2, 2: 4, 3: 6}, 4}, + {ch, 2}, + + {[]int{}, 1}, + {map[int]int{}, 1}, + {make(chan int), 1}, + + {[]int(nil), 1}, + {map[int]int(nil), 1}, + {(chan int)(nil), 1}, + } + + for _, c := range cases { + False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) + } } func TestWithinDuration(t *testing.T) { @@ -536,3 +663,76 @@ func TestInDelta(t *testing.T) { True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) } } + +func TestInEpsilon(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), uint16(2), .001}, + {2.1, 2.2, 0.1}, + {2.2, 2.1, 0.1}, + {-2.1, -2.2, 0.1}, + {-2.2, -2.1, 0.1}, + {uint64(100), uint8(101), 0.01}, + {0.1, -0.1, 2}, + } + + for _, tc := range cases { + True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + + cases = []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), int16(-2), .001}, + {uint64(100), uint8(102), 0.01}, + {2.1, 2.2, 0.001}, + {2.2, 2.1, 0.001}, + {2.1, -2.2, 1}, + {2.1, "bla-bla", 0}, + {0.1, -0.1, 1.99}, + } + + for _, tc := range cases { + False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + +} + +func TestRegexp(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + rx, str string + }{ + {"^start", "start of the line"}, + {"end$", "in the end"}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, + } + + for _, tc := range cases { + True(t, Regexp(mockT, tc.rx, tc.str)) + True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + False(t, NotRegexp(mockT, tc.rx, tc.str)) + False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + } + + cases = []struct { + rx, str string + }{ + {"^asdfastart", "Not the start of the line"}, + {"end$", "in the end."}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, + } + + for _, tc := range cases { + False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) + False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + True(t, NotRegexp(mockT, tc.rx, tc.str)) + True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + } +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go index 4c72f42c..1c6de283 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go @@ -73,9 +73,9 @@ // // assert.IsType(t, expectedObject, actualObject [, message [, format-args]]) // -// assert.Contains(t, string, substring [, message [, format-args]]) +// assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]]) // -// assert.NotContains(t, string, substring [, message [, format-args]]) +// assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]]) // // assert.Panics(t, func(){ // @@ -126,9 +126,9 @@ // // assert.IsType(expectedObject, actualObject [, message [, format-args]]) // -// assert.Contains(string, substring [, message [, format-args]]) +// assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]]) // -// assert.NotContains(string, substring [, message [, format-args]]) +// assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]]) // // assert.Panics(func(){ // diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go index 7c2eea76..e2866f8b 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go @@ -129,7 +129,7 @@ func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interf // assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") // // Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) Contains(s, contains string, msgAndArgs ...interface{}) bool { +func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool { return Contains(a.t, s, contains, msgAndArgs...) } @@ -138,7 +138,7 @@ func (a *Assertions) Contains(s, contains string, msgAndArgs ...interface{}) boo // assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") // // Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) NotContains(s, contains string, msgAndArgs ...interface{}) bool { +func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool { return NotContains(a.t, s, contains, msgAndArgs...) } @@ -183,14 +183,14 @@ func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Durat // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { +func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { +func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } @@ -230,3 +230,23 @@ func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool { func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { return EqualError(a.t, theError, errString, msgAndArgs...) } + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Regexp(rx interface{}, str interface{}) bool { + return Regexp(a.t, rx, str) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotRegexp(rx interface{}, str interface{}) bool { + return NotRegexp(a.t, rx, str) +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go index 7982b07a..20cca6e2 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go @@ -2,6 +2,7 @@ package assert import ( "errors" + "regexp" "testing" "time" ) @@ -148,6 +149,7 @@ func TestNotEqualWrapper(t *testing.T) { func TestContainsWrapper(t *testing.T) { assert := New(new(testing.T)) + list := []string{"Foo", "Bar"} if !assert.Contains("Hello World", "Hello") { t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") @@ -156,11 +158,19 @@ func TestContainsWrapper(t *testing.T) { t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") } + if !assert.Contains(list, "Foo") { + t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + if assert.Contains(list, "Salut") { + t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") + } + } func TestNotContainsWrapper(t *testing.T) { assert := New(new(testing.T)) + list := []string{"Foo", "Bar"} if !assert.NotContains("Hello World", "Hello!") { t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") @@ -169,6 +179,27 @@ func TestNotContainsWrapper(t *testing.T) { t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") } + if !assert.NotContains(list, "Foo!") { + t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") + } + if assert.NotContains(list, "Foo") { + t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + +} + +func TestConditionWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + if !assert.Condition(func() bool { return true }, "Truth") { + t.Error("Condition should return true") + } + + if assert.Condition(func() bool { return false }, "Lie") { + t.Error("Condition should return false") + } + } func TestDidPanicWrapper(t *testing.T) { @@ -378,3 +409,110 @@ func TestWithinDurationWrapper(t *testing.T) { assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") } + +func TestInDeltaWrapper(t *testing.T) { + assert := New(new(testing.T)) + + True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01") + True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01") + True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1") + False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") + False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") + False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail") + + cases := []struct { + a, b interface{} + delta float64 + }{ + {uint8(2), uint8(1), 1}, + {uint16(2), uint16(1), 1}, + {uint32(2), uint32(1), 1}, + {uint64(2), uint64(1), 1}, + + {int(2), int(1), 1}, + {int8(2), int8(1), 1}, + {int16(2), int16(1), 1}, + {int32(2), int32(1), 1}, + {int64(2), int64(1), 1}, + + {float32(2), float32(1), 1}, + {float64(2), float64(1), 1}, + } + + for _, tc := range cases { + True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) + } +} + +func TestInEpsilonWrapper(t *testing.T) { + assert := New(new(testing.T)) + + cases := []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), uint16(2), .001}, + {2.1, 2.2, 0.1}, + {2.2, 2.1, 0.1}, + {-2.1, -2.2, 0.1}, + {-2.2, -2.1, 0.1}, + {uint64(100), uint8(101), 0.01}, + {0.1, -0.1, 2}, + } + + for _, tc := range cases { + True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + + cases = []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), int16(-2), .001}, + {uint64(100), uint8(102), 0.01}, + {2.1, 2.2, 0.001}, + {2.2, 2.1, 0.001}, + {2.1, -2.2, 1}, + {2.1, "bla-bla", 0}, + {0.1, -0.1, 1.99}, + } + + for _, tc := range cases { + False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } +} + +func TestRegexpWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + cases := []struct { + rx, str string + }{ + {"^start", "start of the line"}, + {"end$", "in the end"}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, + } + + for _, tc := range cases { + True(t, assert.Regexp(tc.rx, tc.str)) + True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) + False(t, assert.NotRegexp(tc.rx, tc.str)) + False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) + } + + cases = []struct { + rx, str string + }{ + {"^asdfastart", "Not the start of the line"}, + {"end$", "in the end."}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, + } + + for _, tc := range cases { + False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) + False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) + True(t, assert.NotRegexp(tc.rx, tc.str)) + True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) + } +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 00000000..0bcb6db9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,157 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 +// if building a new request fails. +func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int { + w := httptest.NewRecorder() + req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil) + if err != nil { + return -1 + } + handler(w, req) + return w.Code +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusOK && code <= http.StatusPartialContent +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusBadRequest +} + +// HttpBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HttpBody(handler http.HandlerFunc, mode, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + body := HttpBody(handler, mode, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + body := HttpBody(handler, mode, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body) + } + + return !contains +} + +// +// Assertions Wrappers +// + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(myHandler, "POST", http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPSuccess(a.t, handler, mode, url, values) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPRedirect(a.t, handler, mode, url, values) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPError(a.t, handler, mode, url, values) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + return HTTPBodyContains(a.t, handler, mode, url, values, str) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + return HTTPBodyNotContains(a.t, handler, mode, url, values, str) +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go new file mode 100644 index 00000000..684c2d5d --- /dev/null +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go @@ -0,0 +1,86 @@ +package assert + +import ( + "fmt" + "net/http" + "net/url" + "testing" +) + +func httpOK(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} + +func httpRedirect(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTemporaryRedirect) +} + +func httpError(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) +} + +func TestHTTPStatuses(t *testing.T) { + assert := New(t) + mockT := new(testing.T) + + assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true) + assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false) + assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false) + + assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false) + assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true) + assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false) + + assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false) + assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false) + assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true) +} + +func TestHTTPStatusesWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true) + assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false) + + assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true) + assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false) + + assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true) +} + +func httpHelloName(w http.ResponseWriter, r *http.Request) { + name := r.FormValue("name") + w.Write([]byte(fmt.Sprintf("Hello, %s!", name))) +} + +func TestHttpBody(t *testing.T) { + assert := New(t) + mockT := new(testing.T) + + assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + + assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) +} + +func TestHttpBodyWrappers(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + + assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + +} diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go index eb003672..f73fa251 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go @@ -7,6 +7,7 @@ import ( "reflect" "runtime" "strings" + "sync" ) // TestingT is an interface wrapper around *testing.T @@ -60,6 +61,8 @@ type Mock struct { // TestData holds any data that might be useful for testing. Testify ignores // this data completely allowing you to do whatever you like with it. testData objx.Map + + mutex sync.Mutex } // TestData holds any data that might be useful for testing. Testify ignores @@ -178,6 +181,8 @@ func callString(method string, arguments Arguments, includeArgumentValues bool) // of arguments to return. Panics if the call is unexpected (i.e. not preceeded by // appropriate .On .Return() calls) func (m *Mock) Called(arguments ...interface{}) Arguments { + defer m.mutex.Unlock() + m.mutex.Lock() // get the calling function's name pc, _, _, ok := runtime.Caller(1) @@ -473,7 +478,7 @@ func (args Arguments) Int(index int) int { var s int var ok bool if s, ok = args.Get(index).(int); !ok { - panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %s", index, args.Get(index))) + panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s } @@ -488,7 +493,7 @@ func (args Arguments) Error(index int) error { return nil } if s, ok = obj.(error); !ok { - panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %s", index, args.Get(index))) + panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s } @@ -499,7 +504,7 @@ func (args Arguments) Bool(index int) bool { var s bool var ok bool if s, ok = args.Get(index).(bool); !ok { - panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %s", index, args.Get(index))) + panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index))) } return s }