Repository: stretchr/testify
Pull request #880 (2020-01-29 08:21:18)

Update License file copyright year

glesica: There are quite a few contributors and AFAIK the project has never had a copyright assignment requirement. Should we add "and contributors" or something to the end of that?

Patch:
diff --git a/.travis.yml b/.travis.yml
index 2d4a445..46fdecf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,6 +20,9 @@ matrix:
     - go: "1.13.x"
       env: GO111MODULE=on
     - go: master
+      env: GO111MODULE=on
+    - go: master
+      env: GO111MODULE=off
 script:
   - ./.travis.gogenerate.sh
   - ./.travis.gofmt.sh
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e155426..a3a062c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,7 +42,7 @@ See `MAINTAINERS.md` for a list of users who can approve / merge your changes.
 ## Issues
 
 If you find a bug or think of a useful feature you'd like to see added to Testify, the best thing
-you can do is make the necessary changes and open a pull requests (see above). If that isn't an
+you can do is make the necessary changes and open a pull request (see above). If that isn't an
 option, or if you'd like to discuss your change before you write the code, open an issue!
 
 Please provide enough context in the issue description that other members of the community can
diff --git a/LICENSE b/LICENSE
index f38ec59..4b0421c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell
+Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/assert/assertion_order.go b/assert/assertion_compare.go
similarity index 62%
rename from assert/assertion_order.go
rename to assert/assertion_compare.go
index 15a486c..66961ba 100644
--- a/assert/assertion_order.go
+++ b/assert/assertion_compare.go
@@ -5,20 +5,28 @@ import (
 	"reflect"
 )
 
-func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
+type CompareType int
+
+const (
+	compareLess CompareType = iota - 1
+	compareEqual
+	compareGreater
+)
+
+func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 	switch kind {
 	case reflect.Int:
 		{
 			intobj1 := obj1.(int)
 			intobj2 := obj2.(int)
 			if intobj1 > intobj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if intobj1 == intobj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if intobj1 < intobj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Int8:
@@ -26,13 +34,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			int8obj1 := obj1.(int8)
 			int8obj2 := obj2.(int8)
 			if int8obj1 > int8obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if int8obj1 == int8obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if int8obj1 < int8obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Int16:
@@ -40,13 +48,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			int16obj1 := obj1.(int16)
 			int16obj2 := obj2.(int16)
 			if int16obj1 > int16obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if int16obj1 == int16obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if int16obj1 < int16obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Int32:
@@ -54,13 +62,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			int32obj1 := obj1.(int32)
 			int32obj2 := obj2.(int32)
 			if int32obj1 > int32obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if int32obj1 == int32obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if int32obj1 < int32obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Int64:
@@ -68,13 +76,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			int64obj1 := obj1.(int64)
 			int64obj2 := obj2.(int64)
 			if int64obj1 > int64obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if int64obj1 == int64obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if int64obj1 < int64obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Uint:
@@ -82,13 +90,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			uintobj1 := obj1.(uint)
 			uintobj2 := obj2.(uint)
 			if uintobj1 > uintobj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if uintobj1 == uintobj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if uintobj1 < uintobj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Uint8:
@@ -96,13 +104,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			uint8obj1 := obj1.(uint8)
 			uint8obj2 := obj2.(uint8)
 			if uint8obj1 > uint8obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if uint8obj1 == uint8obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if uint8obj1 < uint8obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Uint16:
@@ -110,13 +118,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			uint16obj1 := obj1.(uint16)
 			uint16obj2 := obj2.(uint16)
 			if uint16obj1 > uint16obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if uint16obj1 == uint16obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if uint16obj1 < uint16obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Uint32:
@@ -124,13 +132,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			uint32obj1 := obj1.(uint32)
 			uint32obj2 := obj2.(uint32)
 			if uint32obj1 > uint32obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if uint32obj1 == uint32obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if uint32obj1 < uint32obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Uint64:
@@ -138,13 +146,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			uint64obj1 := obj1.(uint64)
 			uint64obj2 := obj2.(uint64)
 			if uint64obj1 > uint64obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if uint64obj1 == uint64obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if uint64obj1 < uint64obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Float32:
@@ -152,13 +160,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			float32obj1 := obj1.(float32)
 			float32obj2 := obj2.(float32)
 			if float32obj1 > float32obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if float32obj1 == float32obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if float32obj1 < float32obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.Float64:
@@ -166,13 +174,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			float64obj1 := obj1.(float64)
 			float64obj2 := obj2.(float64)
 			if float64obj1 > float64obj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if float64obj1 == float64obj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if float64obj1 < float64obj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	case reflect.String:
@@ -180,18 +188,18 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 			stringobj1 := obj1.(string)
 			stringobj2 := obj2.(string)
 			if stringobj1 > stringobj2 {
-				return -1, true
+				return compareGreater, true
 			}
 			if stringobj1 == stringobj2 {
-				return 0, true
+				return compareEqual, true
 			}
 			if stringobj1 < stringobj2 {
-				return 1, true
+				return compareLess, true
 			}
 		}
 	}
 
-	return 0, false
+	return compareEqual, false
 }
 
 // Greater asserts that the first element is greater than the second
@@ -200,26 +208,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
 //    assert.Greater(t, float64(2), float64(1))
 //    assert.Greater(t, "b", "a")
 func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
-	if h, ok := t.(tHelper); ok {
-		h.Helper()
-	}
-
-	e1Kind := reflect.ValueOf(e1).Kind()
-	e2Kind := reflect.ValueOf(e2).Kind()
-	if e1Kind != e2Kind {
-		return Fail(t, "Elements should be the same type", msgAndArgs...)
-	}
-
-	res, isComparable := compare(e1, e2, e1Kind)
-	if !isComparable {
-		return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
-	}
-
-	if res != -1 {
-		return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...)
-	}
-
-	return true
+	return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%s\" is not greater than \"%s\"", msgAndArgs)
 }
 
 // GreaterOrEqual asserts that the first element is greater than or equal to the second
