Repository: stretchr/testify
Pull request #1349 (2023-02-17 00:56:24)

docs: Update URLs in README
## Summary
Update URLs in README to HTTPS and latest/updated URLs

## Changes
All `http://` URLs in the README have been updated

## Motivation
`http://` is insecure and older URLs required redirections to reach their final destinations.

<!-- ## Example usage (if applicable) -->

## Related issues
<!-- Put `Closes #XXXX` for each issue number this PR fixes/closes -->



Patch:
diff --git a/README.md b/README.md
index ce6d3de..b0d8cef 100644
--- a/README.md
+++ b/README.md
@@ -16,14 +16,14 @@ Features include:
 Get started:
 
   * Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date)
-  * For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing
-  * Check out the API Documentation http://godoc.org/github.com/stretchr/testify
-  * To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc)
-  * A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development)
+  * For an introduction to writing test code in Go, see https://go.dev/doc/code#Testing
+  * Check out the API Documentation https://pkg.go.dev/github.com/stretchr/testify
+  * To make your testing life easier, check out our other project, [gorc](https://github.com/stretchr/gorc)
+  * A little about [Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development)
 
 
 
-[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package
+[`assert`](https://pkg.go.dev/github.com/stretchr/testify/assert "API documentation") package
 -------------------------------------------------------------------------------------------
 
 The `assert` package provides some helpful methods that allow you to write better test code in Go.
@@ -100,14 +100,14 @@ func TestSomething(t *testing.T) {
 }
 ```
 
-[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package
+[`require`](https://pkg.go.dev/github.com/stretchr/testify/require "API documentation") package
 ---------------------------------------------------------------------------------------------
 
 The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test.
 
-See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details.
+See [t.FailNow](https://pkg.go.dev/testing#T.FailNow) for details.
 
-[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package
+[`mock`](https://pkg.go.dev/github.com/stretchr/testify/mock "API documentation") package
 ----------------------------------------------------------------------------------------
 
 The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code.
@@ -217,11 +217,11 @@ func TestSomethingElse2(t *testing.T) {
 }
 ```
 
-For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock).
+For more information on how to write mock code, check out the [API documentation for the `mock` package](https://pkg.go.dev/github.com/stretchr/testify/mock).
 
-You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker.
+You can use the [mockery tool](https://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker.
 
-[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package
+[`suite`](https://pkg.go.dev/github.com/stretchr/testify/suite "API documentation") package
 -----------------------------------------------------------------------------------------
 
 The `suite` package provides functionality that you might be used to from more common object oriented languages.  With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal.
@@ -265,7 +265,7 @@ func TestExampleTestSuite(t *testing.T) {
 
 For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go)
 
-For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite).
+For more information on writing suites, check out the [API documentation for the `suite` package](https://pkg.go.dev/github.com/stretchr/testify/suite).
 
 `Suite` object has assertion methods:
 
diff --git a/assert/assertions.go b/assert/assertions.go
index 2924cf3..c540bb0 100644
--- a/assert/assertions.go
+++ b/assert/assertions.go
@@ -816,44 +816,49 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
 		return true // we consider nil to be equal to the nil set
 	}
 
+	defer func() {
+		if e := recover(); e != nil {
+			ok = false
+		}
+	}()
+
 	listKind := reflect.TypeOf(list).Kind()
+	subsetKind := reflect.TypeOf(subset).Kind()
+
 	if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
 		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
 	}
 
-	subsetKind := reflect.TypeOf(subset).Kind()
 	if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
 		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
 	}
 
+	subsetValue := reflect.ValueOf(subset)
 	if subsetKind == reflect.Map && listKind == reflect.Map {
-		subsetMap := reflect.ValueOf(subset)
-		actualMap := reflect.ValueOf(list)
+		listValue := reflect.ValueOf(list)
+		subsetKeys := subsetValue.MapKeys()
 
-		for _, k := range subsetMap.MapKeys() {
-			ev := subsetMap.MapIndex(k)
-			av := actualMap.MapIndex(k)
+		for i := 0; i < len(subsetKeys); i++ {
+			subsetKey := subsetKeys[i]
+			subsetElement := subsetValue.MapIndex(subsetKey).Interface()
+			listElement := listValue.MapIndex(subsetKey).Interface()
 
-			if !av.IsValid() {
-				return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
-			}
-			if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
-				return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+			if !ObjectsAreEqual(subsetElement, listElement) {
+				return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...)
 			}
 		}
 
 		return true
 	}
 
-	subsetList := reflect.ValueOf(subset)
-	for i := 0; i < subsetList.Len(); i++ {
-		element := subsetList.Index(i).Interface()
+	for i := 0; i < subsetValue.Len(); i++ {
+		element := subsetValue.Index(i).Interface()
 		ok, found := containsElement(list, element)
 		if !ok {
-			return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
+			return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
 		}
 		if !found {
-			return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
+			return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...)
 		}
 	}
 
@@ -872,28 +877,34 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
 		return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
 	}
 
+	defer func() {
+		if e := recover(); e != nil {
+			ok = false
+		}
+	}()
+
 	listKind := reflect.TypeOf(list).Kind()
+	subsetKind := reflect.TypeOf(subset).Kind()
+
 	if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
 		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
 	}
 
-	subsetKind := reflect.TypeOf(subset).Kind()
 	if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
 		return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
 	}
 