@@ -229,26 +218,7 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
 //    assert.GreaterOrEqual(t, "b", "a")
 //    assert.GreaterOrEqual(t, "b", "b")
 func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
-	if h, ok := t.(tHelper); ok {
-		h.Helper()
-	}
-
-	e1Kind := reflect.ValueOf(e1).Kind()
-	e2Kind := reflect.ValueOf(e2).Kind()
-	if e1Kind != e2Kind {
-		return Fail(t, "Elements should be the same type", msgAndArgs...)
-	}
-
-	res, isComparable := compare(e1, e2, e1Kind)
-	if !isComparable {
-		return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
-	}
-
-	if res != -1 && res != 0 {
-		return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...)
-	}
-
-	return true
+	return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%s\" is not greater than or equal to \"%s\"", msgAndArgs)
 }
 
 // Less asserts that the first element is less than the second
@@ -257,26 +227,7 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
 //    assert.Less(t, float64(1), float64(2))
 //    assert.Less(t, "a", "b")
 func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
-	if h, ok := t.(tHelper); ok {
-		h.Helper()
-	}
-
-	e1Kind := reflect.ValueOf(e1).Kind()
-	e2Kind := reflect.ValueOf(e2).Kind()
-	if e1Kind != e2Kind {
-		return Fail(t, "Elements should be the same type", msgAndArgs...)
-	}
-
-	res, isComparable := compare(e1, e2, e1Kind)
-	if !isComparable {
-		return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
-	}
-
-	if res != 1 {
-		return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...)
-	}
-
-	return true
+	return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%s\" is not less than \"%s\"", msgAndArgs)
 }
 
 // LessOrEqual asserts that the first element is less than or equal to the second
@@ -286,6 +237,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
 //    assert.LessOrEqual(t, "a", "b")
 //    assert.LessOrEqual(t, "b", "b")
 func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+	return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%s\" is not less than or equal to \"%s\"", msgAndArgs)
+}
+
+func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
 	if h, ok := t.(tHelper); ok {
 		h.Helper()
 	}
@@ -296,14 +251,24 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
 		return Fail(t, "Elements should be the same type", msgAndArgs...)
 	}
 
-	res, isComparable := compare(e1, e2, e1Kind)
+	compareResult, isComparable := compare(e1, e2, e1Kind)
 	if !isComparable {
 		return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
 	}
 
-	if res != 1 && res != 0 {
-		return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...)
+	if !containsValue(allowedComparesResults, compareResult) {
+		return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
 	}
 
 	return true
 }
+
+func containsValue(values []CompareType, value CompareType) bool {
+	for _, v := range values {
+		if v == value {
+			return true
+		}
+	}
+
+	return false
+}
diff --git a/assert/assertion_format.go b/assert/assertion_format.go
index bf89ecd..c07387d 100644
--- a/assert/assertion_format.go
+++ b/assert/assertion_format.go
@@ -245,6 +245,18 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
 	return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
 }
 
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+//  assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...)
+}
+
 // HTTPSuccessf asserts that a specified handler returns a success status code.
 //
 //  assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
diff --git a/assert/assertion_forward.go b/assert/assertion_forward.go
index 75ecdca..d55c980 100644
--- a/assert/assertion_forward.go
+++ b/assert/assertion_forward.go
@@ -479,6 +479,30 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
 	return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
 }
 
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+//  a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+//  a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
+}
+
 // HTTPSuccess asserts that a specified handler returns a success status code.
 //
 //  a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
diff --git a/assert/assertions.go b/assert/assertions.go
index bdd8138..bfbe9cf 100644
--- a/assert/assertions.go
+++ b/assert/assertions.go
@@ -104,11 +104,11 @@ the problem actually occurred in calling code.*/
 // failed.
 func CallerInfo() []string {
 
-	pc := uintptr(0)
-	file := ""
-	line := 0
-	ok := false
-	name := ""
+	var pc uintptr
+	var ok bool
+	var file string
+	var line int
+	var name string
 
 	callers := []string{}
 	for i := 0; ; i++ {
@@ -429,14 +429,27 @@ func samePointers(first, second interface{}) bool {
 // to a type conversion in the Go grammar.
 func formatUnequalValues(expected, actual interface{}) (e string, a string) {
 	if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
-		return fmt.Sprintf("%T(%#v)", expected, expected),
-			fmt.Sprintf("%T(%#v)", actual, actual)
+		return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
+			fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
 	}
 	switch expected.(type) {
 	case time.Duration:
 		return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
 	}
-	return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual)
+	return truncatingFormat(expected), truncatingFormat(actual)
+}
+
+// truncatingFormat formats the data and truncates it if it's too long.
+//
+// This helps keep formatted error messages lines from exceeding the
+// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
+func truncatingFormat(data interface{}) string {
+	value := fmt.Sprintf("%#v", data)
+	max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
+	if len(value) > max {
+		value = value[0:max] + "<... truncated>"
+	}
+	return value
 }
 
 // EqualValues asserts that two objects are equal or convertable to the same types
@@ -648,7 +661,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
 		h.Helper()
 	}
 
-	if value != true {
+	if !value {
 		return Fail(t, "Should be true", msgAndArgs...)
 	}
 
@@ -664,7 +677,7 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
 		h.Helper()
 	}
 
-	if value != false {
+	if value {
 		return Fail(t, "Should be false", msgAndArgs...)
 	}
 
@@ -747,10 +760,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
 
 	ok, found := includeElement(s, contains)
 	if !ok {
-		return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+		return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
 	}
 	if !found {
-		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
+		return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
 	}
 
 	return true
@@ -881,27 +894,39 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
 		return true
 	}
 
-	aKind := reflect.TypeOf(listA).Kind()
-	bKind := reflect.TypeOf(listB).Kind()
+	if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) {
+		return false
+	}
+
+	extraA, extraB := diffLists(listA, listB)
 
-	if aKind != reflect.Array && aKind != reflect.Slice {
-		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...)
+	if len(extraA) == 0 && len(extraB) == 0 {
+		return true
 	}
 
-	if bKind != reflect.Array && bKind != reflect.Slice {
-		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...)
+	return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...)
+}
+
+// isList checks that the provided value is array or slice.
+func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) {
+	kind := reflect.TypeOf(list).Kind()
+	if kind != reflect.Array && kind != reflect.Slice {
+		return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind),
+			msgAndArgs...)
 	}
+	return true
+}
 
+// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
+// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
+// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
+func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
 	aValue := reflect.ValueOf(listA)
 	bValue := reflect.ValueOf(listB)
 
 	aLen := aValue.Len()
 	bLen := bValue.Len()
 
-	if aLen != bLen {
-		return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...)
-	}
-
 	// Mark indexes in bValue that we already used
 	visited := make([]bool, bLen)
 	for i := 0; i < aLen; i++ {
@@ -918,11 +943,38 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
 			}
 		}
 		if !found {
-			return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...)
+			extraA = append(extraA, element)
 		}
 	}
 
-	return true
+	for j := 0; j < bLen; j++ {
+		if visited[j] {
+			continue
+		}
+		extraB = append(extraB, bValue.Index(j).Interface())
+	}
+
+	return
+}
+
+func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string {
+	var msg bytes.Buffer
+
+	msg.WriteString("elements differ")
+	if len(extraA) > 0 {
+		msg.WriteString("\n\nextra elements in list A:\n")
+		msg.WriteString(spewConfig.Sdump(extraA))
+	}
+	if len(extraB) > 0 {
+		msg.WriteString("\n\nextra elements in list B:\n")
+		msg.WriteString(spewConfig.Sdump(extraB))
+	}
+	msg.WriteString("\n\nlistA:\n")
+	msg.WriteString(spewConfig.Sdump(listA))
+	msg.WriteString("\n\nlistB:\n")
+	msg.WriteString(spewConfig.Sdump(listB))
+
+	return msg.String()
 }
 
 // Condition uses a Comparison to assert a complex condition.
@@ -1079,7 +1131,7 @@ func toFloat(x interface{}) (float64, bool) {
 	case float32:
 		xf = float64(xn)
 	case float64:
-		xf = float64(xn)
+		xf = xn
 	case time.Duration:
 		xf = float64(xn)
 	default:
@@ -1193,6 +1245,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
 	if !aok {
 		return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
 	}
+	if math.IsNaN(af) {
+		return 0, errors.New("expected value must not be NaN")
+	}
 	if af == 0 {
 		return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
 	}
@@ -1200,6 +1255,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
 	if !bok {
 		return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
 	}
+	if math.IsNaN(bf) {
+		return 0, errors.New("actual value must not be NaN")
+	}
 
 	return math.Abs(af-bf) / math.Abs(af), nil
 }
@@ -1209,6 +1267,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
 	if h, ok := t.(tHelper); ok {
 		h.Helper()
 	}
+	if math.IsNaN(epsilon) {
+		return Fail(t, "epsilon must not be NaN")
+	}
 	actualEpsilon, err := calcRelativeError(expected, actual)
 	if err != nil {
 		return Fail(t, err.Error(), msgAndArgs...)
@@ -1553,6 +1614,7 @@ var spewConfig = spew.ConfigState{
 	DisablePointerAddresses: true,
 	DisableCapacities:       true,
 	SortKeys:                true,
+	DisableMethods:          true,
 }
 
 type tHelper interface {
diff --git a/assert/http_assertions.go b/assert/http_assertions.go
index df46fa7..4ed341d 100644
--- a/assert/http_assertions.go
+++ b/assert/http_assertions.go
@@ -33,7 +33,6 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
 	code, err := httpCode(handler, method, url, values)
 	if err != nil {
 		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
-		return false
 	}
 
 	isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
@@ -56,7 +55,6 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
 	code, err := httpCode(handler, method, url, values)
 	if err != nil {
 		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
-		return false
 	}
 
 	isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
@@ -79,7 +77,6 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
 	code, err := httpCode(handler, method, url, values)
 	if err != nil {
 		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
-		return false
 	}
 
 	isErrorCode := code >= http.StatusBadRequest
@@ -90,6 +87,28 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
 	return isErrorCode
 }
 
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+//  assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	code, err := httpCode(handler, method, url, values)
+	if err != nil {
+		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+	}
+
+	successful := code == statuscode
+	if !successful {
+		Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
+	}
+
+	return successful
+}
+
 // 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, method, url string, values url.Values) string {
diff --git a/mock/mock.go b/mock/mock.go
index b5288af..30fcf3d 100644
--- a/mock/mock.go
+++ b/mock/mock.go
@@ -147,10 +147,10 @@ func (c *Call) After(d time.Duration) *Call {
 }
 
 // Run sets a handler to be called before returning. It can be used when
-// mocking a method such as unmarshalers that takes a pointer to a struct and
+// mocking a method (such as an unmarshaler) that takes a pointer to a struct and
 // sets properties in such struct
 //
-//    Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) {
+//    Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) {
 //    	arg := args.Get(0).(*map[string]interface{})
 //    	arg["foo"] = "bar"
 //    })
@@ -527,6 +527,45 @@ func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...inter
 	return true
 }
 