+	subsetValue := reflect.ValueOf(subset)
 	if subsetKind == reflect.Map && listKind == reflect.Map {
-		subsetMap := reflect.ValueOf(subset)
-		actualMap := reflect.ValueOf(list)
+		listValue := reflect.ValueOf(list)
+		subsetKeys := subsetValue.MapKeys()
 
-		for _, k := range subsetMap.MapKeys() {
-			ev := subsetMap.MapIndex(k)
-			av := actualMap.MapIndex(k)
+		for i := 0; i < len(subsetKeys); i++ {
+			subsetKey := subsetKeys[i]
+			subsetElement := subsetValue.MapIndex(subsetKey).Interface()
+			listElement := listValue.MapIndex(subsetKey).Interface()
 
-			if !av.IsValid() {
-				return true
-			}
-			if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
+			if !ObjectsAreEqual(subsetElement, listElement) {
 				return true
 			}
 		}
@@ -901,9 +912,8 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
 		return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
 	}
 
-	subsetList := reflect.ValueOf(subset)
-	for i := 0; i < subsetList.Len(); i++ {
-		element := subsetList.Index(i).Interface()
+	for i := 0; i < subsetValue.Len(); i++ {
+		element := subsetValue.Index(i).Interface()
 		ok, found := containsElement(list, element)
 		if !ok {
 			return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)


Test patch:
diff --git a/assert/assertions_test.go b/assert/assertions_test.go
index cae11f8..b5193a5 100644
--- a/assert/assertions_test.go
+++ b/assert/assertions_test.go
@@ -672,18 +672,20 @@ func TestContainsNotContainsOnNilValue(t *testing.T) {
 }
 
 func TestSubsetNotSubset(t *testing.T) {
+
+	// MTestCase adds a custom message to the case
 	cases := []struct {
-		list    interface{}
-		subset  interface{}
-		result  bool
-		message string
+		expected interface{}
+		actual   interface{}
+		result   bool
+		message  string
 	}{
 		// cases that are expected to contain
-		{[]int{1, 2, 3}, nil, true, `nil is the empty set which is a subset of every set`},
-		{[]int{1, 2, 3}, []int{}, true, `[] is a subset of ['\x01' '\x02' '\x03']`},
-		{[]int{1, 2, 3}, []int{1, 2}, true, `['\x01' '\x02'] is a subset of ['\x01' '\x02' '\x03']`},
-		{[]int{1, 2, 3}, []int{1, 2, 3}, true, `['\x01' '\x02' '\x03'] is a subset of ['\x01' '\x02' '\x03']`},
-		{[]string{"hello", "world"}, []string{"hello"}, true, `["hello"] is a subset of ["hello" "world"]`},
+		{[]int{1, 2, 3}, nil, true, "given subset is nil"},
+		{[]int{1, 2, 3}, []int{}, true, "any set contains the nil set"},
+		{[]int{1, 2, 3}, []int{1, 2}, true, "[1, 2, 3] contains [1, 2]"},
+		{[]int{1, 2, 3}, []int{1, 2, 3}, true, "[1, 2, 3] contains [1, 2, 3"},
+		{[]string{"hello", "world"}, []string{"hello"}, true, "[\"hello\", \"world\"] contains [\"hello\"]"},
 		{map[string]string{
 			"a": "x",
 			"c": "z",
@@ -691,12 +693,12 @@ func TestSubsetNotSubset(t *testing.T) {
 		}, map[string]string{
 			"a": "x",
 			"b": "y",
-		}, true, `map["a":"x" "b":"y"] is a subset of map["a":"x" "b":"y" "c":"z"]`},
+		}, true, `{ "a": "x", "b": "y", "c": "z"} contains { "a": "x", "b": "y"}`},
 
 		// cases that are expected not to contain
-		{[]string{"hello", "world"}, []string{"hello", "testify"}, false, `[]string{"hello", "world"} does not contain "testify"`},
-		{[]int{1, 2, 3}, []int{4, 5}, false, `[]int{1, 2, 3} does not contain 4`},
-		{[]int{1, 2, 3}, []int{1, 5}, false, `[]int{1, 2, 3} does not contain 5`},
+		{[]string{"hello", "world"}, []string{"hello", "testify"}, false, "[\"hello\", \"world\"] does not contain [\"hello\", \"testify\"]"},
+		{[]int{1, 2, 3}, []int{4, 5}, false, "[1, 2, 3] does not contain [4, 5"},
+		{[]int{1, 2, 3}, []int{1, 5}, false, "[1, 2, 3] does not contain [1, 5]"},
 		{map[string]string{
 			"a": "x",
 			"c": "z",
@@ -704,51 +706,35 @@ func TestSubsetNotSubset(t *testing.T) {
 		}, map[string]string{
 			"a": "x",
 			"b": "z",
-		}, false, `map[string]string{"a":"x", "b":"y", "c":"z"} does not contain map[string]string{"a":"x", "b":"z"}`},
-		{map[string]string{
-			"a": "x",
-			"b": "y",
-		}, map[string]string{
-			"a": "x",
-			"b": "y",
-			"c": "z",
-		}, false, `map[string]string{"a":"x", "b":"y"} does not contain map[string]string{"a":"x", "b":"y", "c":"z"}`},
+		}, false, `{ "a": "x", "b": "y", "c": "z"} does not contain { "a": "x", "b": "z"}`},
 	}
 
 	for _, c := range cases {
 		t.Run("SubSet: "+c.message, func(t *testing.T) {
 
-			mockT := new(mockTestingT)
-			res := Subset(mockT, c.list, c.subset)
+			mockT := new(testing.T)
+			res := Subset(mockT, c.expected, c.actual)
 
 			if res != c.result {
-				t.Errorf("Subset should return %t: %s", c.result, c.message)
-			}
-			if !c.result {
-				expectedFail := c.message
-				actualFail := mockT.errorString()
-				if !strings.Contains(actualFail, expectedFail) {
-					t.Log(actualFail)
-					t.Errorf("Subset failure should contain %q but was %q", expectedFail, actualFail)
+				if res {
+					t.Errorf("Subset should return true: %s", c.message)
+				} else {
+					t.Errorf("Subset should return false: %s", c.message)
 				}
 			}
 		})
 	}
 	for _, c := range cases {
 		t.Run("NotSubSet: "+c.message, func(t *testing.T) {
-			mockT := new(mockTestingT)
-			res := NotSubset(mockT, c.list, c.subset)
+			mockT := new(testing.T)
+			res := NotSubset(mockT, c.expected, c.actual)
 
 			// NotSubset should match the inverse of Subset. If it doesn't, something is wrong
-			if res == Subset(mockT, c.list, c.subset) {
-				t.Errorf("NotSubset should return %t: %s", !c.result, c.message)
-			}
-			if c.result {
-				expectedFail := c.message
-				actualFail := mockT.errorString()
-				if !strings.Contains(actualFail, expectedFail) {
-					t.Log(actualFail)
-					t.Errorf("NotSubset failure should contain %q but was %q", expectedFail, actualFail)
+			if res == Subset(mockT, c.expected, c.actual) {
+				if res {
+					t.Errorf("NotSubset should return true: %s", c.message)
+				} else {
+					t.Errorf("NotSubset should return false: %s", c.message)
 				}
 			}
 		})