+// IsMethodCallable checking that the method can be called
+// If the method was called more than `Repeatability` return false
+func (m *Mock) IsMethodCallable(t TestingT, methodName string, arguments ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	m.mutex.Lock()
+	defer m.mutex.Unlock()
+
+	for _, v := range m.ExpectedCalls {
+		if v.Method != methodName {
+			continue
+		}
+		if len(arguments) != len(v.Arguments) {
+			continue
+		}
+		if v.Repeatability < v.totalCalls {
+			continue
+		}
+		if isArgsEqual(v.Arguments, arguments) {
+			return true
+		}
+	}
+	return false
+}
+
+// isArgsEqual compares arguments
+func isArgsEqual(expected Arguments, args []interface{}) bool {
+	if len(expected) != len(args) {
+		return false
+	}
+	for i, v := range args {
+		if !reflect.DeepEqual(expected[i], v) {
+			return false
+		}
+	}
+	return true
+}
+
 func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
 	for _, call := range m.calls() {
 		if call.Method == methodName {
@@ -578,6 +617,23 @@ func AnythingOfType(t string) AnythingOfTypeArgument {
 	return AnythingOfTypeArgument(t)
 }
 
+// IsTypeArgument is a struct that contains the type of an argument
+// for use when type checking.  This is an alternative to AnythingOfType.
+// Used in Diff and Assert.
+type IsTypeArgument struct {
+	t interface{}
+}
+
+// IsType returns an IsTypeArgument object containing the type to check for.
+// You can provide a zero-value of the type to check.  This is an
+// alternative to AnythingOfType.  Used in Diff and Assert.
+//
+// For example:
+// Assert(t, IsType(""), IsType(0))
+func IsType(t interface{}) *IsTypeArgument {
+	return &IsTypeArgument{t: t}
+}
+
 // argumentMatcher performs custom argument matching, returning whether or
 // not the argument is matched by the expectation fixture function.
 type argumentMatcher struct {
@@ -711,6 +767,12 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
 				output = fmt.Sprintf("%s\t%d: FAIL:  type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
 			}
 
+		} else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) {
+			t := expected.(*IsTypeArgument).t
+			if reflect.TypeOf(t) != reflect.TypeOf(actual) {
+				differences++
+				output = fmt.Sprintf("%s\t%d: FAIL:  type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt)
+			}
 		} else {
 
 			// normal checking
@@ -768,7 +830,7 @@ func (args Arguments) String(indexOrNil ...int) string {
 		// normal String() method - return a string representation of the args
 		var argsStr []string
 		for _, arg := range args {
-			argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg)))
+			argsStr = append(argsStr, reflect.TypeOf(arg).String())
 		}
 		return strings.Join(argsStr, ",")
 	} else if len(indexOrNil) == 1 {
diff --git a/require/require.go b/require/require.go
index cf6c7b5..22784c1 100644
--- a/require/require.go
+++ b/require/require.go
@@ -606,6 +606,36 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
 	t.FailNow()
 }
 
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+//  assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+//  assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // HTTPSuccess asserts that a specified handler returns a success status code.
 //
 //  assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
diff --git a/require/require_forward.go b/require/require_forward.go
index 5aac226..b556d5d 100644
--- a/require/require_forward.go
+++ b/require/require_forward.go
@@ -480,6 +480,30 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
 	HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
 }
 
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+//  a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+//  a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
+}
+
 // HTTPSuccess asserts that a specified handler returns a success status code.
 //
 //  a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
diff --git a/suite/interfaces.go b/suite/interfaces.go
index b55db43..8b98a8a 100644
--- a/suite/interfaces.go
+++ b/suite/interfaces.go
@@ -1,10 +1,12 @@
 package suite
 
+import "testing"
+
 // TestingSuite can store and return the current *testing.T context
 // generated by 'go test'.
 type TestingSuite interface {
-	T() TestingT
-	SetT(TestingT)
+	T() *testing.T
+	SetT(*testing.T)
 }
 
 // SetupAllSuite has a SetupSuite method, which will run before the
@@ -42,3 +44,10 @@ type BeforeTest interface {
 type AfterTest interface {
 	AfterTest(suiteName, testName string)
 }
+
+// WithStats implements HandleStats, a function that will be executed
+// when a test suite is finished. The stats contain information about
+// the execution of that suite and its tests.
+type WithStats interface {
+	HandleStats(suiteName string, stats *SuiteInformation)
+}
diff --git a/suite/stats.go b/suite/stats.go
new file mode 100644
index 0000000..261da37
--- /dev/null
+++ b/suite/stats.go
@@ -0,0 +1,46 @@
+package suite
+
+import "time"
+
+// SuiteInformation stats stores stats for the whole suite execution.
+type SuiteInformation struct {
+	Start, End time.Time
+	TestStats  map[string]*TestInformation
+}
+
+// TestInformation stores information about the execution of each test.
+type TestInformation struct {
+	TestName   string
+	Start, End time.Time
+	Passed     bool
+}
+
+func newSuiteInformation() *SuiteInformation {
+	testStats := make(map[string]*TestInformation)
+
+	return &SuiteInformation{
+		TestStats: testStats,
+	}
+}
+
+func (s SuiteInformation) start(testName string) {
+	s.TestStats[testName] = &TestInformation{
+		TestName: testName,
+		Start:    time.Now(),
+	}
+}
+
+func (s SuiteInformation) end(testName string, passed bool) {
+	s.TestStats[testName].End = time.Now()
+	s.TestStats[testName].Passed = passed
+}
+
+func (s SuiteInformation) Passed() bool {
+	for _, stats := range s.TestStats {
+		if !stats.Passed {
+			return false
+		}
+	}
+
+	return true
+}
diff --git a/suite/suite.go b/suite/suite.go
index 6e54781..cdaf9a9 100644
--- a/suite/suite.go
+++ b/suite/suite.go
@@ -9,6 +9,7 @@ import (
 	"runtime/debug"
 	"sync"
 	"testing"
+	"time"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -17,29 +18,21 @@ import (
 var allTestsFilter = func(_, _ string) (bool, error) { return true, nil }
 var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run")
 
-type TestingT interface {
-	Run(name string, f func(t *testing.T)) bool
-	Errorf(format string, args ...interface{})
-	FailNow()
-	Log(args ...interface{})
-	Skip(args ...interface{})
-}
-
 // Suite is a basic testing suite with methods for storing and
 // retrieving the current *testing.T context.
 type Suite struct {
 	*assert.Assertions
 	require *require.Assertions
-	t       TestingT
+	t       *testing.T
 }
 
 // T retrieves the current *testing.T context.
-func (suite *Suite) T() TestingT {
+func (suite *Suite) T() *testing.T {
 	return suite.t
 }
 
 // SetT sets the current *testing.T context.
-func (suite *Suite) SetT(t TestingT) {
+func (suite *Suite) SetT(t *testing.T) {
 	suite.t = t
 	suite.Assertions = assert.New(t)
 	suite.require = require.New(t)
@@ -95,6 +88,12 @@ func Run(t *testing.T, suite TestingSuite) {
 
 	suiteSetupDone := false
 
+	var stats *SuiteInformation
+
+	if _, ok := suite.(WithStats); ok {
+		stats = newSuiteInformation()
+	}
+
 	methodFinder := reflect.TypeOf(suite)
 	tests := []testing.InternalTest{}
 	for index := 0; index < methodFinder.NumMethod(); index++ {
@@ -104,21 +103,36 @@ func Run(t *testing.T, suite TestingSuite) {
 			fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
 			os.Exit(1)
 		}
+
 		if !ok {
 			continue
 		}
+
+		suiteName := methodFinder.Elem().Name()
+
 		if !suiteSetupDone {
+			if stats != nil {
+				stats.Start = time.Now()
+			}
+
 			if setupAllSuite, ok := suite.(SetupAllSuite); ok {
 				setupAllSuite.SetupSuite()
 			}
+
 			defer func() {
 				if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
 					testsSync.Wait()
 					tearDownAllSuite.TearDownSuite()
 				}
+
+				if suiteWithStats, measureStats := suite.(WithStats); measureStats {
+					stats.End = time.Now()
+					suiteWithStats.HandleStats(suiteName, stats)
+				}
 			}()
 			suiteSetupDone = true
 		}
+
 		test := testing.InternalTest{
 			Name: method.Name,
 			F: func(t *testing.T) {
@@ -130,16 +144,29 @@ func Run(t *testing.T, suite TestingSuite) {
 				if setupTestSuite, ok := suite.(SetupTestSuite); ok {
 					setupTestSuite.SetupTest()
 				}
+
 				if beforeTestSuite, ok := suite.(BeforeTest); ok {
 					beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
 				}
+
+				if stats != nil {
+					stats.start(method.Name)
+				}
+
 				defer func() {
+					if stats != nil {
+						passed := !t.Failed()
+						stats.end(method.Name, passed)
+					}
+
 					if afterTestSuite, ok := suite.(AfterTest); ok {
-						afterTestSuite.AfterTest(methodFinder.Elem().Name(), method.Name)
+						afterTestSuite.AfterTest(suiteName, method.Name)
 					}
+
 					if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
 						tearDownTestSuite.TearDownTest()
 					}
+
 					suite.SetT(parentT)
 				}()
 				method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})


Test patch:
diff --git a/assert/assertion_order_test.go b/assert/assertion_compare_test.go
similarity index 53%
rename from assert/assertion_order_test.go
rename to assert/assertion_compare_test.go
index 4dd897a..daf9bea 100644
--- a/assert/assertion_order_test.go
+++ b/assert/assertion_compare_test.go
@@ -29,7 +29,7 @@ func TestCompare(t *testing.T) {
 			t.Error("object should be comparable for type " + currCase.cType)
 		}
 
-		if resLess != 1 {
+		if resLess != compareLess {
 			t.Errorf("object less should be less than greater for type " + currCase.cType)
 		}
 
@@ -38,7 +38,7 @@ func TestCompare(t *testing.T) {
 			t.Error("object are comparable for type " + currCase.cType)
 		}
 
-		if resGreater != -1 {
+		if resGreater != compareGreater {
 			t.Errorf("object greater should be greater than less for type " + currCase.cType)
 		}
 
@@ -116,3 +116,76 @@ func TestLessOrEqual(t *testing.T) {
 		t.Error("Greater should return false")
 	}
 }
+
+func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) {
+	mockT := new(testing.T)
+
+	for _, currCase := range []struct {
+		v1            interface{}
+		v2            interface{}
+		compareResult bool
+	}{
+		{v1: 123, v2: "abc"},
+		{v1: "abc", v2: 123456},
+		{v1: float64(12), v2: "123"},
+		{v1: "float(12)", v2: float64(1)},
+	} {
+		compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
+		False(t, compareResult)
+	}
+}
+
+func Test_compareTwoValuesNotComparableValues(t *testing.T) {
+	mockT := new(testing.T)
+
+	type CompareStruct struct {
+	}
+
+	for _, currCase := range []struct {
+		v1 interface{}
+		v2 interface{}
+	}{
+		{v1: CompareStruct{}, v2: CompareStruct{}},
+		{v1: map[string]int{}, v2: map[string]int{}},
+		{v1: make([]int, 5, 5), v2: make([]int, 5, 5)},
+	} {
+		compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage")
+		False(t, compareResult)
+	}
+}
+
+func Test_compareTwoValuesCorrectCompareResult(t *testing.T) {
+	mockT := new(testing.T)
+
+	for _, currCase := range []struct {
+		v1           interface{}
+		v2           interface{}
+		compareTypes []CompareType
+	}{
+		{v1: 1, v2: 2, compareTypes: []CompareType{compareLess}},
+		{v1: 1, v2: 2, compareTypes: []CompareType{compareLess, compareEqual}},
+		{v1: 2, v2: 2, compareTypes: []CompareType{compareGreater, compareEqual}},
+		{v1: 2, v2: 2, compareTypes: []CompareType{compareEqual}},
+		{v1: 2, v2: 1, compareTypes: []CompareType{compareEqual, compareGreater}},
+		{v1: 2, v2: 1, compareTypes: []CompareType{compareGreater}},
+	} {
+		compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.compareTypes, "testFailMessage")
+		True(t, compareResult)
+	}
+}
+
+func Test_containsValue(t *testing.T) {
+	for _, currCase := range []struct {
+		values []CompareType
+		value  CompareType
+		result bool
+	}{
+		{values: []CompareType{compareGreater}, value: compareGreater, result: true},
+		{values: []CompareType{compareGreater, compareLess}, value: compareGreater, result: true},
+		{values: []CompareType{compareGreater, compareLess}, value: compareLess, result: true},
+		{values: []CompareType{compareGreater, compareLess}, value: compareEqual, result: false},
+	} {
+		compareResult := containsValue(currCase.values, currCase.value)
+		Equal(t, currCase.result, compareResult)
+	}
+}
diff --git a/assert/assertions_test.go b/assert/assertions_test.go
index 35a643e..042cf68 100644
--- a/assert/assertions_test.go
+++ b/assert/assertions_test.go
@@ -1,6 +1,7 @@
 package assert
 
 import (
+	"bufio"
 	"bytes"
 	"encoding/json"
 	"errors"
@@ -73,11 +74,11 @@ var (
 		[1]interface{}{1},
 		[]interface{}{},
 		struct{ x int }{1},
-		(*interface{})(&i),
-		(func())(func() {}),
+		(&i),
+		(func() {}),
 		interface{}(1),
 		map[interface{}]interface{}{},
-		(chan interface{})(make(chan interface{})),
+		(make(chan interface{})),
 		(<-chan interface{})(make(chan interface{})),
 		(chan<- interface{})(make(chan interface{})),
 	}
@@ -591,6 +592,18 @@ func TestContains(t *testing.T) {
 	}
 }
 
+func TestContainsFailMessage(t *testing.T) {
+
+	mockT := new(mockTestingT)
+
+	Contains(mockT, "Hello World", errors.New("Hello"))
+	expectedFail := "\"Hello World\" does not contain &errors.errorString{s:\"Hello\"}"
+	actualFail := mockT.errorString()
+	if !strings.Contains(actualFail, expectedFail) {
+		t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail)
+	}
+}
+
 func TestNotContains(t *testing.T) {
 
 	mockT := new(testing.T)
@@ -788,6 +801,90 @@ func TestElementsMatch(t *testing.T) {
 	}
 }
 
+func TestDiffLists(t *testing.T) {
+	tests := []struct {
+		name   string
+		listA  interface{}
+		listB  interface{}
+		extraA []interface{}
+		extraB []interface{}
+	}{
+		{
+			name:   "equal empty",
+			listA:  []string{},
+			listB:  []string{},
+			extraA: nil,
+			extraB: nil,
+		},
+		{
+			name:   "equal same order",
+			listA:  []string{"hello", "world"},
+			listB:  []string{"hello", "world"},
+			extraA: nil,
+			extraB: nil,
+		},
+		{
+			name:   "equal different order",
+			listA:  []string{"hello", "world"},
+			listB:  []string{"world", "hello"},
+			extraA: nil,
+			extraB: nil,
+		},
+		{
+			name:   "extra A",
+			listA:  []string{"hello", "hello", "world"},
+			listB:  []string{"hello", "world"},
+			extraA: []interface{}{"hello"},
+			extraB: nil,
+		},
+		{
+			name:   "extra A twice",
+			listA:  []string{"hello", "hello", "hello", "world"},
+			listB:  []string{"hello", "world"},
+			extraA: []interface{}{"hello", "hello"},
+			extraB: nil,
+		},
+		{
+			name:   "extra B",
+			listA:  []string{"hello", "world"},
+			listB:  []string{"hello", "hello", "world"},
+			extraA: nil,
+			extraB: []interface{}{"hello"},
+		},
+		{
+			name:   "extra B twice",
+			listA:  []string{"hello", "world"},
+			listB:  []string{"hello", "hello", "world", "hello"},
+			extraA: nil,
+			extraB: []interface{}{"hello", "hello"},
+		},
+		{
+			name:   "integers 1",
+			listA:  []int{1, 2, 3, 4, 5},
+			listB:  []int{5, 4, 3, 2, 1},
+			extraA: nil,
+			extraB: nil,
+		},
+		{
+			name:   "integers 2",
+			listA:  []int{1, 2, 1, 2, 1},
+			listB:  []int{2, 1, 2, 1, 2},
+			extraA: []interface{}{1},
+			extraB: []interface{}{2},
+		},
+	}
+	for _, test := range tests {
+		test := test
+		t.Run(test.name, func(t *testing.T) {
+			actualExtraA, actualExtraB := diffLists(test.listA, test.listB)
+			Equal(t, test.extraA, actualExtraA, "extra A does not match for listA=%v listB=%v",
+				test.listA, test.listB)
+			Equal(t, test.extraB, actualExtraB, "extra B does not match for listA=%v listB=%v",
+				test.listA, test.listB)
+		})
+	}
+}
+
 func TestCondition(t *testing.T) {
 	mockT := new(testing.T)
 
@@ -917,9 +1014,6 @@ func TestNoError(t *testing.T) {
 	// returning an empty error interface
 	err = func() error {
 		var err *customError
-		if err != nil {
-			t.Fatal("err should be nil here")
-		}
 		return err
 	}()
 
@@ -954,9 +1048,6 @@ func TestError(t *testing.T) {
 	// returning an empty error interface
 	err = func() error {
 		var err *customError
-		if err != nil {
-			t.Fatal("err should be nil here")
-		}
 		return err
 	}()
 
@@ -1025,7 +1116,6 @@ func TestEmpty(t *testing.T) {
 	type TString string
 	type TStruct struct {
 		x int
-		s []int
 	}
 
 	True(t, Empty(mockT, ""), "Empty string is empty")
@@ -1368,6 +1458,9 @@ func TestInEpsilon(t *testing.T) {
 		{0.1, -0.1, 1.99},
 		{0, 0.1, 2}, // expected must be different to zero
 		{time.Second, time.Second + 10*time.Millisecond, 0.002},
+		{math.NaN(), 0, 1},
+		{0, math.NaN(), 1},
+		{0, 0, math.NaN()},
 	}
 
 	for _, tc := range cases {
@@ -1750,6 +1843,15 @@ func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) {
 	False(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`))
 }
 
+type diffTestingStruct struct {
+	A string
+	B int
+}
+
+func (d *diffTestingStruct) String() string {
+	return d.A
+}
+
 func TestDiff(t *testing.T) {
 	expected := `
 
@@ -1829,6 +1931,42 @@ Diff:
 		map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7},
 	)
 	Equal(t, expected, actual)
+
+	expected = `
+
+Diff:
+--- Expected
++++ Actual
+@@ -1,3 +1,3 @@
+ (*errors.errorString)({
+- s: (string) (len=19) "some expected error"
++ s: (string) (len=12) "actual error"
+ })
+`
+
+	actual = diff(
+		errors.New("some expected error"),
+		errors.New("actual error"),
+	)
+	Equal(t, expected, actual)
+
+	expected = `
+
+Diff:
+--- Expected
++++ Actual
+@@ -2,3 +2,3 @@
+  A: (string) (len=11) "some string",
+- B: (int) 10
++ B: (int) 15
+ }
+`
+
+	actual = diff(
+		diffTestingStruct{A: "some string", B: 10},
+		diffTestingStruct{A: "some string", B: 15},
+	)
+	Equal(t, expected, actual)
 }
 
 func TestTimeEqualityErrorFormatting(t *testing.T) {
@@ -2159,7 +2297,7 @@ func TestEventuallyTrue(t *testing.T) {
 	state := 0
 	condition := func() bool {
 		defer func() {
-			state = state + 1
+			state += 1
 		}()
 		return state == 2
 	}
@@ -2210,3 +2348,18 @@ func Test_validateEqualArgs(t *testing.T) {
 		t.Error("nil functions are equal")
 	}
 }
+
+func Test_truncatingFormat(t *testing.T) {
+
+	original := strings.Repeat("a", bufio.MaxScanTokenSize-102)
+	result := truncatingFormat(original)
+	Equal(t, fmt.Sprintf("%#v", original), result, "string should not be truncated")
+
+	original = original + "x"
+	result = truncatingFormat(original)
+	NotEqual(t, fmt.Sprintf("%#v", original), result, "string should have been truncated.")
+
+	if !strings.HasSuffix(result, "<... truncated>") {
+		t.Error("truncated string should have <... truncated> suffix")
+	}
+}
diff --git a/assert/http_assertions_test.go b/assert/http_assertions_test.go
index 112beaf..991866a 100644
--- a/assert/http_assertions_test.go
+++ b/assert/http_assertions_test.go
@@ -19,6 +19,10 @@ func httpError(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusInternalServerError)
 }
 
+func httpStatusCode(w http.ResponseWriter, r *http.Request) {
+	w.WriteHeader(http.StatusSwitchingProtocols)
+}
+
 func TestHTTPSuccess(t *testing.T) {
 	assert := New(t)
 
@@ -33,6 +37,10 @@ func TestHTTPSuccess(t *testing.T) {
 	mockT3 := new(testing.T)
 	assert.Equal(HTTPSuccess(mockT3, httpError, "GET", "/", nil), false)
 	assert.True(mockT3.Failed())
+
+	mockT4 := new(testing.T)
+	assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false)
+	assert.True(mockT4.Failed())
 }
 
 func TestHTTPRedirect(t *testing.T) {
@@ -49,6 +57,10 @@ func TestHTTPRedirect(t *testing.T) {
 	mockT3 := new(testing.T)
 	assert.Equal(HTTPRedirect(mockT3, httpError, "GET", "/", nil), false)
 	assert.True(mockT3.Failed())
+
+	mockT4 := new(testing.T)
+	assert.Equal(HTTPRedirect(mockT4, httpStatusCode, "GET", "/", nil), false)
+	assert.True(mockT4.Failed())
 }
 
 func TestHTTPError(t *testing.T) {
@@ -65,6 +77,30 @@ func TestHTTPError(t *testing.T) {
 	mockT3 := new(testing.T)
 	assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true)
 	assert.False(mockT3.Failed())
+
+	mockT4 := new(testing.T)
+	assert.Equal(HTTPError(mockT4, httpStatusCode, "GET", "/", nil), false)
+	assert.True(mockT4.Failed())
+}
+
+func TestHTTPStatusCode(t *testing.T) {
+	assert := New(t)
+
+	mockT1 := new(testing.T)
+	assert.Equal(HTTPStatusCode(mockT1, httpOK, "GET", "/", nil, http.StatusSwitchingProtocols), false)
+	assert.True(mockT1.Failed())
+
+	mockT2 := new(testing.T)
+	assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false)
+	assert.True(mockT2.Failed())
+
+	mockT3 := new(testing.T)
+	assert.Equal(HTTPStatusCode(mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols), false)
+	assert.True(mockT3.Failed())
+
+	mockT4 := new(testing.T)
+	assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true)
+	assert.False(mockT4.Failed())
 }
 
 func TestHTTPStatusesWrapper(t *testing.T) {
diff --git a/http/test_response_writer.go b/http/test_response_writer.go
index 5c3f813..300a63b 100644
--- a/http/test_response_writer.go
+++ b/http/test_response_writer.go
@@ -36,7 +36,7 @@ func (rw *TestResponseWriter) Write(bytes []byte) (int, error) {
 	}
 
 	// add these bytes to the output string
-	rw.Output = rw.Output + string(bytes)
+	rw.Output += string(bytes)
 
 	// return normal values
 	return 0, nil
diff --git a/http/test_round_tripper.go b/http/test_round_tripper.go
index b1e32f1..11a024e 100644
--- a/http/test_round_tripper.go
+++ b/http/test_round_tripper.go
@@ -1,8 +1,9 @@
 package http
 
 import (
-	"github.com/stretchr/testify/mock"
 	"net/http"
+
+	"github.com/stretchr/testify/mock"
 )
 
 // TestRoundTripper DEPRECATED USE net/http/httptest
diff --git a/mock/mock_test.go b/mock/mock_test.go
index 4fea2fe..fcbc4f6 100644
--- a/mock/mock_test.go
+++ b/mock/mock_test.go
@@ -1143,6 +1143,41 @@ func Test_Mock_AssertNotCalled(t *testing.T) {
 
 }
 
+func Test_Mock_IsMethodCallable(t *testing.T) {
+	var mockedService = new(TestExampleImplementation)
+
+	arg := []Call{{Repeatability: 1}, {Repeatability: 2}}
+	arg2 := []Call{{Repeatability: 1}, {Repeatability: 1}}
+	arg3 := []Call{{Repeatability: 1}, {Repeatability: 1}}
+
+	mockedService.On("Test_Mock_IsMethodCallable", arg2).Return(true).Twice()
+
+	assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg))
+	assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2))
+	assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg3))
+
+	mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2)
+	mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2)
+
+	assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2))
+}
+
+func TestIsArgsEqual(t *testing.T) {
+	var expected = Arguments{5, 3, 4, 6, 7, 2}
+	var args = make([]interface{}, 5)
+	for i := 1; i < len(expected); i++ {
+		args[i-1] = expected[i]
+	}
+	args[2] = expected[1]
+	assert.False(t, isArgsEqual(expected, args))
+
+	var arr = make([]interface{}, 6)
+	for i := 0; i < len(expected); i++ {
+		arr[i] = expected[i]
+	}
+	assert.True(t, isArgsEqual(expected, arr))
+}
+
 func Test_Mock_AssertOptional(t *testing.T) {
 	// Optional called
 	var ms1 = new(TestExampleImplementation)
@@ -1257,6 +1292,24 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
 
 }
 
+func Test_Arguments_Diff_WithIsTypeArgument(t *testing.T) {
+	var args = Arguments([]interface{}{"string", IsType(0), true})
+	var count int
+	_, count = args.Diff([]interface{}{"string", 123, true})
+
+	assert.Equal(t, 0, count)
+}
+
+func Test_Arguments_Diff_WithIsTypeArgument_Failing(t *testing.T) {
+	var args = Arguments([]interface{}{"string", IsType(""), true})
+	var count int
+	var diff string
+	diff, count = args.Diff([]interface{}{"string", 123, true})
+
+	assert.Equal(t, 1, count)
+	assert.Contains(t, diff, `string != type int - (int=123)`)
+}
+
 func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
 	matchFn := func(a int) bool {
 		return a == 123
@@ -1272,6 +1325,7 @@ func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
 	assert.Contains(t, diff, `(bool=false) not matched by func(int) bool`)
 
 	diff, count = args.Diff([]interface{}{"string", 123, false})
+	assert.Equal(t, 1, count)
 	assert.Contains(t, diff, `(int=123) matched by func(int) bool`)
 
 	diff, count = args.Diff([]interface{}{"string", 123, true})
diff --git a/suite/stats_test.go b/suite/stats_test.go
new file mode 100644
index 0000000..4446a6d
--- /dev/null
+++ b/suite/stats_test.go
@@ -0,0 +1,29 @@
+package suite
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestPassedReturnsTrueWhenAllTestsPass(t *testing.T) {
+	sinfo := newSuiteInformation()
+	sinfo.TestStats = map[string]*TestInformation{
+		"Test1": {TestName: "Test1", Passed: true},
+		"Test2": {TestName: "Test2", Passed: true},
+		"Test3": {TestName: "Test3", Passed: true},
+	}
+
+	assert.True(t, sinfo.Passed())
+}
+
+func TestPassedReturnsFalseWhenSomeTestFails(t *testing.T) {
+	sinfo := newSuiteInformation()
+	sinfo.TestStats = map[string]*TestInformation{
+		"Test1": {TestName: "Test1", Passed: true},
+		"Test2": {TestName: "Test2", Passed: false},
+		"Test3": {TestName: "Test3", Passed: true},
+	}
+
+	assert.False(t, sinfo.Passed())
+}
diff --git a/suite/suite_test.go b/suite/suite_test.go
index 5d757dd..8b698a0 100644
--- a/suite/suite_test.go
+++ b/suite/suite_test.go
@@ -482,3 +482,33 @@ func (s *CallOrderSuite) Test_A() {
 func (s *CallOrderSuite) Test_B() {
 	s.call("Test B")
 }
+
+type suiteWithStats struct {
+	Suite
+	wasCalled bool
+	stats     *SuiteInformation
+}
+
+func (s *suiteWithStats) HandleStats(suiteName string, stats *SuiteInformation) {
+	s.wasCalled = true
+	s.stats = stats
+}
+
+func (s *suiteWithStats) TestSomething() {
+	s.Equal(1, 1)
+}
+
+func TestSuiteWithStats(t *testing.T) {
+	suiteWithStats := new(suiteWithStats)
+	Run(t, suiteWithStats)
+
+	assert.True(t, suiteWithStats.wasCalled)
+	assert.NotZero(t, suiteWithStats.stats.Start)
+	assert.NotZero(t, suiteWithStats.stats.End)
+	assert.True(t, suiteWithStats.stats.Passed())
+
+	testStats := suiteWithStats.stats.TestStats["TestSomething"]
+	assert.NotZero(t, testStats.Start)
+	assert.NotZero(t, testStats.End)
+	assert.True(t, testStats.Passed)
+}