Repository: gavv/httpexpect
Pull request #213 (2022-12-26 14:52:18)

Added methods to enhance datetime class.
- New Methods for datetime class
- Added unit test

coveralls: 
[![Coverage Status](https://coveralls.io/builds/55461470/badge)](https://coveralls.io/builds/55461470)

Coverage: 95.312% (+0.06%) from 95.249% when pulling **f87d23f776148fa693f597c2c3def2fdbb951037 on kaviranjan88:master** into **6d1f40521fa8542241ead387ba9a62c6ffda955e on gavv:master**.

gavv: Hi, thanks for pr!

A couple of comments.
gavv: For each method, could you please add a short comment describing the return value?

For example, for Month we should mention the range of returned integer (is it 0-11 or 1-12).

You can base comments on comments from time.Time.
gavv: And another one. 

For the test, could you use a date-time which fields are all nonzero and all have different numeric values?

This is needed to be sure that the methods work properly. 

Patch:
diff --git a/.github/workflows/detect_conflicts.yml b/.github/workflows/detect_conflicts.yml
new file mode 100644
index 0000000..25e1198
--- /dev/null
+++ b/.github/workflows/detect_conflicts.yml
@@ -0,0 +1,20 @@
+name: "detect conflicts"
+
+on:
+  push:
+    branches:
+      - "*"
+    tags:
+      - "!*"
+  pull_request:
+    types: synchronize
+
+jobs:
+  main:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Run the action to detect unmergeable PRs
+        uses: cats-oss/github-action-detect-unmergeable@v2.1.1
+        env:
+          LABEL_NEED_REBASE: "needs rebase"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/remove_labels.yml b/.github/workflows/remove_labels.yml
new file mode 100644
index 0000000..905a37f
--- /dev/null
+++ b/.github/workflows/remove_labels.yml
@@ -0,0 +1,14 @@
+name: remove labels
+
+on:
+  pull_request:
+    types:
+      - closed
+
+jobs:
+  remove-labels:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: andymckay/labeler@master
+        with:
+          remove-labels: 'work in progress,ready for review,review in progress,needs revision'
diff --git a/_examples/go.mod b/_examples/go.mod
index 920e6c4..03d0a13 100644
--- a/_examples/go.mod
+++ b/_examples/go.mod
@@ -44,7 +44,7 @@ require (
 	github.com/kataras/golog v0.1.8 // indirect
 	github.com/kataras/pio v0.0.11 // indirect
 	github.com/kataras/sitemap v0.0.6 // indirect
-	github.com/klauspost/compress v1.15.13 // indirect
+	github.com/klauspost/compress v1.15.14 // indirect
 	github.com/labstack/gommon v0.4.0 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
@@ -73,9 +73,9 @@ require (
 	github.com/yudai/gojsondiff v1.0.0 // indirect
 	github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
 	golang.org/x/crypto v0.3.0 // indirect
-	golang.org/x/net v0.4.0 // indirect
-	golang.org/x/sys v0.3.0 // indirect
-	golang.org/x/text v0.5.0 // indirect
+	golang.org/x/net v0.5.0 // indirect
+	golang.org/x/sys v0.4.0 // indirect
+	golang.org/x/text v0.6.0 // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/_examples/go.sum b/_examples/go.sum
index 83d4f4a..cdc437a 100644
--- a/_examples/go.sum
+++ b/_examples/go.sum
@@ -131,8 +131,8 @@ github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
 github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
-github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0=
-github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
+github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc=
+github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
@@ -304,8 +304,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
-golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
+golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
+golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -335,20 +335,20 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
+golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
diff --git a/array.go b/array.go
index f044935..c3bad2b 100644
--- a/array.go
+++ b/array.go
@@ -219,7 +219,7 @@ func (a *Array) Iter() []Value {
 	ret := []Value{}
 	for n := range a.value {
 		valueChain := a.chain.clone()
-		valueChain.replace("Iter[%d]", n)
+		valueChain.replace("Iter[%v]", n)
 
 		ret = append(ret, *newValue(valueChain, a.value[n]))
 	}
@@ -263,7 +263,7 @@ func (a *Array) Every(fn func(index int, value *Value)) *Array {
 
 	for index, val := range a.value {
 		valueChain := a.chain.clone()
-		valueChain.replace("Every[%d]", index)
+		valueChain.replace("Every[%v]", index)
 
 		valueChain.setFailCallback(func() {
 			chainFailure = true
@@ -280,14 +280,14 @@ func (a *Array) Every(fn func(index int, value *Value)) *Array {
 }
 
 // Filter accepts a function that returns a boolean. The function is ran
-// over the array items. If the function returns true, the item passes
-// the filter and is added to the new array of filtered items. If false,
-// the item is skipped (or in other words filtered out). After iterating
-// through all the items of the original array, the new filtered array
+// over the array elements. If the function returns true, the element passes
+// the filter and is added to the new array of filtered elements. If false,
+// the element is skipped (or in other words filtered out). After iterating
+// through all the elements of the original array, the new filtered array
 // is returned.
 //
 // If there are any failed assertions in the filtering function, the
-// item is omitted without causing test failure.
+// element is omitted without causing test failure.
 //
 // Example:
 //
@@ -319,12 +319,15 @@ func (a *Array) Filter(fn func(index int, value *Value) bool) *Array {
 
 	for index, element := range a.value {
 		valueChain := a.chain.clone()
+		valueChain.replace("Filter[%v]", index)
+
 		valueChain.setSeverity(SeverityLog)
+
 		chainFailed := false
 		valueChain.setFailCallback(func() {
 			chainFailed = true
 		})
-		valueChain.replace("Filter[%v]", index)
+
 		if fn(index, newValue(valueChain, element)) && !chainFailed {
 			filteredArray = append(filteredArray, element)
 		}
@@ -372,6 +375,186 @@ func (a *Array) Transform(fn func(index int, value interface{}) interface{}) *Ar
 	return newArray(a.chain, array)
 }
 
+// Find accepts a function that returns a boolean, runs it over the array
+// elements, and returns the first element on which it returned true.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If no elements were found, a failure is reported.
+//
+// Example:
+//
+//	array := NewArray(t, []interface{}{1, "foo", 101, "bar", 201})
+//	foundValue := array.Find(func(index int, value *httpexpect.Value) bool {
+//		num := value.Number()    // skip if element is not a number
+//		return num.Raw() > 100   // check element value
+//	})
+//	foundValue.Equal(101) // succeeds
+func (a *Array) Find(fn func(index int, value *Value) bool) *Value {
+	a.chain.enter("Find()")
+	defer a.chain.leave()
+
+	if a.chain.failed() {
+		return newValue(a.chain, nil)
+	}
+
+	if fn == nil {
+		a.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return newValue(a.chain, nil)
+	}
+
+	for index, element := range a.value {
+		valueChain := a.chain.clone()
+		valueChain.replace("Find[%v]", index)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(index, newValue(valueChain, element)) && !chainFailed {
+			return newValue(a.chain, element)
+		}
+	}
+
+	a.chain.fail(AssertionFailure{
+		Type:   AssertValid,
+		Actual: &AssertionValue{a.value},
+		Errors: []error{
+			errors.New("expected: at least one array element matches predicate"),
+		},
+	})
+
+	return newValue(a.chain, nil)
+}
+
+// FindAll accepts a function that returns a boolean, runs it over the array
+// elements, and returns all the elements on which it returned true.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If no elements were found, empty slice is returned without reporting error.
+//
+// Example:
+//
+//	array := NewArray(t, []interface{}{1, "foo", 101, "bar", 201})
+//	foundValues := array.FindAll(func(index int, value *httpexpect.Value) bool {
+//		num := value.Number()   // skip if element is not a number
+//		return num.Raw() > 100  // check element value
+//	})
+//
+//	assert.Equal(t, len(foundValues), 2)
+//	foundValues[0].Equal(101)
+//	foundValues[1].Equal(201)
+func (a *Array) FindAll(fn func(index int, value *Value) bool) []Value {
+	a.chain.enter("FindAll()")
+	defer a.chain.leave()
+
+	if a.chain.failed() {
+		return []Value{}
+	}
+
+	if fn == nil {
+		a.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return []Value{}
+	}
+
+	foundValues := make([]Value, 0, len(a.value))
+	for index, element := range a.value {
+		valueChain := a.chain.clone()
+		valueChain.replace("FindAll[%v]", index)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(index, newValue(valueChain, element)) && !chainFailed {
+			foundValues = append(foundValues, *newValue(a.chain, element))
+		}
+	}
+
+	return foundValues
+}
+
+// NotFind accepts a function that returns a boolean, runs it over the array
+// elelements, and checks that it does not return true for any of the elements.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If the predicate function did not fail and returned true for at least
+// one element, a failure is reported.
+//
+// Example:
+//
+//	array := NewArray(t, []interface{}{1, "foo", 2, "bar"})
+//	array.NotFind(func(index int, value *httpexpect.Value) bool {
+//		num := value.Number()    // skip if element is not a number
+//		return num.Raw() > 100   // check element value
+//	}) // succeeds
+func (a *Array) NotFind(fn func(index int, value *Value) bool) *Array {
+	a.chain.enter("NotFind()")
+	defer a.chain.leave()
+
+	if a.chain.failed() {
+		return a
+	}
+
+	if fn == nil {
+		a.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return a
+	}
+
+	for index, element := range a.value {
+		valueChain := a.chain.clone()
+		valueChain.replace("NotFind[%v]", index)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(index, newValue(valueChain, element)) && !chainFailed {
+			a.chain.fail(AssertionFailure{
+				Type:     AssertNotContainsElement,
+				Expected: &AssertionValue{element},
+				Actual:   &AssertionValue{a.value},
+				Errors: []error{
+					errors.New("expected: none of the array elements match predicate"),
+					fmt.Errorf("element with index %d matches predicate", index),
+				},
+			})
+			return a
+		}
+	}
+
+	return a
+}
+
 // Empty succeeds if array is empty.
 //
 // Example:
diff --git a/datetime.go b/datetime.go
index 0bdbc88..091292e 100644
--- a/datetime.go
+++ b/datetime.go
@@ -283,3 +283,230 @@ func (dt *DateTime) NotInRange(min, max time.Time) *DateTime {
 
 	return dt
 }
+
+// Zone returns a new String instance with datetime zone.
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Zone().Equal("IST")
+func (dt *DateTime) Zone() *String {
+	dt.chain.enter("Zone()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newString(dt.chain, "")
+	}
+
+	zone, _ := dt.value.Zone()
+	return newString(dt.chain, zone)
+}
+
+// Year returns the year in which datetime occurs,
+// in the range [0, 9999]
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Year().Equal(2022)
+func (dt *DateTime) Year() *Number {
+	dt.chain.enter("Year()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Year()))
+}
+
+// Month returns the month of the year specified by datetime,
+// in the range [1,12].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Month().Equal(12)
+func (dt *DateTime) Month() *Number {
+	dt.chain.enter("Month()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Month()))
+}
+
+// Day returns the day of the month specified datetime,
+// in the range [1,31].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Day().Equal(30)
+func (dt *DateTime) Day() *Number {
+	dt.chain.enter("Day()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Day()))
+}
+
+// Weekday returns the day of the week specified by datetime,
+// in the range [0, 6], 0 corresponds to Sunday
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.WeekDay().Equal(time.Friday)
+func (dt *DateTime) WeekDay() *Number {
+	dt.chain.enter("WeekDay()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Weekday()))
+}
+
+// YearDay returns the day of the year specified by datetime,
+// in the range [1,365] for non-leap years,
+// and [1,366] in leap years.
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.YearDay().Equal(364)
+func (dt *DateTime) YearDay() *Number {
+	dt.chain.enter("YearDay()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.YearDay()))
+}
+
+// Hour returns the hour within the day specified by datetime,
+// in the range [0, 23].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Hour().Equal(15)
+func (dt *DateTime) Hour() *Number {
+	dt.chain.enter("Hour()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Hour()))
+}
+
+// Minute returns the minute offset within the hour specified by datetime,
+// in the range [0, 59].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Minute().Equal(4)
+func (dt *DateTime) Minute() *Number {
+	dt.chain.enter("Minute()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Minute()))
+}
+
+// Second returns the second offset within the minute specified by datetime,
+// in the range [0, 59].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Second().Equal(5)
+func (dt *DateTime) Second() *Number {
+	dt.chain.enter("Second()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Second()))
+}
+
+// Nanosecond returns the nanosecond offset within the second specified by datetime,
+// in the range [0, 999999999].
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.Nanosecond().Equal(0)
+func (dt *DateTime) Nanosecond() *Number {
+	dt.chain.enter("Nanosecond()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return newNumber(dt.chain, float64(0))
+	}
+
+	return newNumber(dt.chain, float64(dt.value.Nanosecond()))
+}
+
+// AsUTC returns a new DateTime instance in UTC timeZone.
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.AsUTC().Zone().Equal("UTC")
+func (dt *DateTime) AsUTC() *DateTime {
+	dt.chain.enter("AsUTC()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return dt
+	}
+
+	return newDateTime(dt.chain, dt.value.UTC())
+}
+
+// AsLocal returns a new DateTime instance in Local timeZone.
+//
+// Example:
+//
+//	tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
+//	dt := NewDateTime(t, tm)
+//	dt.AsLocal().Zone().Equal("IST")
+func (dt *DateTime) AsLocal() *DateTime {
+	dt.chain.enter("AsLocal()")
+	defer dt.chain.leave()
+
+	if dt.chain.failed() {
+		return dt
+	}
+
+	return newDateTime(dt.chain, dt.value.Local())
+}
diff --git a/formatter.go b/formatter.go
index b21c15c..e139816 100644
--- a/formatter.go
+++ b/formatter.go
@@ -63,10 +63,10 @@ type DefaultFormatter struct {
 // FormatSuccess implements Formatter.FormatSuccess.
 func (f *DefaultFormatter) FormatSuccess(ctx *AssertionContext) string {
 	if f.SuccessTemplate != "" {
-		return f.formatTemplate("SuccessTemplate",
+		return f.applyTemplate("SuccessTemplate",
 			f.SuccessTemplate, f.TemplateFuncs, ctx, nil)
 	} else {
-		return f.formatTemplate("SuccessTemplate",
+		return f.applyTemplate("SuccessTemplate",
 			defaultSuccessTemplate, defaultTemplateFuncs, ctx, nil)
 	}
 }
@@ -76,10 +76,10 @@ func (f *DefaultFormatter) FormatFailure(
 	ctx *AssertionContext, failure *AssertionFailure,
 ) string {
 	if f.FailureTemplate != "" {
-		return f.formatTemplate("FailureTemplate",
+		return f.applyTemplate("FailureTemplate",
 			f.FailureTemplate, f.TemplateFuncs, ctx, failure)
 	} else {
-		return f.formatTemplate("FailureTemplate",
+		return f.applyTemplate("FailureTemplate",
 			defaultFailureTemplate, defaultTemplateFuncs, ctx, failure)
 	}
 }
@@ -131,7 +131,7 @@ const (
 	kindValueList  = "values"
 )
 
-func (f *DefaultFormatter) formatTemplate(
+func (f *DefaultFormatter) applyTemplate(
 	templateName string,
 	templateString string,
 	templateFuncs template.FuncMap,
@@ -229,11 +229,11 @@ func (f *DefaultFormatter) fillActual(
 
 	case AssertType, AssertNotType:
 		data.HaveActual = true
-		data.Actual = formatTyped(failure.Actual.Value)
+		data.Actual = f.formatTyped(failure.Actual.Value)
 
 	default:
 		data.HaveActual = true
-		data.Actual = formatValue(failure.Actual.Value)
+		data.Actual = f.formatValue(failure.Actual.Value)
 	}
 }
 
@@ -253,11 +253,11 @@ func (f *DefaultFormatter) fillExpected(
 		data.HaveExpected = true
 		data.ExpectedKind = kindValue
 		data.Expected = []string{
-			formatValue(failure.Expected.Value),
+			f.formatValue(failure.Expected.Value),
 		}
 
 		if !f.DisableDiffs && failure.Actual != nil && failure.Expected != nil {
-			data.Diff, data.HaveDiff = formatDiff(
+			data.Diff, data.HaveDiff = f.formatDiff(
 				failure.Expected.Value, failure.Actual.Value)
 		}
 
@@ -265,33 +265,33 @@ func (f *DefaultFormatter) fillExpected(
 		data.HaveExpected = true
 		data.ExpectedKind = kindValue
 		data.Expected = []string{
-			formatValue(failure.Expected.Value),
+			f.formatValue(failure.Expected.Value),
 		}
 
 	case AssertInRange, AssertNotInRange:
 		data.HaveExpected = true
 		data.ExpectedKind = kindRange
-		data.Expected = formatRange(failure.Expected.Value)
+		data.Expected = f.formatRange(failure.Expected.Value)
 
 	case AssertMatchSchema, AssertNotMatchSchema:
 		data.HaveExpected = true
 		data.ExpectedKind = kindSchema
 		data.Expected = []string{
-			formatString(failure.Expected.Value),
+			f.formatBareString(failure.Expected.Value),
 		}
 
 	case AssertMatchPath, AssertNotMatchPath:
 		data.HaveExpected = true
 		data.ExpectedKind = kindPath
 		data.Expected = []string{
-			formatString(failure.Expected.Value),
+			f.formatBareString(failure.Expected.Value),
 		}
 
 	case AssertMatchRegexp, AssertNotMatchRegexp:
 		data.HaveExpected = true
 		data.ExpectedKind = kindRegexp
 		data.Expected = []string{
-			formatString(failure.Expected.Value),
+			f.formatBareString(failure.Expected.Value),
 		}
 
 	case AssertMatchFormat, AssertNotMatchFormat:
@@ -301,33 +301,33 @@ func (f *DefaultFormatter) fillExpected(
 		} else {
 			data.ExpectedKind = kindFormat
 		}
-		data.Expected = formatList(failure.Expected.Value)
+		data.Expected = f.formatList(failure.Expected.Value)
 
 	case AssertContainsKey, AssertNotContainsKey:
 		data.HaveExpected = true
 		data.ExpectedKind = kindKey
 		data.Expected = []string{
-			formatValue(failure.Expected.Value),
+			f.formatValue(failure.Expected.Value),
 		}
 
 	case AssertContainsElement, AssertNotContainsElement:
 		data.HaveExpected = true
 		data.ExpectedKind = kindElement
 		data.Expected = []string{
-			formatValue(failure.Expected.Value),
+			f.formatValue(failure.Expected.Value),
 		}
 
 	case AssertContainsSubset, AssertNotContainsSubset:
 		data.HaveExpected = true
 		data.ExpectedKind = kindSubset
 		data.Expected = []string{
-			formatValue(failure.Expected.Value),
+			f.formatValue(failure.Expected.Value),
 		}
 
 	case AssertBelongs, AssertNotBelongs:
 		data.HaveExpected = true
 		data.ExpectedKind = kindValueList
-		data.Expected = formatList(failure.Expected.Value)
+		data.Expected = f.formatList(failure.Expected.Value)
 	}
 }
 
@@ -384,21 +384,29 @@ func (f *DefaultFormatter) fillReference(
 	data *FormatData, ctx *AssertionContext, failure *AssertionFailure,
 ) {
 	data.HaveReference = true
-	data.Reference = formatValue(failure.Reference.Value)
+	data.Reference = f.formatValue(failure.Reference.Value)
 }
 
 func (f *DefaultFormatter) fillDelta(
 	data *FormatData, ctx *AssertionContext, failure *AssertionFailure,
 ) {
 	data.HaveDelta = true
-	data.Delta = formatFloat(failure.Delta.Value)
+	data.Delta = f.formatValue(failure.Delta.Value)
 }
 
-func formatTyped(value interface{}) string {
+func (f *DefaultFormatter) formatTyped(value interface{}) string {
+	if isNumber(value) {
+		return fmt.Sprintf("%T(%v)", value, f.formatValue(value))
+	}
+
 	return fmt.Sprintf("%T(%#v)", value, value)
 }
 
-func formatValue(value interface{}) string {
+func (f *DefaultFormatter) formatValue(value interface{}) string {
+	if isNumber(value) {
+		return fmt.Sprintf("%v", value)
+	}
+
 	if !isNil(value) && !isHTTP(value) {
 		if s, _ := value.(fmt.Stringer); s != nil {
 			if ss := s.String(); strings.TrimSpace(ss) != "" {
@@ -417,33 +425,20 @@ func formatValue(value interface{}) string {
 	return sq.Sdump(value)
 }
 
-func formatString(value interface{}) string {
+func (f *DefaultFormatter) formatBareString(value interface{}) string {
 	switch v := value.(type) {
 	case string:
 		return v
 	}
 
-	return formatValue(value)
-}
-
-func formatFloat(value interface{}) string {
-	switch value.(type) {
-	case float32, float64:
-		return fmt.Sprintf("%f", value)
-	}
-
-	if isNumber(value) {
-		return fmt.Sprintf("%v", value)
-	}
-
-	return formatValue(value)
+	return f.formatValue(value)
 }
 
-func formatRange(value interface{}) []string {
+func (f *DefaultFormatter) formatRange(value interface{}) []string {
 	if rng := exctractRange(value); rng != nil {
 		if isNumber(rng.Min) && isNumber(rng.Max) {
 			return []string{
-				fmt.Sprintf("[%v; %v]", rng.Min, rng.Max),
+				fmt.Sprintf("[%v; %v]", f.formatValue(rng.Min), f.formatValue(rng.Max)),
 			}
 		} else {
 			return []string{
@@ -453,26 +448,26 @@ func formatRange(value interface{}) []string {
 		}
 	} else {
 		return []string{
-			formatValue(value),
+			f.formatValue(value),
 		}
 	}
 }
 
-func formatList(value interface{}) []string {
+func (f *DefaultFormatter) formatList(value interface{}) []string {
 	if lst := extractList(value); lst != nil {
 		s := make([]string, 0, len(*lst))
 		for _, e := range *lst {
-			s = append(s, formatValue(e))
+			s = append(s, f.formatValue(e))
 		}
 		return s
 	} else {
 		return []string{
-			formatValue(value),
+			f.formatValue(value),
 		}
 	}
 }
 
-func formatDiff(expected, actual interface{}) (string, bool) {
+func (f *DefaultFormatter) formatDiff(expected, actual interface{}) (string, bool) {
 	differ := gojsondiff.New()
 
 	var diff gojsondiff.Diff
@@ -500,9 +495,9 @@ func formatDiff(expected, actual interface{}) (string, bool) {
 	config := formatter.AsciiFormatterConfig{
 		ShowArrayIndex: true,
 	}
-	f := formatter.NewAsciiFormatter(expected, config)
+	fa := formatter.NewAsciiFormatter(expected, config)
 
-	str, err := f.Format(diff)
+	str, err := fa.Format(diff)
 	if err != nil {
 		return "", false
 	}
diff --git a/go.mod b/go.mod
index 73c6bfe..014b30f 100644
--- a/go.mod
+++ b/go.mod
@@ -11,7 +11,7 @@ require (
 	github.com/imkira/go-interpol v1.1.0
 	github.com/mitchellh/go-wordwrap v1.0.1
 	github.com/sanity-io/litter v1.5.5
-	github.com/stretchr/testify v1.4.0
+	github.com/stretchr/testify v1.5.0
 	github.com/valyala/fasthttp v1.34.0
 	github.com/xeipuuv/gojsonschema v1.2.0
 	github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0
@@ -21,6 +21,7 @@ require (
 )
 
 require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
 	github.com/mattn/go-colorable v0.1.2 // indirect
 	github.com/onsi/ginkgo v1.10.1 // indirect
@@ -28,5 +29,5 @@ require (
 	github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
 	github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
 	github.com/yudai/pp v2.0.1+incompatible // indirect
-	gopkg.in/yaml.v2 v2.2.8 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
 )
diff --git a/go.sum b/go.sum
index f588cbc..782fb0b 100644
--- a/go.sum
+++ b/go.sum
@@ -4,8 +4,9 @@ github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu
 github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/fasthttp/websocket v1.4.3-rc.6 h1:omHqsl8j+KXpmzRjF8bmzOSYJ8GnS0E3efi1wYT+niY=
 github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CACNqNvCqQCoty/Lc=
 github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
@@ -55,8 +56,9 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.0 h1:DMOzIV76tmoDNE9pX6RSN0aDtCYeCg5VueieJaAo1uw=
+github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -135,7 +137,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
 moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
diff --git a/object.go b/object.go
index 863d39a..ab24e80 100644
--- a/object.go
+++ b/object.go
@@ -85,7 +85,7 @@ func (o *Object) Schema(schema interface{}) *Object {
 }
 
 // Keys returns a new Array instance with object's keys.
-// Keys are sorted.
+// Keys are sorted in ascending order.
 //
 // Example:
 //
@@ -100,19 +100,15 @@ func (o *Object) Keys() *Array {
 	}
 
 	keys := []interface{}{}
-	for k := range o.value {
-		keys = append(keys, k)
+	for _, kv := range o.sortedKV() {
+		keys = append(keys, kv.key)
 	}
 
-	sort.Slice(keys, func(i, j int) bool {
-		return keys[i].(string) < keys[j].(string)
-	})
-
 	return newArray(o.chain, keys)
 }
 
 // Values returns a new Array instance with object's values.
-// Values are sorted by keys.
+// Values are sorted by keys ascending order.
 //
 // Example:
 //
@@ -126,18 +122,9 @@ func (o *Object) Values() *Array {
 		return newArray(o.chain, nil)
 	}
 
-	keys := []string{}
-	for k := range o.value {
-		keys = append(keys, k)
-	}
-
-	sort.Slice(keys, func(i, j int) bool {
-		return keys[i] < keys[j]
-	})
-
 	values := []interface{}{}
-	for _, k := range keys {
-		values = append(values, o.value[k])
+	for _, kv := range o.sortedKV() {
+		values = append(values, kv.val)
 	}
 
 	return newArray(o.chain, values)
@@ -211,6 +198,8 @@ func (o *Object) Iter() map[string]Value {
 // Every will execute the function for all values in the object irrespective
 // of assertion failures for some values in the object.
 //
+// The function is invoked for key value pairs sorted by keys in ascending order.
+//
 // Example:
 //
 //	object := NewObject(t, map[string]interface{}{"foo": 123, "bar": 456})
@@ -238,16 +227,15 @@ func (o *Object) Every(fn func(key string, value *Value)) *Object {
 
 	chainFailure := false
 
-	for key, val := range o.value {
+	for _, kv := range o.sortedKV() {
 		valueChain := o.chain.clone()
-		valueChain.replace("Every[%q]", key)
+		valueChain.replace("Every[%q]", kv.key)
 
 		valueChain.setFailCallback(func() {
 			chainFailure = true
 		})
 
-		fn(key, newValue(valueChain, val))
-
+		fn(kv.key, newValue(valueChain, kv.val))
 	}
 
 	if chainFailure {
@@ -258,14 +246,16 @@ func (o *Object) Every(fn func(key string, value *Value)) *Object {
 }
 
 // Filter accepts a function that returns a boolean. The function is ran
-// over the object items. If the function returns true, the item passes
-// the filter and is added to the new object of filtered items. If false,
+// over the object elements. If the function returns true, the element passes
+// the filter and is added to the new object of filtered elements. If false,
 // the value is skipped (or in other words filtered out). After iterating
-// through all the items of the original object, the new filtered object
+// through all the elements of the original object, the new filtered object
 // is returned.
 //
 // If there are any failed assertions in the filtering function, the
-// item is omitted without causing test failure.
+// element is omitted without causing test failure.
+//
+// The function is invoked for key value pairs sorted by keys in ascending order.
 //
 // Example:
 //
@@ -299,16 +289,19 @@ func (o *Object) Filter(fn func(key string, value *Value) bool) *Object {
 
 	filteredObject := make(map[string]interface{})
 
-	for key, element := range o.value {
+	for _, kv := range o.sortedKV() {
 		valueChain := o.chain.clone()
+		valueChain.replace("Filter[%q]", kv.key)
+
 		valueChain.setSeverity(SeverityLog)
+
 		chainFailed := false
 		valueChain.setFailCallback(func() {
 			chainFailed = true
 		})
-		valueChain.replace("Filter[%q]", key)
-		if fn(key, newValue(valueChain, element)) && !chainFailed {
-			filteredObject[key] = element
+
+		if fn(kv.key, newValue(valueChain, kv.val)) && !chainFailed {
+			filteredObject[kv.key] = kv.val
 		}
 	}
 
@@ -318,6 +311,8 @@ func (o *Object) Filter(fn func(key string, value *Value) bool) *Object {
 // Transform runs the passed function on all the Elements in the Object
 // and returns a new object without effecting original object.
 //
+// The function is invoked for key value pairs sorted by keys in ascending order.
+//
 // Example:
 //
 //	object := NewObject(t, []interface{}{"x": "foo", "y": "bar"})
@@ -346,14 +341,218 @@ func (o *Object) Transform(fn func(key string, value interface{}) interface{}) *
 
 	object := map[string]interface{}{}
 
-	for key, val := range o.value {
-		transformedValue := fn(key, val)
-		object[key] = transformedValue
+	for _, kv := range o.sortedKV() {
+		transformedValue := fn(kv.key, kv.val)
+		object[kv.key] = transformedValue
 	}
 
 	return newObject(o.chain, object)
 }
 
+// Find accepts a function that returns a boolean, runs it over the object
+// elements, and returns the first element on which it returned true.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If no elements were found, a failure is reported.
+//
+// The function is invoked for key value pairs sorted by keys in ascending order.
+//
+// Example:
+//
+//	object := NewObject(t, map[string]interface{}{
+//		"a": 1,
+//		"b": "foo",
+//		"c": 101,
+//		"d": "bar",
+//		"e": 201,
+//	})
+//	foundValue := object.Find(func(key string, value *httpexpect.Value)  bool {
+//		num := value.Number()      // skip if element is not a string
+//		return num.Raw() > 100     // check element value
+//	})
+//	foundValue.Equal(101) // succeeds
+func (o *Object) Find(fn func(key string, value *Value) bool) *Value {
+	o.chain.enter("Find()")
+	defer o.chain.leave()
+
+	if o.chain.failed() {
+		return newValue(o.chain, nil)
+	}
+
+	if fn == nil {
+		o.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return newValue(o.chain, nil)
+	}
+
+	for _, kv := range o.sortedKV() {
+		valueChain := o.chain.clone()
+		valueChain.replace("Find[%q]", kv.key)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(kv.key, newValue(valueChain, kv.val)) && !chainFailed {
+			return newValue(o.chain, kv.val)
+		}
+	}
+
+	o.chain.fail(AssertionFailure{
+		Type:   AssertValid,
+		Actual: &AssertionValue{o.value},
+		Errors: []error{
+			errors.New("expected: at least one object element matches predicate"),
+		},
+	})
+
+	return newValue(o.chain, nil)
+}
+
+// FindAll accepts a function that returns a boolean, runs it over the object
+// elements, and returns all the elements on which it returned true.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If no elements were found, empty slice is returned without reporting error.
+//
+// The function is invoked for key value pairs sorted by keys in ascending order.
+//
+// Example:
+//
+//	object := NewObject(t, map[string]interface{}{
+//		"a": 1,
+//		"b": "foo",
+//		"c": 101,
+//		"d": "bar",
+//		"e": 201,
+//	})
+//	foundValues := object.FindAll(func(key string, value *httpexpect.Value)  bool {
+//		num := value.Number()      // skip if element is not a string
+//		return num.Raw() > 100     // check element value
+//	})
+//
+//	assert.Equal(t, len(foundValues), 2)
+//	foundValues[0].Equal(101)
+//	foundValues[1].Equal(201)
+func (o *Object) FindAll(fn func(key string, value *Value) bool) []Value {
+	o.chain.enter("FindAll()")
+	defer o.chain.leave()
+
+	if o.chain.failed() {
+		return []Value{}
+	}
+
+	if fn == nil {
+		o.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return []Value{}
+	}
+
+	foundValues := make([]Value, 0, len(o.value))
+
+	for _, kv := range o.sortedKV() {
+		valueChain := o.chain.clone()
+		valueChain.replace("FindAll[%q]", kv.key)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(kv.key, newValue(valueChain, kv.val)) && !chainFailed {
+			foundValues = append(foundValues, *newValue(o.chain, kv.val))
+		}
+	}
+
+	return foundValues
+}
+
+// NotFind accepts a function that returns a boolean, runs it over the object
+// elelements, and checks that it does not return true for any of the elements.
+//
+// If there are any failed assertions in the predicate function, the
+// element is skipped without causing test failure.
+//
+// If the predicate function did not fail and returned true for at least
+// one element, a failure is reported.
+//
+// The function is invoked for key value pairs sorted by keys in ascending order.
+//
+// Example:
+//
+//	object := NewObject(t, map[string]interface{}{
+//		"a": 1,
+//		"b": "foo",
+//		"c": 2,
+//		"d": "bar",
+//	})
+//	object.NotFind(func(key string, value *httpexpect.Value) bool {
+//		num := value.Number()    // skip if element is not a number
+//		return num.Raw() > 100   // check element value
+//	}) // succeeds
+func (o *Object) NotFind(fn func(key string, value *Value) bool) *Object {
+	o.chain.enter("NotFind()")
+	defer o.chain.leave()
+
+	if o.chain.failed() {
+		return o
+	}
+
+	if fn == nil {
+		o.chain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected nil function argument"),
+			},
+		})
+		return o
+	}
+
+	for _, kv := range o.sortedKV() {
+		valueChain := o.chain.clone()
+		valueChain.replace("NotFind[%q]", kv.key)
+
+		valueChain.setSeverity(SeverityLog)
+
+		chainFailed := false
+		valueChain.setFailCallback(func() {
+			chainFailed = true
+		})
+
+		if fn(kv.key, newValue(valueChain, kv.val)) && !chainFailed {
+			o.chain.fail(AssertionFailure{
+				Type:     AssertNotContainsElement,
+				Expected: &AssertionValue{kv.val},
+				Actual:   &AssertionValue{o.value},
+				Errors: []error{
+					errors.New("expected: none of the object elements match predicate"),
+					fmt.Errorf("element with key %q matches predicate", kv.key),
+				},
+			})
+			return o
+		}
+	}
+
+	return o
+}
+
 // Empty succeeds if object is empty.
 //
 // Example:
@@ -799,6 +998,20 @@ func (o *Object) ValueNotEqual(key string, value interface{}) *Object {
 	return o.NotValueEqual(key, value)
 }
 
+type kv struct {
+	key string
+	val interface{}
+}
+
+func (o *Object) sortedKV() []kv {
+	kvs := make([]kv, 0, len(o.value))
+	for key, val := range o.value {
+		kvs = append(kvs, kv{key: key, val: val})
+	}
+	sort.Slice(kvs, func(i, j int) bool { return kvs[i].key < kvs[j].key })
+	return kvs
+}
+
 func (o *Object) containsKey(arg string) bool {
 	for k := range o.value {
 		if k == arg {


Test patch:
diff --git a/array_test.go b/array_test.go
index 902844e..b7bdece 100644
--- a/array_test.go
+++ b/array_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestArrayFailed(t *testing.T) {
+func TestArray_Failed(t *testing.T) {
 	check := func(value *Array) {
 		value.chain.assertFailed(t)
 
@@ -47,6 +47,18 @@ func TestArrayFailed(t *testing.T) {
 		value.Transform(func(index int, value interface{}) interface{} {
 			return nil
 		})
+		value.Find(func(index int, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
+		value.FindAll(func(index int, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
+		value.NotFind(func(index int, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
 	}
 
 	t.Run("failed_chain", func(t *testing.T) {
@@ -76,7 +88,7 @@ func TestArrayFailed(t *testing.T) {
 	})
 }
 
-func TestArrayConstructors(t *testing.T) {
+func TestArray_Constructors(t *testing.T) {
 	testValue := []interface{}{"Foo", 123}
 
 	t.Run("Constructor without config", func(t *testing.T) {
@@ -94,9 +106,16 @@ func TestArrayConstructors(t *testing.T) {
 		value.Equal(testValue)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newArray(chain, testValue)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestArrayGetters(t *testing.T) {
+func TestArray_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	a := []interface{}{"foo", 123.0}
@@ -143,7 +162,7 @@ func TestArrayGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayEmpty(t *testing.T) {
+func TestArray_Empty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewArray(reporter, nil)
@@ -173,7 +192,7 @@ func TestArrayEmpty(t *testing.T) {
 	value3.chain.clearFailed()
 }
 
-func TestArrayEmptyGetters(t *testing.T) {
+func TestArray_EmptyGetters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{})
@@ -195,7 +214,7 @@ func TestArrayEmptyGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayEqualEmpty(t *testing.T) {
+func TestArray_EqualEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{})
@@ -219,7 +238,7 @@ func TestArrayEqualEmpty(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayEqualNotEmpty(t *testing.T) {
+func TestArray_EqualNotEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{"foo", "bar"})
@@ -259,7 +278,7 @@ func TestArrayEqualNotEmpty(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayEqualTypes(t *testing.T) {
+func TestArray_EqualTypes(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewArray(reporter, []interface{}{"foo", "bar"})
@@ -326,7 +345,7 @@ func TestArrayEqualTypes(t *testing.T) {
 	value3.chain.clearFailed()
 }
 
-func TestArrayEqualUnordered(t *testing.T) {
+func TestArray_EqualUnordered(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("without_duplicates", func(t *testing.T) {
@@ -410,7 +429,7 @@ func TestArrayEqualUnordered(t *testing.T) {
 	})
 }
 
-func TestArrayElements(t *testing.T) {
+func TestArray_Elements(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{123, "foo"})
@@ -436,7 +455,7 @@ func TestArrayElements(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayNotElements(t *testing.T) {
+func TestArray_NotElements(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{123, "foo"})
@@ -462,7 +481,7 @@ func TestArrayNotElements(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayContains(t *testing.T) {
+func TestArray_Contains(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{123, "foo"})
@@ -512,7 +531,7 @@ func TestArrayContains(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayContainsOnly(t *testing.T) {
+func TestArray_ContainsOnly(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("without_duplicates", func(t *testing.T) {
@@ -596,7 +615,7 @@ func TestArrayContainsOnly(t *testing.T) {
 	})
 }
 
-func TestArrayContainsAny(t *testing.T) {
+func TestArray_ContainsAny(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewArray(reporter, []interface{}{123, "foo"})
@@ -650,7 +669,7 @@ func TestArrayContainsAny(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayConvertEqual(t *testing.T) {
+func TestArray_ConvertEqual(t *testing.T) {
 	type (
 		myArray []interface{}
 		myInt   int
@@ -687,7 +706,7 @@ func TestArrayConvertEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayConvertElements(t *testing.T) {
+func TestArray_ConvertElements(t *testing.T) {
 	type (
 		myInt int
 	)
@@ -707,7 +726,7 @@ func TestArrayConvertElements(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayConvertContains(t *testing.T) {
+func TestArray_ConvertContains(t *testing.T) {
 	type (
 		myInt int
 	)
@@ -779,7 +798,7 @@ func TestArrayConvertContains(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestArrayEvery(t *testing.T) {
+func TestArray_Every(t *testing.T) {
 	t.Run("Check validation", func(ts *testing.T) {
 		reporter := newMockReporter(ts)
 		array := NewArray(reporter, []interface{}{2, 4, 6})
@@ -836,7 +855,7 @@ func TestArrayEvery(t *testing.T) {
 	})
 }
 
-func TestArrayTransform(t *testing.T) {
+func TestArray_Transform(t *testing.T) {
 	t.Run("Square Integers", func(ts *testing.T) {
 		reporter := newMockReporter(ts)
 		array := NewArray(reporter, []interface{}{2, 4, 6})
@@ -884,7 +903,7 @@ func TestArrayTransform(t *testing.T) {
 	})
 }
 
-func TestArrayFilter(t *testing.T) {
+func TestArray_Filter(t *testing.T) {
 	t.Run("Filter an array of elements of the same type and validate", func(ts *testing.T) {
 		reporter := newMockReporter(t)
 		array := NewArray(reporter, []interface{}{1, 2, 3, 4, 5, 6})
@@ -952,3 +971,322 @@ func TestArrayFilter(t *testing.T) {
 			filteredArray.chain.assertNotFailed(t)
 		})
 }
+
+func TestArray_Find(t *testing.T) {
+	t.Run("Elements of the same type", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, 2, 3, 4, 5, 6})
+		foundValue := array.Find(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+		assert.Equal(t, 2.0, foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0, 3.0, 4.0, 5.0, 6.0})
+
+		array.chain.assertNotFailed(t)
+		foundValue.chain.assertNotFailed(t)
+	})
+
+	t.Run("Elements of multiple types", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, "foo", true, "bar"})
+		foundValue := array.Find(func(index int, value *Value) bool {
+			stringifiedValue := value.String().NotEmpty().Raw()
+			return stringifiedValue == "bar"
+		})
+		assert.Equal(t, "bar", foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{1.0, "foo", true, "bar"})
+
+		array.chain.assertNotFailed(t)
+		foundValue.chain.assertNotFailed(t)
+	})
+
+	t.Run("First match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, "foo", true, "bar"})
+		foundValue := array.Find(func(index int, value *Value) bool {
+			stringifiedValue := value.String().Raw()
+			return stringifiedValue != ""
+		})
+		assert.Equal(t, "foo", foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{1.0, "foo", true, "bar"})
+
+		array.chain.assertNotFailed(t)
+		foundValue.chain.assertNotFailed(t)
+	})
+
+	t.Run("No match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, "foo", true, "bar"})
+		foundValue := array.Find(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{1.0, "foo", true, "bar"})
+
+		array.chain.assertFailed(t)
+		foundValue.chain.assertFailed(t)
+	})
+
+	t.Run("Empty array", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{})
+		foundValue := array.Find(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{})
+
+		array.chain.assertFailed(t)
+		foundValue.chain.assertFailed(t)
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			array := NewArray(reporter, []interface{}{1, 2})
+			foundValue := array.Find(func(index int, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Equal(t, nil, foundValue.Raw())
+			assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0})
+
+			array.chain.assertFailed(t)
+			foundValue.chain.assertFailed(t)
+		})
+
+	t.Run("Predicate returns true, assertion fails, have match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			array := NewArray(reporter, []interface{}{1, 2, "str"})
+			foundValue := array.Find(func(index int, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Equal(t, "str", foundValue.Raw())
+			assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0, "str"})
+
+			array.chain.assertNotFailed(t)
+			foundValue.chain.assertNotFailed(t)
+		})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, 2})
+		foundValue := array.Find(nil)
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0})
+
+		array.chain.assertFailed(t)
+		foundValue.chain.assertFailed(t)
+	})
+}
+
+func TestArray_FindAll(t *testing.T) {
+	t.Run("Elements of the same type", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, 2, 3, 4, 5, 6})
+		foundValues := array.FindAll(func(index int, value *Value) bool {
+			return value.Raw() == 2.0 || value.Raw() == 5.0
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{2.0, 5.0}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0, 3.0, 4.0, 5.0, 6.0})
+
+		array.chain.assertNotFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+	})
+
+	t.Run("Elements of multiple types", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1.0, "foo", true, "bar"})
+		foundValues := array.FindAll(func(index int, value *Value) bool {
+			stringifiedValue := value.String().Raw()
+			return stringifiedValue != ""
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+		assert.Equal(t, []interface{}{"foo", "bar"}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{1.0, "foo", true, "bar"})
+
+		array.chain.assertNotFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+	})
+
+	t.Run("No match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1.0, "foo", true, "bar"})
+		foundValues := array.FindAll(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{1.0, "foo", true, "bar"})
+
+		array.chain.assertNotFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+	})
+
+	t.Run("Empty array", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{})
+		foundValues := array.FindAll(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{})
+
+		array.chain.assertNotFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			array := NewArray(reporter, []interface{}{1, 2})
+			foundValues := array.FindAll(func(index int, value *Value) bool {
+				value.String()
+				return true
+			})
+
+			actual := []interface{}{}
+			for _, value := range foundValues {
+				actual = append(actual, value.Raw())
+			}
+			assert.Equal(t, []interface{}{}, actual)
+			assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0})
+
+			array.chain.assertNotFailed(t)
+			for _, value := range foundValues {
+				value.chain.assertNotFailed(t)
+			}
+		})
+
+	t.Run("Predicate returns true, assertion fails, have matches", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{"foo", 1, 2, "bar"})
+		foundValues := array.FindAll(func(index int, value *Value) bool {
+			value.String()
+			return true
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+		assert.Equal(t, []interface{}{"foo", "bar"}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{"foo", 1.0, 2.0, "bar"})
+
+		array.chain.assertNotFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+	})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, 2})
+		foundValues := array.FindAll(nil)
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, array.Raw(), []interface{}{1.0, 2.0})
+
+		array.chain.assertFailed(t)
+		for _, value := range foundValues {
+			value.chain.assertFailed(t)
+		}
+	})
+}
+
+func TestArray_NotFind(t *testing.T) {
+	t.Run("Succeeds if no element matches predicate", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, "foo", true, "bar"})
+		afterArray := array.NotFind(func(index int, value *Value) bool {
+			return value.String().Raw() == "baz"
+		})
+		assert.Same(t, array, afterArray)
+		array.chain.assertNotFailed(t)
+	})
+
+	t.Run("Fails if there is a match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, "foo", true, "bar"})
+		afterArray := array.NotFind(func(index int, value *Value) bool {
+			return value.String().NotEmpty().Raw() == "bar"
+		})
+		assert.Same(t, array, afterArray)
+		array.chain.assertFailed(t)
+	})
+
+	t.Run("Empty array", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{})
+		afterArray := array.NotFind(func(index int, value *Value) bool {
+			return value.Raw() == 2.0
+		})
+		assert.Same(t, array, afterArray)
+		array.chain.assertNotFailed(t)
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			array := NewArray(reporter, []interface{}{1, 2})
+			afterArray := array.NotFind(func(index int, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Same(t, array, afterArray)
+			array.chain.assertNotFailed(t)
+		})
+
+	t.Run("Predicate returns true, assertion fails, have match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			array := NewArray(reporter, []interface{}{1, 2, "str"})
+			afterArray := array.NotFind(func(index int, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Same(t, array, afterArray)
+			array.chain.assertFailed(t)
+		})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		array := NewArray(reporter, []interface{}{1, 2})
+		afterArray := array.NotFind(nil)
+		assert.Same(t, array, afterArray)
+		array.chain.assertFailed(t)
+	})
+}
diff --git a/assertion_test.go b/assertion_test.go
index 2573fe8..e36e7c5 100644
--- a/assertion_test.go
+++ b/assertion_test.go
@@ -8,7 +8,7 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestAssertionHandler(t *testing.T) {
+func TestAssertion_Handler(t *testing.T) {
 	type test struct {
 		formatter *mockFormatter
 		reporter  *mockReporter
@@ -141,7 +141,7 @@ func TestAssertionHandler(t *testing.T) {
 	})
 }
 
-func TestAssertionHandlerPanics(t *testing.T) {
+func TestAssertion_HandlerPanics(t *testing.T) {
 	t.Run("success_nil_Formatter", func(t *testing.T) {
 		handler := &DefaultAssertionHandler{
 			Formatter: nil,
@@ -195,7 +195,7 @@ func TestAssertionHandlerPanics(t *testing.T) {
 	})
 }
 
-func TestAssertionValidation(t *testing.T) {
+func TestAssertion_Validation(t *testing.T) {
 	tests := []struct {
 		testName          string
 		errorContainsText string
@@ -464,7 +464,7 @@ func TestAssertionValidation(t *testing.T) {
 	}
 }
 
-func TestAssertionStrings(t *testing.T) {
+func TestAssertion_Strings(t *testing.T) {
 	t.Run("AssertionType", func(t *testing.T) {
 		for i := 0; i < 100; i++ {
 			assert.NotEmpty(t, AssertionType(i).String())
diff --git a/binder_test.go b/binder_test.go
index 1c92497..ed35ca5 100644
--- a/binder_test.go
+++ b/binder_test.go
@@ -52,7 +52,7 @@ func (c *mockHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 	assert.True(c.t, err == nil)
 }
 
-func TestBinder(t *testing.T) {
+func TestBinder_Basic(t *testing.T) {
 	handler := &mockHandler{
 		t:       t,
 		http10:  true,
@@ -92,7 +92,7 @@ func TestBinder(t *testing.T) {
 	assert.Equal(t, []string(nil), resp.TransferEncoding)
 }
 
-func TestBinderTLS(t *testing.T) {
+func TestBinder_TLS(t *testing.T) {
 	handler := &mockHandler{t: t}
 
 	httpClient := &http.Client{
@@ -141,7 +141,7 @@ func TestBinderTLS(t *testing.T) {
 	assert.Same(t, tlsState, resp.Request.TLS)
 }
 
-func TestBinderChunked(t *testing.T) {
+func TestBinder_Chunked(t *testing.T) {
 	handler := &mockHandler{
 		t:       t,
 		chunked: true,
@@ -167,7 +167,7 @@ func TestBinderChunked(t *testing.T) {
 	assert.Equal(t, []string{"chunked"}, resp.TransferEncoding)
 }
 
-func TestFastBinder(t *testing.T) {
+func TestFastBinder_Basic(t *testing.T) {
 	handler := func(ctx *fasthttp.RequestCtx) {
 		assert.Equal(t, "POST", string(ctx.Request.Header.Method()))
 		assert.Equal(t, "http://example.com/path", string(ctx.Request.Header.RequestURI()))
@@ -243,7 +243,7 @@ func TestFastBinder(t *testing.T) {
 	assert.Equal(t, []string(nil), resp.TransferEncoding)
 }
 
-func TestFastBinderRemoteAddr(t *testing.T) {
+func TestFastBinder_RemoteAddr(t *testing.T) {
 	handler := func(ctx *fasthttp.RequestCtx) {
 		assert.NotNil(t, ctx.RemoteAddr())
 		assert.Equal(t, "tcp", ctx.RemoteAddr().Network())
@@ -278,7 +278,7 @@ func TestFastBinderRemoteAddr(t *testing.T) {
 	assert.Equal(t, `ok`, string(b))
 }
 
-func TestFastBinderProtocol(t *testing.T) {
+func TestFastBinder_Protocol(t *testing.T) {
 	test := func(setProto func(req *http.Request)) {
 		handler := func(ctx *fasthttp.RequestCtx) {
 			assert.Equal(t, "HTTP/1.0", string(ctx.Request.Header.Protocol()))
@@ -323,7 +323,7 @@ func TestFastBinderProtocol(t *testing.T) {
 	})
 }
 
-func TestFastBinderTLS(t *testing.T) {
+func TestFastBinder_TLS(t *testing.T) {
 	var isHTTPS, isTLS bool
 
 	tlsState := &tls.ConnectionState{
@@ -381,7 +381,7 @@ func TestFastBinderTLS(t *testing.T) {
 	assert.True(t, isTLS)
 }
 
-func TestFastBinderChunked(t *testing.T) {
+func TestFastBinder_Chunked(t *testing.T) {
 	handler := func(ctx *fasthttp.RequestCtx) {
 		assert.Equal(t, "POST", string(ctx.Request.Header.Method()))
 		assert.Equal(t, "http://example.com/path", string(ctx.Request.Header.RequestURI()))
@@ -437,7 +437,7 @@ func TestFastBinderChunked(t *testing.T) {
 	assert.Equal(t, []string{"chunked"}, resp.TransferEncoding)
 }
 
-func TestFastBinderEmptyResponse(t *testing.T) {
+func TestFastBinder_EmptyResponse(t *testing.T) {
 	handler := func(*fasthttp.RequestCtx) {}
 
 	client := &http.Client{
@@ -464,7 +464,7 @@ func TestFastBinderEmptyResponse(t *testing.T) {
 	assert.Equal(t, "", string(b))
 }
 
-func TestFastBinderLogger(t *testing.T) {
+func TestFastBinder_Logger(t *testing.T) {
 	handler := func(ctx *fasthttp.RequestCtx) {
 		ctx.Logger().Printf("test_message")
 	}
diff --git a/body_wrapper_test.go b/body_wrapper_test.go
index 669037a..99749a4 100644
--- a/body_wrapper_test.go
+++ b/body_wrapper_test.go
@@ -8,7 +8,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestBodyWrapperRewind(t *testing.T) {
+func TestBodyWrapper_Rewind(t *testing.T) {
 	body := newMockBody("test_body")
 
 	cancelled := false
@@ -35,7 +35,7 @@ func TestBodyWrapperRewind(t *testing.T) {
 	assert.Equal(t, "test_body", string(b))
 }
 
-func TestBodyWrapperGetBody(t *testing.T) {
+func TestBodyWrapper_GetBody(t *testing.T) {
 	body := newMockBody("test_body")
 
 	wrp := newBodyWrapper(body, nil)
@@ -55,7 +55,7 @@ func TestBodyWrapperGetBody(t *testing.T) {
 	assert.Equal(t, "test_body", string(b))
 }
 
-func TestBodyWrapperClose(t *testing.T) {
+func TestBodyWrapper_Close(t *testing.T) {
 	body := newMockBody("test_body")
 
 	cancelled := false
@@ -72,7 +72,7 @@ func TestBodyWrapperClose(t *testing.T) {
 	assert.True(t, cancelled)
 }
 
-func TestBodyWrapperOneError(t *testing.T) {
+func TestBodyWrapper_OneError(t *testing.T) {
 	bodyErr := errors.New("test_error")
 
 	checkReadErr := func(t *testing.T, wrp *bodyWrapper) {
@@ -175,7 +175,7 @@ func TestBodyWrapperOneError(t *testing.T) {
 	})
 }
 
-func TestBodyWrapperTwoErrors(t *testing.T) {
+func TestBodyWrapper_TwoErrors(t *testing.T) {
 	t.Run("read_close", func(t *testing.T) {
 		body := newMockBody("test_body")
 
@@ -217,7 +217,7 @@ func TestBodyWrapperTwoErrors(t *testing.T) {
 	})
 }
 
-func TestBodyWrapperErrorRewind(t *testing.T) {
+func TestBodyWrapper_ErrorRewind(t *testing.T) {
 	body := newMockBody("test_body")
 
 	body.readErr = errors.New("read_error")
diff --git a/boolean_test.go b/boolean_test.go
index dfc9f75..7b944e6 100644
--- a/boolean_test.go
+++ b/boolean_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestBooleanFailed(t *testing.T) {
+func TestBoolean_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -21,7 +21,7 @@ func TestBooleanFailed(t *testing.T) {
 	value.False()
 }
 
-func TestBooleanConstructors(t *testing.T) {
+func TestBoolean_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		value := NewBoolean(reporter, true)
@@ -37,9 +37,16 @@ func TestBooleanConstructors(t *testing.T) {
 		value.Equal(true)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newBoolean(chain, true)
+		assert.NotSame(t, value.chain, &chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestBooleanGetters(t *testing.T) {
+func TestBoolean_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewBoolean(reporter, true)
@@ -61,7 +68,7 @@ func TestBooleanGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestBooleanTrue(t *testing.T) {
+func TestBoolean_True(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewBoolean(reporter, true)
@@ -93,7 +100,7 @@ func TestBooleanTrue(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestBooleanFalse(t *testing.T) {
+func TestBoolean_False(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewBoolean(reporter, false)
diff --git a/canon_test.go b/canon_test.go
index 5eae441..7716b7b 100644
--- a/canon_test.go
+++ b/canon_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestCanonNumber(t *testing.T) {
+func TestCanon_Number(t *testing.T) {
 	type (
 		myInt int
 	)
@@ -42,7 +42,7 @@ func TestCanonNumber(t *testing.T) {
 	chain.clearFailed()
 }
 
-func TestCanonArray(t *testing.T) {
+func TestCanon_Array(t *testing.T) {
 	type (
 		myArray []interface{}
 		myInt   int
@@ -83,7 +83,7 @@ func TestCanonArray(t *testing.T) {
 	chain.clearFailed()
 }
 
-func TestCanonMap(t *testing.T) {
+func TestCanon_Map(t *testing.T) {
 	type (
 		myMap map[string]interface{}
 		myInt int
diff --git a/chain_test.go b/chain_test.go
index 3f285a9..e9d7b4d 100644
--- a/chain_test.go
+++ b/chain_test.go
@@ -7,7 +7,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestChainFail(t *testing.T) {
+func TestChain_Fail(t *testing.T) {
 	chain := newMockChain(t)
 
 	assert.False(t, chain.failed())
@@ -19,7 +19,7 @@ func TestChainFail(t *testing.T) {
 	assert.True(t, chain.failed())
 }
 
-func TestChainClone(t *testing.T) {
+func TestChain_Clone(t *testing.T) {
 	chain1 := newMockChain(t)
 	chain2 := chain1.clone()
 
@@ -37,7 +37,7 @@ func TestChainClone(t *testing.T) {
 	assert.True(t, chain2.failed())
 }
 
-func TestChainEnv(t *testing.T) {
+func TestChain_Env(t *testing.T) {
 	t.Run("newChainWithConfig", func(t *testing.T) {
 		env1 := NewEnvironment(newMockReporter(t))
 		chain1 := newChainWithConfig("root", Config{
@@ -59,7 +59,7 @@ func TestChainEnv(t *testing.T) {
 	})
 }
 
-func TestChainRoot(t *testing.T) {
+func TestChain_Root(t *testing.T) {
 	t.Run("newChainWithConfig", func(t *testing.T) {
 		chain1 := newChainWithConfig("root", Config{
 			AssertionHandler: &mockAssertionHandler{},
@@ -81,7 +81,7 @@ func TestChainRoot(t *testing.T) {
 	})
 }
 
-func TestChainPath(t *testing.T) {
+func TestChain_Path(t *testing.T) {
 	path := func(c *chain) string {
 		return strings.Join(c.context.Path, ".")
 	}
@@ -127,7 +127,7 @@ func TestChainPath(t *testing.T) {
 	assert.Equal(t, "root", path(chainClone))
 }
 
-func TestChainPanics(t *testing.T) {
+func TestChain_Panics(t *testing.T) {
 	t.Run("nil reporter", func(t *testing.T) {
 		assert.Panics(t, func() {
 			_ = newChainWithDefaults("test", nil)
@@ -183,7 +183,7 @@ func TestChainPanics(t *testing.T) {
 	})
 }
 
-func TestChainReport(t *testing.T) {
+func TestChain_Report(t *testing.T) {
 	r0 := newMockReporter(t)
 
 	chain := newChainWithDefaults("test", r0)
@@ -210,7 +210,7 @@ func TestChainReport(t *testing.T) {
 	assert.True(t, r2.reported)
 }
 
-func TestChainHandler(t *testing.T) {
+func TestChain_Handler(t *testing.T) {
 	handler := &mockAssertionHandler{}
 
 	chain := newChainWithConfig("test", Config{
@@ -236,7 +236,7 @@ func TestChainHandler(t *testing.T) {
 	assert.Nil(t, handler.failure)
 }
 
-func TestChainSeverity(t *testing.T) {
+func TestChain_Severity(t *testing.T) {
 	handler := &mockAssertionHandler{}
 
 	chain := newChainWithConfig("test", Config{
@@ -265,7 +265,7 @@ func TestChainSeverity(t *testing.T) {
 	assert.Equal(t, SeverityLog, handler.failure.Severity)
 }
 
-func TestChainCallback(t *testing.T) {
+func TestChain_Callback(t *testing.T) {
 	handler := &mockAssertionHandler{}
 
 	chain := newChainWithConfig("test", Config{
diff --git a/cookie_test.go b/cookie_test.go
index 2e411f2..8411226 100644
--- a/cookie_test.go
+++ b/cookie_test.go
@@ -9,7 +9,7 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestCookieFailed(t *testing.T) {
+func TestCookie_Failed(t *testing.T) {
 	check := func(value *Cookie, isNil bool) {
 		value.chain.assertFailed(t)
 
@@ -56,7 +56,7 @@ func TestCookieFailed(t *testing.T) {
 	})
 }
 
-func TestCookieConstructors(t *testing.T) {
+func TestCookie_Constructors(t *testing.T) {
 	cookie := &http.Cookie{
 		Name:    "Test",
 		Value:   "Test_val",
@@ -89,9 +89,16 @@ func TestCookieConstructors(t *testing.T) {
 		value.MaxAge().Equal(123 * time.Second)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newCookie(chain, cookie)
+		assert.NotSame(t, value.chain, &chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestCookieGetters(t *testing.T) {
+func TestCookie_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewCookie(reporter, &http.Cookie{
@@ -122,7 +129,7 @@ func TestCookieGetters(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestCookieMaxAge(t *testing.T) {
+func TestCookie_MaxAge(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("unset", func(t *testing.T) {
diff --git a/datetime_test.go b/datetime_test.go
index 20b63b0..5c6aa3d 100644
--- a/datetime_test.go
+++ b/datetime_test.go
@@ -7,7 +7,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestDateTimeFailed(t *testing.T) {
+func TestDateTime_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -25,9 +25,21 @@ func TestDateTimeFailed(t *testing.T) {
 	value.Le(tm)
 	value.InRange(tm, tm)
 	value.NotInRange(tm, tm)
+	value.Zone()
+	value.Year()
+	value.Month()
+	value.Day()
+	value.WeekDay()
+	value.YearDay()
+	value.Hour()
+	value.Minute()
+	value.Second()
+	value.Nanosecond()
+	value.AsUTC()
+	value.AsLocal()
 }
 
-func TestDatetimeConstructors(t *testing.T) {
+func TestDateTime_Constructors(t *testing.T) {
 	time := time.Unix(0, 1234)
 
 	t.Run("Constructor without config", func(t *testing.T) {
@@ -45,9 +57,16 @@ func TestDatetimeConstructors(t *testing.T) {
 		value.Equal(time)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newDateTime(chain, time)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestDateTimeEqual(t *testing.T) {
+func TestDateTime_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDateTime(reporter, time.Unix(0, 1234))
@@ -71,7 +90,7 @@ func TestDateTimeEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDateTimeGreater(t *testing.T) {
+func TestDateTime_Greater(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDateTime(reporter, time.Unix(0, 1234))
@@ -97,7 +116,7 @@ func TestDateTimeGreater(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDateTimeLesser(t *testing.T) {
+func TestDateTime_Lesser(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDateTime(reporter, time.Unix(0, 1234))
@@ -123,7 +142,7 @@ func TestDateTimeLesser(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDateTimeInRange(t *testing.T) {
+func TestDateTime_InRange(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDateTime(reporter, time.Unix(0, 1234))
@@ -176,3 +195,39 @@ func TestDateTimeInRange(t *testing.T) {
 	value.chain.assertNotFailed(t)
 	value.chain.clearFailed()
 }
+
+func TestDateTimeGetters(t *testing.T) {
+	reporter := newMockReporter(t)
+
+	parsedTime, _ := time.Parse(time.UnixDate, "FRI Dec 30 15:04:05 IST 2022")
+
+	value := NewDateTime(reporter, parsedTime)
+
+	value.chain.assertNotFailed(t)
+
+	value.Zone().chain.assertNotFailed(t)
+	value.Year().chain.assertNotFailed(t)
+	value.Month().chain.assertNotFailed(t)
+	value.Day().chain.assertNotFailed(t)
+	value.WeekDay().chain.assertNotFailed(t)
+	value.YearDay().chain.assertNotFailed(t)
+	value.Hour().chain.assertNotFailed(t)
+	value.Minute().chain.assertNotFailed(t)
+	value.Second().chain.assertNotFailed(t)
+	value.Nanosecond().chain.assertNotFailed(t)
+	value.AsUTC().chain.assertNotFailed(t)
+	value.AsLocal().chain.assertNotFailed(t)
+
+	expectedTime := parsedTime
+	expectedZone, _ := expectedTime.Zone()
+	assert.Equal(t, expectedZone, value.Zone().Raw())
+	assert.Equal(t, float64(expectedTime.Year()), value.Year().Raw())
+	assert.Equal(t, float64(expectedTime.Month()), value.Month().Raw())
+	assert.Equal(t, float64(expectedTime.Day()), value.Day().Raw())
+	assert.Equal(t, float64(expectedTime.Weekday()), value.WeekDay().Raw())
+	assert.Equal(t, float64(expectedTime.YearDay()), value.YearDay().Raw())
+	assert.Equal(t, float64(expectedTime.Hour()), value.Hour().Raw())
+	assert.Equal(t, float64(expectedTime.Minute()), value.Minute().Raw())
+	assert.Equal(t, float64(expectedTime.Second()), value.Second().Raw())
+	assert.Equal(t, float64(expectedTime.Nanosecond()), value.Nanosecond().Raw())
+}
diff --git a/duration_test.go b/duration_test.go
index 7547f86..0054b8a 100644
--- a/duration_test.go
+++ b/duration_test.go
@@ -7,7 +7,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestDurationFailed(t *testing.T) {
+func TestDuration_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -24,7 +24,7 @@ func TestDurationFailed(t *testing.T) {
 	value.NotInRange(tm, tm)
 }
 
-func TestDurationConstructors(t *testing.T) {
+func TestDuration_Constructors(t *testing.T) {
 	tm := time.Second
 
 	t.Run("Constructor without config", func(t *testing.T) {
@@ -42,9 +42,17 @@ func TestDurationConstructors(t *testing.T) {
 		value.Equal(tm)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newDuration(chain, &tm)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
+
 }
 
-func TestDurationSet(t *testing.T) {
+func TestDuration_Set(t *testing.T) {
 	chain := newMockChain(t)
 
 	tm := time.Second
@@ -59,7 +67,7 @@ func TestDurationSet(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDurationUnset(t *testing.T) {
+func TestDuration_Unset(t *testing.T) {
 	chain := newMockChain(t)
 
 	value := newDuration(chain, nil)
@@ -73,7 +81,7 @@ func TestDurationUnset(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDurationEqual(t *testing.T) {
+func TestDuration_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDuration(reporter, time.Second)
@@ -97,7 +105,7 @@ func TestDurationEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDurationGreater(t *testing.T) {
+func TestDuration_Greater(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDuration(reporter, time.Second)
@@ -123,7 +131,7 @@ func TestDurationGreater(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDurationLesser(t *testing.T) {
+func TestDuration_Lesser(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDuration(reporter, time.Second)
@@ -149,7 +157,7 @@ func TestDurationLesser(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestDurationInRange(t *testing.T) {
+func TestDuration_InRange(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewDuration(reporter, time.Second)
diff --git a/e2e_basic_test.go b/e2e_basic_test.go
index b5b1a84..8497551 100644
--- a/e2e_basic_test.go
+++ b/e2e_basic_test.go
@@ -91,7 +91,7 @@ func testBasicHandler(e *Expect) {
 		Form().ValueEqual("username", "john").ValueEqual("password", "secret")
 }
 
-func TestE2EBasicLiveDefault(t *testing.T) {
+func TestE2EBasic_LiveDefault(t *testing.T) {
 	handler := createBasicHandler()
 
 	server := httptest.NewServer(handler)
@@ -100,7 +100,7 @@ func TestE2EBasicLiveDefault(t *testing.T) {
 	testBasicHandler(Default(t, server.URL))
 }
 
-func TestE2EBasicLiveConfig(t *testing.T) {
+func TestE2EBasic_LiveConfig(t *testing.T) {
 	handler := createBasicHandler()
 
 	server := httptest.NewServer(handler)
@@ -116,7 +116,7 @@ func TestE2EBasicLiveConfig(t *testing.T) {
 	}))
 }
 
-func TestE2EBasicLiveTLS(t *testing.T) {
+func TestE2EBasic_LiveTLS(t *testing.T) {
 	handler := createBasicHandler()
 
 	server := httptest.NewTLSServer(handler)
@@ -135,7 +135,7 @@ func TestE2EBasicLiveTLS(t *testing.T) {
 	}))
 }
 
-func TestE2EBasicLiveLongRun(t *testing.T) {
+func TestE2EBasic_LiveLongRun(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -152,7 +152,7 @@ func TestE2EBasicLiveLongRun(t *testing.T) {
 	}
 }
 
-func TestE2EBasicBinderStandard(t *testing.T) {
+func TestE2EBasic_BinderStandard(t *testing.T) {
 	handler := createBasicHandler()
 
 	testBasicHandler(WithConfig(Config{
@@ -164,7 +164,7 @@ func TestE2EBasicBinderStandard(t *testing.T) {
 	}))
 }
 
-func TestE2EBasicBinderFast(t *testing.T) {
+func TestE2EBasic_BinderFast(t *testing.T) {
 	handler := fasthttpadaptor.NewFastHTTPHandler(createBasicHandler())
 
 	testBasicHandler(WithConfig(Config{
diff --git a/e2e_chunked_test.go b/e2e_chunked_test.go
index 7176c0d..41f8b28 100644
--- a/e2e_chunked_test.go
+++ b/e2e_chunked_test.go
@@ -65,7 +65,7 @@ func testChunkedHandler(e *Expect) {
 		JSON().Array().Elements(1, 2)
 }
 
-func TestE2EChunkedLive(t *testing.T) {
+func TestE2EChunked_Live(t *testing.T) {
 	handler := createChunkedHandler()
 
 	server := httptest.NewServer(handler)
@@ -74,7 +74,7 @@ func TestE2EChunkedLive(t *testing.T) {
 	testChunkedHandler(Default(t, server.URL))
 }
 
-func TestE2EChunkedBinderStandard(t *testing.T) {
+func TestE2EChunked_BinderStandard(t *testing.T) {
 	handler := createChunkedHandler()
 
 	testChunkedHandler(WithConfig(Config{
@@ -86,7 +86,7 @@ func TestE2EChunkedBinderStandard(t *testing.T) {
 	}))
 }
 
-func TestE2EChunkedBinderFast(t *testing.T) {
+func TestE2EChunked_BinderFast(t *testing.T) {
 	handler := createChunkedFastHandler(t)
 
 	testChunkedHandler(WithConfig(Config{
diff --git a/e2e_context_test.go b/e2e_context_test.go
index 54858e0..51a12bd 100644
--- a/e2e_context_test.go
+++ b/e2e_context_test.go
@@ -29,8 +29,8 @@ func (h *waitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	h.mux.ServeHTTP(w, r)
 }
 
-func (h *waitHandler) WaitForContextCancellation(w http.ResponseWriter, r *http.Request) {
-	callCount := h.IncrCallCount()
+func (h *waitHandler) waitForContextCancellation(w http.ResponseWriter, r *http.Request) {
+	callCount := h.incrCallCount()
 	// if retries-to-fail are not set then simply wait for the cancellation
 	if h.retriesToFail == 0 {
 		<-r.Context().Done()
@@ -46,8 +46,8 @@ func (h *waitHandler) WaitForContextCancellation(w http.ResponseWriter, r *http.
 	}
 }
 
-func (h *waitHandler) WaitForPerRequestTimeout(w http.ResponseWriter, r *http.Request) {
-	callCount := h.IncrCallCount()
+func (h *waitHandler) waitForPerRequestTimeout(w http.ResponseWriter, r *http.Request) {
+	callCount := h.incrCallCount()
 	// if retries-to-fail are not set or not exhausted yet, simply wait for
 	// the timeout
 	if h.retriesToFail == 0 || callCount < h.retriesToFail+1 {
@@ -58,7 +58,7 @@ func (h *waitHandler) WaitForPerRequestTimeout(w http.ResponseWriter, r *http.Re
 	}
 }
 
-func (h *waitHandler) IncrCallCount() int {
+func (h *waitHandler) incrCallCount() int {
 	h.Lock()
 	defer h.Unlock()
 	h.callCount++
@@ -66,7 +66,7 @@ func (h *waitHandler) IncrCallCount() int {
 	return r
 }
 
-func (h *waitHandler) GetCallCount() int {
+func (h *waitHandler) getCallCount() int {
 	h.RLock()
 	defer h.RUnlock()
 	return h.callCount
@@ -81,8 +81,8 @@ func newWaitHandler(retriesToFail int) *waitHandler {
 		retriesDone:   make(chan struct{}),
 	}
 
-	mux.HandleFunc("/WaitForContextCancellation", handler.WaitForContextCancellation)
-	mux.HandleFunc("/WaitForPerRequestTimeout", handler.WaitForPerRequestTimeout)
+	mux.HandleFunc("/waitForContextCancellation", handler.waitForContextCancellation)
+	mux.HandleFunc("/waitForPerRequestTimeout", handler.waitForPerRequestTimeout)
 
 	return handler
 }
@@ -126,7 +126,7 @@ func (h *expErrorSuppressor) Failure(
 	h.backend.Fail(h.formatter.FormatFailure(ctx, failure))
 }
 
-func TestE2EContextGlobalCancel(t *testing.T) {
+func TestE2EContext_GlobalCancel(t *testing.T) {
 	handler := newWaitHandler(0)
 
 	server := httptest.NewServer(handler)
@@ -149,7 +149,7 @@ func TestE2EContextGlobalCancel(t *testing.T) {
 	done := make(chan struct{})
 
 	go func() {
-		e.GET("/WaitForContextCancellation").
+		e.GET("/waitForContextCancellation").
 			Expect()
 		done <- struct{}{}
 	}()
@@ -162,7 +162,7 @@ func TestE2EContextGlobalCancel(t *testing.T) {
 	assert.True(t, suppressor.expErrorOccurred)
 }
 
-func TestE2EContextGlobalWithRetries(t *testing.T) {
+func TestE2EContext_GlobalWithRetries(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -191,7 +191,7 @@ func TestE2EContextGlobalWithRetries(t *testing.T) {
 	done := make(chan struct{})
 
 	go func() {
-		e.GET("/WaitForContextCancellation").
+		e.GET("/waitForContextCancellation").
 			WithMaxRetries(maxRetries).
 			Expect()
 		done <- struct{}{}
@@ -205,10 +205,10 @@ func TestE2EContextGlobalWithRetries(t *testing.T) {
 	// expected error should occur
 	assert.True(t, suppressor.expErrorOccurred)
 	// first call + retries to fail should be the call count
-	assert.Equal(t, retriesToFail+1, handler.GetCallCount())
+	assert.Equal(t, retriesToFail+1, handler.getCallCount())
 }
 
-func TestE2EContextPerRequest(t *testing.T) {
+func TestE2EContext_PerRequest(t *testing.T) {
 	handler := newWaitHandler(0)
 
 	server := httptest.NewServer(handler)
@@ -230,7 +230,7 @@ func TestE2EContextPerRequest(t *testing.T) {
 	done := make(chan struct{})
 
 	go func() {
-		e.GET("/WaitForContextCancellation").
+		e.GET("/waitForContextCancellation").
 			WithContext(ctx).
 			Expect()
 		done <- struct{}{}
@@ -244,7 +244,7 @@ func TestE2EContextPerRequest(t *testing.T) {
 	assert.True(t, suppressor.expErrorOccurred)
 }
 
-func TestE2EContextPerRequestWithRetries(t *testing.T) {
+func TestE2EContext_PerRequestWithRetries(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -272,7 +272,7 @@ func TestE2EContextPerRequestWithRetries(t *testing.T) {
 	done := make(chan struct{})
 
 	go func() {
-		e.GET("/WaitForContextCancellation").
+		e.GET("/waitForContextCancellation").
 			WithMaxRetries(maxRetries).
 			WithContext(ctx).
 			Expect()
@@ -287,10 +287,10 @@ func TestE2EContextPerRequestWithRetries(t *testing.T) {
 	// expected error should occur
 	assert.True(t, suppressor.expErrorOccurred)
 	// first call + retries to fail should be the call count
-	assert.Equal(t, retriesToFail+1, handler.GetCallCount())
+	assert.Equal(t, retriesToFail+1, handler.getCallCount())
 }
 
-func TestE2EContextPerRequestWithTimeout(t *testing.T) {
+func TestE2EContext_PerRequestWithTimeout(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -310,7 +310,7 @@ func TestE2EContextPerRequestWithTimeout(t *testing.T) {
 		AssertionHandler: suppressor,
 	})
 
-	e.GET("/WaitForPerRequestTimeout").
+	e.GET("/waitForPerRequestTimeout").
 		WithTimeout(TimeOutDuration).
 		Expect()
 
@@ -318,7 +318,7 @@ func TestE2EContextPerRequestWithTimeout(t *testing.T) {
 	assert.True(t, suppressor.expErrorOccurred)
 }
 
-func TestE2EContextPerRequestWithTimeoutAndRetries(t *testing.T) {
+func TestE2EContext_PerRequestWithTimeoutAndRetries(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -336,17 +336,17 @@ func TestE2EContextPerRequestWithTimeoutAndRetries(t *testing.T) {
 		Reporter: NewAssertReporter(t),
 	})
 
-	e.GET("/WaitForPerRequestTimeout").
+	e.GET("/waitForPerRequestTimeout").
 		WithTimeout(TimeOutDuration).
 		WithMaxRetries(maxRetries).
 		Expect().
 		Status(http.StatusOK)
 
 	// first call + retries to fail should be the call count
-	assert.Equal(t, retriesToFail+1, handler.GetCallCount())
+	assert.Equal(t, retriesToFail+1, handler.getCallCount())
 }
 
-func TestE2EContextPerRequestWithTimeoutCancelledByTimeout(t *testing.T) {
+func TestE2EContext_PerRequestWithTimeoutCancelledByTimeout(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -369,7 +369,7 @@ func TestE2EContextPerRequestWithTimeoutCancelledByTimeout(t *testing.T) {
 		AssertionHandler: suppressor,
 	})
 
-	e.GET("/WaitForPerRequestTimeout").
+	e.GET("/waitForPerRequestTimeout").
 		WithContext(ctx).
 		WithTimeout(TimeOutDuration).
 		Expect()
@@ -378,7 +378,7 @@ func TestE2EContextPerRequestWithTimeoutCancelledByTimeout(t *testing.T) {
 	assert.True(t, suppressor.expErrorOccurred)
 }
 
-func TestE2EContextPerRequestWithTimeoutCancelledByContext(t *testing.T) {
+func TestE2EContext_PerRequestWithTimeoutCancelledByContext(t *testing.T) {
 	handler := newWaitHandler(0)
 
 	server := httptest.NewServer(handler)
@@ -400,7 +400,7 @@ func TestE2EContextPerRequestWithTimeoutCancelledByContext(t *testing.T) {
 	done := make(chan struct{})
 
 	go func() {
-		e.GET("/WaitForContextCancellation").
+		e.GET("/waitForContextCancellation").
 			WithContext(ctx).
 			WithTimeout(TimeOutDuration).
 			Expect()
@@ -415,7 +415,7 @@ func TestE2EContextPerRequestWithTimeoutCancelledByContext(t *testing.T) {
 	assert.True(t, suppressor.expErrorOccurred)
 }
 
-func TestE2EContextPerRequestRetry(t *testing.T) {
+func TestE2EContext_PerRequestRetry(t *testing.T) {
 	var m sync.Mutex
 
 	t.Run("not cancelled", func(t *testing.T) {
diff --git a/e2e_cookie_test.go b/e2e_cookie_test.go
index f3521a9..c5c388c 100644
--- a/e2e_cookie_test.go
+++ b/e2e_cookie_test.go
@@ -51,7 +51,7 @@ func testCookieHandler(e *Expect, enabled bool) {
 	}
 }
 
-func TestE2ECookieLiveDisabled(t *testing.T) {
+func TestE2ECookie_LiveDisabled(t *testing.T) {
 	handler := createCookieHandler()
 
 	server := httptest.NewServer(handler)
@@ -68,7 +68,7 @@ func TestE2ECookieLiveDisabled(t *testing.T) {
 	testCookieHandler(e, false)
 }
 
-func TestE2ECookieLiveEnabled(t *testing.T) {
+func TestE2ECookie_LiveEnabled(t *testing.T) {
 	handler := createCookieHandler()
 
 	server := httptest.NewServer(handler)
@@ -85,7 +85,7 @@ func TestE2ECookieLiveEnabled(t *testing.T) {
 	testCookieHandler(e, true)
 }
 
-func TestE2ECookieBinderStandardDisabled(t *testing.T) {
+func TestE2ECookie_BinderStandardDisabled(t *testing.T) {
 	handler := createCookieHandler()
 
 	e := WithConfig(Config{
@@ -100,7 +100,7 @@ func TestE2ECookieBinderStandardDisabled(t *testing.T) {
 	testCookieHandler(e, false)
 }
 
-func TestE2ECookieBinderStandardEnabled(t *testing.T) {
+func TestE2ECookie_BinderStandardEnabled(t *testing.T) {
 	handler := createCookieHandler()
 
 	e := WithConfig(Config{
@@ -115,7 +115,7 @@ func TestE2ECookieBinderStandardEnabled(t *testing.T) {
 	testCookieHandler(e, true)
 }
 
-func TestE2ECookieBinderFastDisabled(t *testing.T) {
+func TestE2ECookie_BinderFastDisabled(t *testing.T) {
 	handler := fasthttpadaptor.NewFastHTTPHandler(createCookieHandler())
 
 	e := WithConfig(Config{
@@ -130,7 +130,7 @@ func TestE2ECookieBinderFastDisabled(t *testing.T) {
 	testCookieHandler(e, false)
 }
 
-func TestE2ECookieBinderFastEnabled(t *testing.T) {
+func TestE2ECookie_BinderFastEnabled(t *testing.T) {
 	handler := fasthttpadaptor.NewFastHTTPHandler(createCookieHandler())
 
 	e := WithConfig(Config{
diff --git a/e2e_environment_test.go b/e2e_environment_test.go
index daa3063..62f7fe9 100644
--- a/e2e_environment_test.go
+++ b/e2e_environment_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestE2EEnvironmentDefault(t *testing.T) {
+func TestE2EEnvironment_Default(t *testing.T) {
 	e1 := Default(t, "")
 	e2 := WithConfig(Config{
 		Reporter: t,
@@ -29,7 +29,7 @@ func TestE2EEnvironmentDefault(t *testing.T) {
 	assert.True(t, e2.Env().Has("key"))
 }
 
-func TestE2EEnvironmentShared(t *testing.T) {
+func TestE2EEnvironment_Shared(t *testing.T) {
 	env := NewEnvironment(t)
 
 	e1 := WithConfig(Config{
diff --git a/e2e_fs_test.go b/e2e_fs_test.go
index 6ba4d0c..75a24c5 100644
--- a/e2e_fs_test.go
+++ b/e2e_fs_test.go
@@ -10,7 +10,7 @@ import (
 	"github.com/valyala/fasthttp"
 )
 
-func TestE2EFsFastBinder(t *testing.T) {
+func TestE2EFs_FastBinder(t *testing.T) {
 	tempdir, err := ioutil.TempDir("", "httpexpect")
 	if err != nil {
 		t.Fatal(err)
diff --git a/e2e_printer_test.go b/e2e_printer_test.go
index 4cd15e0..ea76177 100644
--- a/e2e_printer_test.go
+++ b/e2e_printer_test.go
@@ -24,7 +24,7 @@ func createPrinterHandler() http.Handler {
 	return mux
 }
 
-func TestE2EPrinter(t *testing.T) {
+func TestE2EPrinter_Single(t *testing.T) {
 	handler := createPrinterHandler()
 
 	server := httptest.NewServer(handler)
@@ -50,7 +50,7 @@ func TestE2EPrinter(t *testing.T) {
 	assert.Equal(t, "test_response", string(p.respBody))
 }
 
-func TestE2EPrinterMultiple(t *testing.T) {
+func TestE2EPrinter_Multiple(t *testing.T) {
 	handler := createPrinterHandler()
 
 	server := httptest.NewServer(handler)
diff --git a/e2e_redirect_test.go b/e2e_redirect_test.go
index 2822035..8145d60 100644
--- a/e2e_redirect_test.go
+++ b/e2e_redirect_test.go
@@ -169,7 +169,7 @@ func testRedirects(t *testing.T, createFn func(Reporter) *Expect) {
 	})
 }
 
-func TestE2ERedirectLive(t *testing.T) {
+func TestE2ERedirect_Live(t *testing.T) {
 	handler := createRedirectHandler()
 
 	server := httptest.NewServer(handler)
@@ -183,7 +183,7 @@ func TestE2ERedirectLive(t *testing.T) {
 	})
 }
 
-func TestE2ERedirectBinderStandard(t *testing.T) {
+func TestE2ERedirect_BinderStandard(t *testing.T) {
 	handler := createRedirectHandler()
 
 	testRedirects(t, func(rep Reporter) *Expect {
@@ -197,7 +197,7 @@ func TestE2ERedirectBinderStandard(t *testing.T) {
 	})
 }
 
-func TestE2ERedirectBinderFast(t *testing.T) {
+func TestE2ERedirect_BinderFast(t *testing.T) {
 	handler := createRedirectFastHandler()
 
 	testRedirects(t, func(rep Reporter) *Expect {
diff --git a/e2e_report_test.go b/e2e_report_test.go
index b99cc40..03d4668 100644
--- a/e2e_report_test.go
+++ b/e2e_report_test.go
@@ -17,7 +17,7 @@ func (r *recordingReporter) Errorf(msg string, args ...interface{}) {
 	r.reported += fmt.Sprintf(msg, args...)
 }
 
-func TestE2EReportNames(t *testing.T) {
+func TestE2EReport_Names(t *testing.T) {
 	mux := http.NewServeMux()
 
 	mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
diff --git a/e2e_retry_test.go b/e2e_retry_test.go
index c71673e..c68e6bc 100644
--- a/e2e_retry_test.go
+++ b/e2e_retry_test.go
@@ -231,7 +231,7 @@ func testRetries(
 	})
 }
 
-func TestE2ERetryLive(t *testing.T) {
+func TestE2ERetry_Live(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -256,7 +256,7 @@ func TestE2ERetryLive(t *testing.T) {
 	})
 }
 
-func TestE2ERetryBinderStandard(t *testing.T) {
+func TestE2ERetry_BinderStandard(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -278,7 +278,7 @@ func TestE2ERetryBinderStandard(t *testing.T) {
 	})
 }
 
-func TestE2ERetryBinderFast(t *testing.T) {
+func TestE2ERetry_BinderFast(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
diff --git a/e2e_timeout_test.go b/e2e_timeout_test.go
index 675e8c5..b6caf11 100644
--- a/e2e_timeout_test.go
+++ b/e2e_timeout_test.go
@@ -46,7 +46,7 @@ func createTimeoutHandler() http.Handler {
 	return mux
 }
 
-func TestE2ETimeoutDeadlineExpired(t *testing.T) {
+func TestE2ETimeout_DeadlineExpired(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -70,7 +70,7 @@ func TestE2ETimeoutDeadlineExpired(t *testing.T) {
 	assert.True(t, r.reported)
 }
 
-func TestE2ETimeoutSmallBody(t *testing.T) {
+func TestE2ETimeout_SmallBody(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -92,7 +92,7 @@ func TestE2ETimeoutSmallBody(t *testing.T) {
 	}
 }
 
-func TestE2ETimeoutLargeBody(t *testing.T) {
+func TestE2ETimeout_LargeBody(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
diff --git a/e2e_tls_test.go b/e2e_tls_test.go
index eee6a60..82d7542 100644
--- a/e2e_tls_test.go
+++ b/e2e_tls_test.go
@@ -71,7 +71,7 @@ func testAutoTLSHandler(config Config) {
 		Status(http.StatusOK).Body().Equal(`hello`)
 }
 
-func TestE2EAutoTLSLive(t *testing.T) {
+func TestE2EAutoTLS_Live(t *testing.T) {
 	httpsServ := httptest.NewTLSServer(createAutoTLSHandler(""))
 	defer httpsServ.Close()
 
@@ -99,7 +99,7 @@ func TestE2EAutoTLSLive(t *testing.T) {
 	}
 }
 
-func TestE2EAutoTLSBinderStandard(t *testing.T) {
+func TestE2EAutoTLS_BinderStandard(t *testing.T) {
 	handler := createAutoTLSHandler("https://example.com")
 
 	for _, url := range []string{"https://example.com", "http://example.com"} {
@@ -119,7 +119,7 @@ func TestE2EAutoTLSBinderStandard(t *testing.T) {
 	}
 }
 
-func TestE2EAutoTLSBinderFast(t *testing.T) {
+func TestE2EAutoTLS_BinderFast(t *testing.T) {
 	handler := createAutoTLSFastHandler("https://example.com")
 
 	for _, url := range []string{"https://example.com", "http://example.com"} {
diff --git a/e2e_websocket_test.go b/e2e_websocket_test.go
index 12077bb..7e2bca2 100644
--- a/e2e_websocket_test.go
+++ b/e2e_websocket_test.go
@@ -166,7 +166,7 @@ func testWebsocket(e *Expect) {
 	testWebsocketTypes(e)
 }
 
-func TestE2EWebsocketLive(t *testing.T) {
+func TestE2EWebsocket_Live(t *testing.T) {
 	handler := createWebsocketHandler(wsHandlerOpts{})
 
 	server := httptest.NewServer(handler)
@@ -183,7 +183,7 @@ func TestE2EWebsocketLive(t *testing.T) {
 	testWebsocket(e)
 }
 
-func TestE2EWebsocketHandlerStandard(t *testing.T) {
+func TestE2EWebsocket_HandlerStandard(t *testing.T) {
 	t.Run("dialer-config", func(t *testing.T) {
 		handler := createWebsocketHandler(wsHandlerOpts{})
 
@@ -214,7 +214,7 @@ func TestE2EWebsocketHandlerStandard(t *testing.T) {
 	})
 }
 
-func TestE2EWebsocketHandlerFast(t *testing.T) {
+func TestE2EWebsocket_HandlerFast(t *testing.T) {
 	t.Run("dialer-config", func(t *testing.T) {
 		e := WithConfig(Config{
 			Reporter:        NewAssertReporter(t),
@@ -282,7 +282,7 @@ func testWebsocketTimeout(
 	}
 }
 
-func TestE2EWebsocketTimeouts(t *testing.T) {
+func TestE2EWebsocket_Timeouts(t *testing.T) {
 	if testing.Short() {
 		t.Skip()
 	}
@@ -330,7 +330,7 @@ func TestE2EWebsocketTimeouts(t *testing.T) {
 	})
 }
 
-func TestE2EWebsocketClosed(t *testing.T) {
+func TestE2EWebsocket_Closed(t *testing.T) {
 	t.Run("close-write", func(t *testing.T) {
 		handler := createWebsocketHandler(wsHandlerOpts{})
 
@@ -380,7 +380,7 @@ func TestE2EWebsocketClosed(t *testing.T) {
 	})
 }
 
-func TestE2EWebsocketDisconnected(t *testing.T) {
+func TestE2EWebsocket_Disconnected(t *testing.T) {
 	t.Run("disconnect-write", func(t *testing.T) {
 		handler := createWebsocketHandler(wsHandlerOpts{})
 
@@ -451,7 +451,7 @@ func TestE2EWebsocketDisconnected(t *testing.T) {
 	})
 }
 
-func TestE2EWebsocketInvalid(t *testing.T) {
+func TestE2EWebsocket_Invalid(t *testing.T) {
 	handler := createWebsocketHandler(wsHandlerOpts{})
 
 	server := httptest.NewServer(handler)
diff --git a/environment_test.go b/environment_test.go
index cd16b2d..abd6b09 100644
--- a/environment_test.go
+++ b/environment_test.go
@@ -9,7 +9,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestEnvironmentConstructors(t *testing.T) {
+func TestEnvironment_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		env := NewEnvironment(reporter)
@@ -23,9 +23,16 @@ func TestEnvironmentConstructors(t *testing.T) {
 		})
 		env.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newEnvironment(chain)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestEnvironmentGeneric(t *testing.T) {
+func TestEnvironment_Generic(t *testing.T) {
 	env := newEnvironment(newMockChain(t))
 
 	assert.False(t, env.Has("good_key"))
@@ -46,7 +53,7 @@ func TestEnvironmentGeneric(t *testing.T) {
 	env.chain.assertFailed(t)
 }
 
-func TestEnvironmentNotFound(t *testing.T) {
+func TestEnvironment_NotFound(t *testing.T) {
 	env := newEnvironment(newMockChain(t))
 
 	assert.Nil(t, env.Get("bad_key"))
@@ -82,7 +89,7 @@ func TestEnvironmentNotFound(t *testing.T) {
 	env.chain.clearFailed()
 }
 
-func TestEnvironmentBool(t *testing.T) {
+func TestEnvironment_Bool(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get bool
@@ -129,7 +136,7 @@ func TestEnvironmentBool(t *testing.T) {
 	}
 }
 
-func TestEnvironmentInt(t *testing.T) {
+func TestEnvironment_Int(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get int
@@ -226,7 +233,7 @@ func TestEnvironmentInt(t *testing.T) {
 	}
 }
 
-func TestEnvironmentFloat(t *testing.T) {
+func TestEnvironment_Float(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get float64
@@ -278,7 +285,7 @@ func TestEnvironmentFloat(t *testing.T) {
 	}
 }
 
-func TestEnvironmentString(t *testing.T) {
+func TestEnvironment_String(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get string
@@ -320,7 +327,7 @@ func TestEnvironmentString(t *testing.T) {
 	}
 }
 
-func TestEnvironmentBytes(t *testing.T) {
+func TestEnvironment_Bytes(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get []byte
@@ -362,7 +369,7 @@ func TestEnvironmentBytes(t *testing.T) {
 	}
 }
 
-func TestEnvironmentDuration(t *testing.T) {
+func TestEnvironment_Duration(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get time.Duration
@@ -404,7 +411,7 @@ func TestEnvironmentDuration(t *testing.T) {
 	}
 }
 
-func TestEnvironmentTime(t *testing.T) {
+func TestEnvironment_Time(t *testing.T) {
 	tests := []struct {
 		put interface{}
 		get time.Time
diff --git a/expect_test.go b/expect_test.go
index dc4a9e3..821f4f2 100644
--- a/expect_test.go
+++ b/expect_test.go
@@ -10,7 +10,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestExpectMethods(t *testing.T) {
+func TestExpect_Methods(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -44,7 +44,7 @@ func TestExpectMethods(t *testing.T) {
 	assert.Equal(t, "DELETE", reqs[7].httpReq.Method)
 }
 
-func TestExpectBuilders(t *testing.T) {
+func TestExpect_Builders(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -81,7 +81,7 @@ func TestExpectBuilders(t *testing.T) {
 	assert.Same(t, r2, reqs2[0])
 }
 
-func TestExpectBuildersCopying(t *testing.T) {
+func TestExpect_BuildersCopying(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -137,7 +137,7 @@ func TestExpectBuildersCopying(t *testing.T) {
 	assert.Equal(t, 1, counter2b)
 }
 
-func TestExpectMatchers(t *testing.T) {
+func TestExpect_Matchers(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -180,7 +180,7 @@ func TestExpectMatchers(t *testing.T) {
 	assert.Same(t, resp2, resps2[0])
 }
 
-func TestExpectMatchersCopying(t *testing.T) {
+func TestExpect_MatchersCopying(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -236,7 +236,7 @@ func TestExpectMatchersCopying(t *testing.T) {
 	assert.Equal(t, 1, counter2b)
 }
 
-func TestExpectValues(t *testing.T) {
+func TestExpect_Values(t *testing.T) {
 	client := &mockClient{}
 
 	r := NewAssertReporter(t)
@@ -262,7 +262,7 @@ func TestExpectValues(t *testing.T) {
 	assert.NotNil(t, e.Boolean(b))
 }
 
-func TestExpectTraverse(t *testing.T) {
+func TestExpect_Traverse(t *testing.T) {
 	client := &mockClient{}
 
 	reporter := NewAssertReporter(t)
@@ -304,7 +304,7 @@ func TestExpectTraverse(t *testing.T) {
 	m.Value("aaa").Array().Element(3).Null()
 }
 
-func TestExpectBranches(t *testing.T) {
+func TestExpect_Branches(t *testing.T) {
 	client := &mockClient{}
 
 	config := Config{
@@ -340,7 +340,7 @@ func TestExpectBranches(t *testing.T) {
 	e4.chain.assertNotFailed(t)
 }
 
-func TestExpectStdCompat(_ *testing.T) {
+func TestExpect_StdCompat(_ *testing.T) {
 	Default(&testing.T{}, "")
 	Default(&testing.B{}, "")
 	Default(testing.TB(&testing.T{}), "")
@@ -360,7 +360,7 @@ func (f *testRequestFactory) NewRequest(
 	return f.lastreq, nil
 }
 
-func TestExpectRequestFactory(t *testing.T) {
+func TestExpect_RequestFactory(t *testing.T) {
 	e1 := WithConfig(Config{
 		BaseURL:  "http://example.com",
 		Reporter: NewAssertReporter(t),
@@ -393,7 +393,7 @@ func TestExpectRequestFactory(t *testing.T) {
 	assert.Nil(t, f3.lastreq)
 }
 
-func TestExpectPanics(t *testing.T) {
+func TestExpect_Panics(t *testing.T) {
 	t.Run("nil_AssertionHandler_nonnil_Reporter", func(t *testing.T) {
 		assert.NotPanics(t, func() {
 			WithConfig(Config{
diff --git a/formatter_test.go b/formatter_test.go
index c55f0e8..8955649 100644
--- a/formatter_test.go
+++ b/formatter_test.go
@@ -9,13 +9,15 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+var mockDefaultFormatter = &DefaultFormatter{}
+
 type typedNil int
 
 func (*typedNil) String() string {
 	return ""
 }
 
-func TestFormatValues(t *testing.T) {
+func TestFormat_Values(t *testing.T) {
 	checkAll := func(t *testing.T, fn func(interface{}) string) {
 		var tnil *typedNil
 		var tnilPtr fmt.Stringer = tnil
@@ -45,39 +47,39 @@ func TestFormatValues(t *testing.T) {
 	}
 
 	t.Run("formatTypes", func(t *testing.T) {
-		checkAll(t, formatTyped)
+		checkAll(t, mockDefaultFormatter.formatTyped)
 	})
 
 	t.Run("formatValue", func(t *testing.T) {
-		checkAll(t, formatValue)
+		checkAll(t, mockDefaultFormatter.formatValue)
 	})
 
-	t.Run("formatString", func(t *testing.T) {
-		checkAll(t, formatString)
+	t.Run("formatBareString", func(t *testing.T) {
+		checkAll(t, mockDefaultFormatter.formatBareString)
 	})
 
 	t.Run("formatRange", func(t *testing.T) {
 		checkAll(t, func(v interface{}) string {
-			return strings.Join(formatRange(v), "")
+			return strings.Join(mockDefaultFormatter.formatRange(v), "")
 		})
 	})
 
 	t.Run("formatList", func(t *testing.T) {
 		checkAll(t, func(v interface{}) string {
-			return strings.Join(formatList(v), "")
+			return strings.Join(mockDefaultFormatter.formatList(v), "")
 		})
 	})
 }
 
-func TestFormatDiff(t *testing.T) {
+func TestFormat_Diff(t *testing.T) {
 	checkOK := func(a, b interface{}) {
-		s, ok := formatDiff(a, b)
+		s, ok := mockDefaultFormatter.formatDiff(a, b)
 		assert.True(t, ok)
 		assert.NotEqual(t, "", s)
 	}
 
 	checkNotOK := func(a, b interface{}) {
-		s, ok := formatDiff(a, b)
+		s, ok := mockDefaultFormatter.formatDiff(a, b)
 		assert.False(t, ok)
 		assert.Equal(t, "", s)
 	}
@@ -93,3 +95,459 @@ func TestFormatDiff(t *testing.T) {
 	checkOK(map[string]interface{}{"a": 1}, map[string]interface{}{})
 	checkOK([]interface{}{"a"}, []interface{}{})
 }
+
+func TestFormat_FailureActual(t *testing.T) {
+	tests := []struct {
+		name           string
+		assertionType  AssertionType
+		assertionValue interface{}
+		wantHaveActual bool
+		wantActual     string
+	}{
+		// AssertType
+		{
+			name:           "AssertType nil",
+			assertionType:  AssertType,
+			assertionValue: nil,
+			wantHaveActual: true,
+			wantActual:     "<nil>(<nil>)",
+		},
+		{
+			name:           "AssertType int",
+			assertionType:  AssertType,
+			assertionValue: int(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "int(1000000)",
+		},
+		{
+			name:           "AssertType float32",
+			assertionType:  AssertType,
+			assertionValue: float32(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "float32(1e+06)",
+		},
+		{
+			name:           "AssertType float64",
+			assertionType:  AssertType,
+			assertionValue: float64(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "float64(1e+06)",
+		},
+		{
+			name:           "AssertType string",
+			assertionType:  AssertType,
+			assertionValue: "test string",
+			wantHaveActual: true,
+			wantActual:     "string(\"test string\")",
+		},
+		{
+			name:           "AssertType object",
+			assertionType:  AssertType,
+			assertionValue: struct{ Name string }{"test name"},
+			wantHaveActual: true,
+			wantActual:     "struct { Name string }(struct { Name string }{Name:\"test name\"})",
+		},
+
+		// AssertValid
+		{
+			name:           "AssertValid nil",
+			assertionType:  AssertValid,
+			assertionValue: nil,
+			wantHaveActual: true,
+			wantActual:     "nil",
+		},
+		{
+			name:           "AssertValid int",
+			assertionType:  AssertValid,
+			assertionValue: int(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "1000000",
+		},
+		{
+			name:           "AssertValid float32",
+			assertionType:  AssertValid,
+			assertionValue: float32(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "1e+06",
+		},
+		{
+			name:           "AssertValid float64",
+			assertionType:  AssertValid,
+			assertionValue: float64(1_000_000),
+			wantHaveActual: true,
+			wantActual:     "1e+06",
+		},
+		{
+			name:           "AssertValid string",
+			assertionType:  AssertValid,
+			assertionValue: "test string",
+			wantHaveActual: true,
+			wantActual:     "\"test string\"",
+		},
+		{
+			name:           "AssertValid object",
+			assertionType:  AssertValid,
+			assertionValue: struct{ Name string }{"test name"},
+			wantHaveActual: true,
+			wantActual:     "{\n  \"Name\": \"test name\"\n}",
+		},
+	}
+
+	df := &DefaultFormatter{}
+	ctx := &AssertionContext{}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			fl := &AssertionFailure{
+				Type: tc.assertionType,
+				Actual: &AssertionValue{
+					Value: tc.assertionValue,
+				},
+			}
+			fd := df.buildFormatData(ctx, fl)
+			assert.Equal(t, tc.wantHaveActual, fd.HaveActual)
+			assert.Equal(t, tc.wantActual, fd.Actual)
+		})
+	}
+}
+
+func TestFormat_FailureExpected(t *testing.T) {
+	tests := []struct {
+		name             string
+		assertionType    AssertionType
+		assertionValue   interface{}
+		wantHaveExpected bool
+		wantExpectedKind string
+		wantExpected     []string
+	}{
+		// AssertInRange
+		{
+			name:          "AssertInRange nil",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: nil,
+				Max: nil,
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"<nil>", "<nil>"},
+		},
+		{
+			name:          "AssertInRange int",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: int(1_000_000),
+				Max: int(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"[1000000; 2000000]"},
+		},
+		{
+			name:          "AssertInRange float32",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: float32(1_000_000),
+				Max: float32(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"[1e+06; 2e+06]"},
+		},
+		{
+			name:          "AssertInRange float64",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: float64(1_000_000),
+				Max: float64(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"[1e+06; 2e+06]"},
+		},
+		{
+			name:          "AssertInRange string",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: "test string 1",
+				Max: "test string 2",
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"test string 1", "test string 2"},
+		},
+		{
+			name:          "AssertInRange object",
+			assertionType: AssertInRange,
+			assertionValue: AssertionRange{
+				Min: struct{ Name string }{"test name 1"},
+				Max: struct{ Name string }{"test name 2"},
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindRange,
+			wantExpected:     []string{"{test name 1}", "{test name 2}"},
+		},
+
+		// AssertMatchPath
+		{
+			name:             "AssertMatchPath nil",
+			assertionType:    AssertMatchPath,
+			assertionValue:   nil,
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"nil"},
+		},
+		{
+			name:             "AssertMatchPath int",
+			assertionType:    AssertMatchPath,
+			assertionValue:   int(1_000_000),
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"1000000"},
+		},
+		{
+			name:             "AssertMatchPath float32",
+			assertionType:    AssertMatchPath,
+			assertionValue:   float32(1_000_000),
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"1e+06"},
+		},
+		{
+			name:             "AssertMatchPath float64",
+			assertionType:    AssertMatchPath,
+			assertionValue:   float64(1_000_000),
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"1e+06"},
+		},
+		{
+			name:             "AssertMatchPath string",
+			assertionType:    AssertMatchPath,
+			assertionValue:   "test string",
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"test string"},
+		},
+		{
+			name:             "AssertMatchPath object",
+			assertionType:    AssertMatchPath,
+			assertionValue:   struct{ Name string }{"test name"},
+			wantHaveExpected: true,
+			wantExpectedKind: kindPath,
+			wantExpected:     []string{"{\n  \"Name\": \"test name\"\n}"},
+		},
+
+		// AssertMatchFormat
+		{
+			name:          "AssertMatchFormat nil",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				nil,
+				nil,
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected:     []string{"nil", "nil"},
+		},
+		{
+			name:          "AssertMatchFormat int",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				int(1_000_000),
+				int(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected:     []string{"1000000", "2000000"},
+		},
+		{
+			name:          "AssertMatchFormat float32",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				float32(1_000_000),
+				float32(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected:     []string{"1e+06", "2e+06"},
+		},
+		{
+			name:          "AssertMatchFormat float64",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				float64(1_000_000),
+				float64(2_000_000),
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected:     []string{"1e+06", "2e+06"},
+		},
+		{
+			name:          "AssertMatchFormat string",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				"test string 1",
+				"test string 2",
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected:     []string{"\"test string 1\"", "\"test string 2\""},
+		},
+		{
+			name:          "AssertMatchFormat object",
+			assertionType: AssertMatchFormat,
+			assertionValue: AssertionList{
+				struct{ Name string }{"test name 1"},
+				struct{ Name string }{"test name 2"},
+			},
+			wantHaveExpected: true,
+			wantExpectedKind: kindFormatList,
+			wantExpected: []string{
+				"{\n  \"Name\": \"test name 1\"\n}", "{\n  \"Name\": \"test name 2\"\n}",
+			},
+		},
+	}
+
+	df := &DefaultFormatter{}
+	ctx := &AssertionContext{}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			fl := &AssertionFailure{
+				Type: tc.assertionType,
+				Expected: &AssertionValue{
+					Value: tc.assertionValue,
+				},
+			}
+			fd := df.buildFormatData(ctx, fl)
+			assert.Equal(t, tc.wantHaveExpected, fd.HaveExpected)
+			assert.Equal(t, tc.wantExpectedKind, fd.ExpectedKind)
+			assert.Equal(t, tc.wantExpected, fd.Expected)
+		})
+	}
+}
+
+func TestFormat_FailureReference(t *testing.T) {
+	tests := []struct {
+		name              string
+		assertionValue    interface{}
+		wantHaveReference bool
+		wantReference     string
+	}{
+		{
+			name:              "nil",
+			assertionValue:    nil,
+			wantHaveReference: true,
+			wantReference:     "nil",
+		},
+		{
+			name:              "int",
+			assertionValue:    int(1_000_000),
+			wantHaveReference: true,
+			wantReference:     "1000000",
+		},
+		{
+			name:              "float32",
+			assertionValue:    float32(1_000_000),
+			wantHaveReference: true,
+			wantReference:     "1e+06",
+		},
+		{
+			name:              "float64",
+			assertionValue:    float64(1_000_000),
+			wantHaveReference: true,
+			wantReference:     "1e+06",
+		},
+		{
+			name:              "string",
+			assertionValue:    "test string",
+			wantHaveReference: true,
+			wantReference:     "\"test string\"",
+		},
+		{
+			name:              "object",
+			assertionValue:    struct{ Name string }{"test name"},
+			wantHaveReference: true,
+			wantReference:     "{\n  \"Name\": \"test name\"\n}",
+		},
+	}
+
+	df := &DefaultFormatter{}
+	ctx := &AssertionContext{}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			fl := &AssertionFailure{
+				Reference: &AssertionValue{
+					Value: tc.assertionValue,
+				},
+			}
+			fd := df.buildFormatData(ctx, fl)
+			assert.Equal(t, tc.wantHaveReference, fd.HaveReference)
+			assert.Equal(t, tc.wantReference, fd.Reference)
+		})
+	}
+}
+
+func TestFormat_FailureDelta(t *testing.T) {
+	tests := []struct {
+		name           string
+		assertionValue interface{}
+		wantHaveDelta  bool
+		wantDelta      string
+	}{
+		{
+			name:           "nil",
+			assertionValue: nil,
+			wantHaveDelta:  true,
+			wantDelta:      "nil",
+		},
+		{
+			name:           "int",
+			assertionValue: int(1_000_000),
+			wantHaveDelta:  true,
+			wantDelta:      "1000000",
+		},
+		{
+			name:           "float32",
+			assertionValue: float32(1_000_000),
+			wantHaveDelta:  true,
+			wantDelta:      "1e+06",
+		},
+		{
+			name:           "float64",
+			assertionValue: float64(1_000_000),
+			wantHaveDelta:  true,
+			wantDelta:      "1e+06",
+		},
+		{
+			name:           "string",
+			assertionValue: "test string",
+			wantHaveDelta:  true,
+			wantDelta:      "\"test string\"",
+		},
+		{
+			name:           "object",
+			assertionValue: struct{ Name string }{"test name"},
+			wantHaveDelta:  true,
+			wantDelta:      "{\n  \"Name\": \"test name\"\n}",
+		},
+	}
+
+	df := &DefaultFormatter{}
+	ctx := &AssertionContext{}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			fl := &AssertionFailure{
+				Delta: &AssertionValue{
+					Value: tc.assertionValue,
+				},
+			}
+			fd := df.buildFormatData(ctx, fl)
+			assert.Equal(t, tc.wantHaveDelta, fd.HaveDelta)
+			assert.Equal(t, tc.wantDelta, fd.Delta)
+		})
+	}
+}
diff --git a/match_test.go b/match_test.go
index 4789de2..c14a3d4 100644
--- a/match_test.go
+++ b/match_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestMatchFailed(t *testing.T) {
+func TestMatch_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -22,7 +22,7 @@ func TestMatchFailed(t *testing.T) {
 	value.NotValues("")
 }
 
-func TestMatchConstructors(t *testing.T) {
+func TestMatch_Constructors(t *testing.T) {
 	matches := []string{"m0", "m1", "m2"}
 	names := []string{"", "n1", "n2"}
 
@@ -41,9 +41,16 @@ func TestMatchConstructors(t *testing.T) {
 		assert.Equal(t, matches, value.Raw())
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newMatch(chain, matches, names)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestMatchGetters(t *testing.T) {
+func TestMatch_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	matches := []string{"m0", "m1", "m2"}
@@ -81,7 +88,7 @@ func TestMatchGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestMatchEmpty(t *testing.T) {
+func TestMatch_Empty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewMatch(reporter, []string{"m"}, nil)
@@ -116,7 +123,7 @@ func TestMatchEmpty(t *testing.T) {
 	value3.chain.clearFailed()
 }
 
-func TestMatchValues(t *testing.T) {
+func TestMatch_Values(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewMatch(reporter, []string{"m0", "m1", "m2"}, nil)
@@ -154,7 +161,7 @@ func TestMatchValues(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestMatchValuesEmpty(t *testing.T) {
+func TestMatch_ValuesEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewMatch(reporter, nil, nil)
diff --git a/number_test.go b/number_test.go
index 256a9e0..9980d02 100644
--- a/number_test.go
+++ b/number_test.go
@@ -7,7 +7,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestNumberFailed(t *testing.T) {
+func TestNumber_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -28,7 +28,7 @@ func TestNumberFailed(t *testing.T) {
 	value.NotInRange(0, 0)
 }
 
-func TestNumberConstructors(t *testing.T) {
+func TestNumber_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		value := NewNumber(reporter, 10.3)
@@ -44,9 +44,16 @@ func TestNumberConstructors(t *testing.T) {
 		value.Equal(10.3)
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newNumber(chain, 10.3)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestNumberGetters(t *testing.T) {
+func TestNumber_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 123.0)
@@ -68,7 +75,7 @@ func TestNumberGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberEqual(t *testing.T) {
+func TestNumber_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -92,7 +99,7 @@ func TestNumberEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberEqualDelta(t *testing.T) {
+func TestNumber_EqualDelta(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234.5)
@@ -130,7 +137,7 @@ func TestNumberEqualDelta(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberEqualNaN(t *testing.T) {
+func TestNumber_EqualNaN(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	v1 := NewNumber(reporter, math.NaN())
@@ -166,7 +173,7 @@ func TestNumberEqualNaN(t *testing.T) {
 	v8.chain.assertFailed(t)
 }
 
-func TestNumberGreater(t *testing.T) {
+func TestNumber_Greater(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -192,7 +199,7 @@ func TestNumberGreater(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberLesser(t *testing.T) {
+func TestNumber_Lesser(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -218,7 +225,7 @@ func TestNumberLesser(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberInRange(t *testing.T) {
+func TestNumber_InRange(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -280,7 +287,7 @@ func TestNumberInRange(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberConvertEqual(t *testing.T) {
+func TestNumber_ConvertEqual(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -310,7 +317,7 @@ func TestNumberConvertEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberConvertGreater(t *testing.T) {
+func TestNumber_ConvertGreater(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -340,7 +347,7 @@ func TestNumberConvertGreater(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberConvertLesser(t *testing.T) {
+func TestNumber_ConvertLesser(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
@@ -370,7 +377,7 @@ func TestNumberConvertLesser(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestNumberConvertInRange(t *testing.T) {
+func TestNumber_ConvertInRange(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 1234)
diff --git a/object_test.go b/object_test.go
index b407263..d1d01c7 100644
--- a/object_test.go
+++ b/object_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestObjectFailed(t *testing.T) {
+func TestObject_Failed(t *testing.T) {
 	check := func(value *Object) {
 		value.chain.assertFailed(t)
 
@@ -40,6 +40,18 @@ func TestObjectFailed(t *testing.T) {
 			value.String().NotEmpty()
 			return true
 		})
+		value.Find(func(key string, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
+		value.FindAll(func(key string, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
+		value.NotFind(func(key string, value *Value) bool {
+			value.String().NotEmpty()
+			return true
+		})
 	}
 
 	t.Run("failed_chain", func(t *testing.T) {
@@ -69,7 +81,7 @@ func TestObjectFailed(t *testing.T) {
 	})
 }
 
-func TestObjectConstructors(t *testing.T) {
+func TestObject_Constructors(t *testing.T) {
 	test := map[string]interface{}{
 		"foo": 100.0,
 	}
@@ -90,9 +102,15 @@ func TestObjectConstructors(t *testing.T) {
 		value.chain.assertNotFailed(t)
 	})
 
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newObject(chain, test)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestObjectGetters(t *testing.T) {
+func TestObject_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	m := map[string]interface{}{
@@ -165,7 +183,7 @@ func TestObjectGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectEmpty(t *testing.T) {
+func TestObject_Empty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewObject(reporter, nil)
@@ -195,7 +213,7 @@ func TestObjectEmpty(t *testing.T) {
 	value3.chain.clearFailed()
 }
 
-func TestObjectEqualEmpty(t *testing.T) {
+func TestObject_EqualEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{})
@@ -219,7 +237,7 @@ func TestObjectEqualEmpty(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectEqual(t *testing.T) {
+func TestObject_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{"foo": 123.0})
@@ -267,7 +285,7 @@ func TestObjectEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectEqualStruct(t *testing.T) {
+func TestObject_EqualStruct(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -312,7 +330,7 @@ func TestObjectEqualStruct(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsKey(t *testing.T) {
+func TestObject_ContainsKey(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{"foo": 123, "bar": ""})
@@ -342,7 +360,7 @@ func TestObjectContainsKey(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsValue(t *testing.T) {
+func TestObject_ContainsValue(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{"foo": 123, "bar": "xxx"})
@@ -372,7 +390,7 @@ func TestObjectContainsValue(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsValueStruct(t *testing.T) {
+func TestObject_ContainsValueStruct(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -422,7 +440,7 @@ func TestObjectContainsValueStruct(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsSubsetSuccess(t *testing.T) {
+func TestObject_ContainsSubsetSuccess(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -467,7 +485,7 @@ func TestObjectContainsSubsetSuccess(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsSubsetFailed(t *testing.T) {
+func TestObject_ContainsSubsetFailed(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -533,7 +551,7 @@ func TestObjectContainsSubsetFailed(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectContainsSubsetStruct(t *testing.T) {
+func TestObject_ContainsSubsetStruct(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -588,7 +606,7 @@ func TestObjectContainsSubsetStruct(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectValueEqual(t *testing.T) {
+func TestObject_ValueEqual(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -640,7 +658,7 @@ func TestObjectValueEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectValueEqualStruct(t *testing.T) {
+func TestObject_ValueEqualStruct(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewObject(reporter, map[string]interface{}{
@@ -689,7 +707,7 @@ func TestObjectValueEqualStruct(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectConvertEqual(t *testing.T) {
+func TestObject_ConvertEqual(t *testing.T) {
 	type (
 		myMap map[string]interface{}
 		myInt int
@@ -732,7 +750,7 @@ func TestObjectConvertEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectConvertContainsSubset(t *testing.T) {
+func TestObject_ConvertContainsSubset(t *testing.T) {
 	type (
 		myArray []interface{}
 		myMap   map[string]interface{}
@@ -763,7 +781,7 @@ func TestObjectConvertContainsSubset(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectConvertValueEqual(t *testing.T) {
+func TestObject_ConvertValueEqual(t *testing.T) {
 	type (
 		myArray []interface{}
 		myMap   map[string]interface{}
@@ -797,7 +815,7 @@ func TestObjectConvertValueEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestObjectEvery(t *testing.T) {
+func TestObject_Every(t *testing.T) {
 	t.Run("Check Validation", func(ts *testing.T) {
 		reporter := newMockReporter(ts)
 		object := NewObject(reporter, map[string]interface{}{
@@ -865,9 +883,27 @@ func TestObjectEvery(t *testing.T) {
 		object.chain.assertFailed(ts)
 		assert.Equal(t, 2, invoked)
 	})
+
+	t.Run("Every traverse fields is ordered", func(ts *testing.T) {
+		reporter := newMockReporter(ts)
+		object := NewObject(reporter, map[string]interface{}{
+			"bar": "123",
+			"baz": "456",
+			"foo": "foo",
+			"foz": "foo",
+			"b":   "789",
+			"c":   "987",
+		})
+		expectedOrder := []string{"b", "bar", "baz", "c", "foo", "foz"}
+		var actualOrder []string
+		object.Every(func(key string, val *Value) {
+			actualOrder = append(actualOrder, key)
+		})
+		assert.Equal(t, expectedOrder, actualOrder)
+	})
 }
 
-func TestObjectTransform(t *testing.T) {
+func TestObject_Transform(t *testing.T) {
 	t.Run("Add Hello", func(ts *testing.T) {
 		reporter := newMockReporter(ts)
 		object := NewObject(reporter, map[string]interface{}{
@@ -936,9 +972,26 @@ func TestObjectTransform(t *testing.T) {
 		})
 		newObject.chain.assertNotFailed(ts)
 	})
+
+	t.Run("Transform is ordered", func(ts *testing.T) {
+		reporter := newMockReporter(ts)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo": "123",
+			"bar": "456",
+			"b":   "456",
+			"baz": "baz",
+		})
+		expectedOrder := []string{"b", "bar", "baz", "foo"}
+		actualOrder := []string{}
+		object.Transform(func(key string, value interface{}) interface{} {
+			actualOrder = append(actualOrder, key)
+			return value
+		})
+		assert.Equal(t, expectedOrder, actualOrder)
+	})
 }
 
-func TestObjectFilter(t *testing.T) {
+func TestObject_Filter(t *testing.T) {
 	t.Run("Filter an object of elements of the same type and validate", func(ts *testing.T) {
 		reporter := newMockReporter(t)
 		object := NewObject(reporter, map[string]interface{}{
@@ -1028,4 +1081,453 @@ func TestObjectFilter(t *testing.T) {
 			filteredObject.chain.assertNotFailed(t)
 			object.chain.assertNotFailed(t)
 		})
+
+	t.Run("Filter is ordered", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  "qux",
+			"bar":  "qux",
+			"b":    "qux",
+			"quux": "corge",
+		})
+		expectedOrder := []string{"b", "bar", "baz", "foo", "quux"}
+		var actualOrder []string
+		object.Filter(func(key string, value *Value) bool {
+			actualOrder = append(actualOrder, key)
+			return false
+		})
+		assert.Equal(t, expectedOrder, actualOrder)
+	})
+}
+
+func TestObject_Find(t *testing.T) {
+	t.Run("Elements of the same type", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  "qux",
+			"quux": "corge",
+		})
+		foundValue := object.Find(func(key string, value *Value) bool {
+			return key == "baz"
+		})
+		assert.Equal(t, "qux", foundValue.Raw())
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  "qux",
+			"quux": "corge",
+		})
+
+		foundValue.chain.assertNotFailed(t)
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Elements of multiple types", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1,
+			"quux": 2,
+		})
+		foundValue := object.Find(func(key string, value *Value) bool {
+			n := value.Number().Raw()
+			return n > 1
+		})
+		assert.Equal(t, 2.0, foundValue.Raw())
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1.0,
+			"quux": 2.0,
+		})
+
+		foundValue.chain.assertNotFailed(t)
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("No match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1,
+			"quux": 2,
+		})
+		foundValue := object.Find(func(key string, value *Value) bool {
+			n := value.Number().Raw()
+			return n == 3
+		})
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1.0,
+			"quux": 2.0,
+		})
+
+		foundValue.chain.assertFailed(t)
+		object.chain.assertFailed(t)
+	})
+
+	t.Run("Empty object", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{})
+		foundValue := object.Find(func(key string, value *Value) bool {
+			n := value.Number().Raw()
+			return n == 3
+		})
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, object.Raw(), map[string]interface{}{})
+
+		foundValue.chain.assertFailed(t)
+		object.chain.assertFailed(t)
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			object := NewObject(reporter, map[string]interface{}{
+				"foo": 1,
+				"bar": 2,
+			})
+			foundValue := object.Find(func(key string, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Equal(t, nil, foundValue.Raw())
+			assert.Equal(t, object.Raw(), map[string]interface{}{
+				"foo": 1.0,
+				"bar": 2.0,
+			})
+
+			foundValue.chain.assertFailed(t)
+			object.chain.assertFailed(t)
+		})
+
+	t.Run("Predicate returns true, assertion fails, have match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			object := NewObject(reporter, map[string]interface{}{
+				"foo": 1,
+				"bar": 2,
+				"baz": "str",
+			})
+			foundValue := object.Find(func(key string, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Equal(t, "str", foundValue.Raw())
+			assert.Equal(t, object.Raw(), map[string]interface{}{
+				"foo": 1.0,
+				"bar": 2.0,
+				"baz": "str",
+			})
+
+			foundValue.chain.assertNotFailed(t)
+			object.chain.assertNotFailed(t)
+		})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo": 1,
+			"bar": 2,
+		})
+		foundValue := object.Find(nil)
+		assert.Equal(t, nil, foundValue.Raw())
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo": 1.0,
+			"bar": 2.0,
+		})
+
+		foundValue.chain.assertFailed(t)
+		object.chain.assertFailed(t)
+	})
+}
+
+func TestObject_FindAll(t *testing.T) {
+	t.Run("Elements of the same type", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  "qux",
+			"quux": "corge",
+		})
+		foundValues := object.FindAll(func(key string, value *Value) bool {
+			return key == "baz" || key == "quux"
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{"qux", "corge"}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  "qux",
+			"quux": "corge",
+		})
+
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Elements of multiple types", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":   "bar",
+			"baz":   6,
+			"qux":   "quux",
+			"corge": "grault",
+		})
+		foundValues := object.FindAll(func(key string, value *Value) bool {
+			value.String().NotEmpty()
+			return key != "qux"
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{"grault", "bar"}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":   "bar",
+			"baz":   6.0,
+			"qux":   "quux",
+			"corge": "grault",
+		})
+
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("No match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1,
+			"quux": 2,
+		})
+		foundValues := object.FindAll(func(key string, value *Value) bool {
+			return value.Number().Raw() == 3.0
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1.0,
+			"quux": 2.0,
+		})
+
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Empty object", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{})
+		foundValues := object.FindAll(func(key string, value *Value) bool {
+			return value.Number().Raw() == 3.0
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{})
+
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			object := NewObject(reporter, map[string]interface{}{
+				"foo": 1,
+				"bar": 2,
+			})
+			foundValues := object.FindAll(func(key string, value *Value) bool {
+				value.String()
+				return true
+			})
+
+			actual := []interface{}{}
+			for _, value := range foundValues {
+				actual = append(actual, value.Raw())
+			}
+
+			assert.Equal(t, []interface{}{}, actual)
+			assert.Equal(t, object.Raw(), map[string]interface{}{
+				"foo": 1.0,
+				"bar": 2.0,
+			})
+
+			for _, value := range foundValues {
+				value.chain.assertNotFailed(t)
+			}
+			object.chain.assertNotFailed(t)
+		})
+
+	t.Run("Predicate returns true, assertion fails, have match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  1,
+			"qux":  2,
+			"quux": "corge",
+		})
+		foundValues := object.FindAll(func(key string, value *Value) bool {
+			value.String()
+			return true
+		})
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{"bar", "corge"}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo":  "bar",
+			"baz":  1.0,
+			"qux":  2.0,
+			"quux": "corge",
+		})
+
+		for _, value := range foundValues {
+			value.chain.assertNotFailed(t)
+		}
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo": 1,
+			"bar": 2,
+		})
+		foundValues := object.FindAll(nil)
+
+		actual := []interface{}{}
+		for _, value := range foundValues {
+			actual = append(actual, value.Raw())
+		}
+
+		assert.Equal(t, []interface{}{}, actual)
+		assert.Equal(t, object.Raw(), map[string]interface{}{
+			"foo": 1.0,
+			"bar": 2.0,
+		})
+
+		for _, value := range foundValues {
+			value.chain.assertFailed(t)
+		}
+		object.chain.assertFailed(t)
+	})
+}
+
+func TestObject_NotFind(t *testing.T) {
+	t.Run("Succeeds if no element matches predicate", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1,
+			"quux": 2,
+		})
+		afterObject := object.NotFind(func(key string, value *Value) bool {
+			return key == "corge"
+		})
+		assert.Same(t, object, afterObject)
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Fails if there is a match", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo":  "bar",
+			"baz":  true,
+			"qux":  -1,
+			"quux": 2,
+		})
+		afterObject := object.NotFind(func(key string, value *Value) bool {
+			return key == "qux"
+		})
+		assert.Same(t, object, afterObject)
+		object.chain.assertFailed(t)
+	})
+
+	t.Run("Empty object", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{})
+		afterObject := object.NotFind(func(key string, value *Value) bool {
+			return key == "corge"
+		})
+		assert.Same(t, object, afterObject)
+		object.chain.assertNotFailed(t)
+	})
+
+	t.Run("Predicate returns true, assertion fails, no match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			object := NewObject(reporter, map[string]interface{}{
+				"foo": 1,
+				"bar": 2,
+			})
+			afterObject := object.NotFind(func(key string, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Same(t, object, afterObject)
+			object.chain.assertNotFailed(t)
+		})
+
+	t.Run("Predicate returns true, assertion fails, have match",
+		func(ts *testing.T) {
+			reporter := newMockReporter(t)
+			object := NewObject(reporter, map[string]interface{}{
+				"foo": 1,
+				"bar": 2,
+				"baz": "str",
+			})
+			afterObject := object.NotFind(func(key string, value *Value) bool {
+				value.String()
+				return true
+			})
+			assert.Same(t, object, afterObject)
+			object.chain.assertFailed(t)
+		})
+
+	t.Run("Predicate func is nil", func(ts *testing.T) {
+		reporter := newMockReporter(t)
+		object := NewObject(reporter, map[string]interface{}{
+			"foo": 1,
+			"bar": 2,
+		})
+		afterObject := object.NotFind(nil)
+		assert.Same(t, object, afterObject)
+		object.chain.assertFailed(t)
+	})
 }
diff --git a/printer_test.go b/printer_test.go
index 9bd278b..b62116b 100644
--- a/printer_test.go
+++ b/printer_test.go
@@ -7,7 +7,7 @@ import (
 	"testing"
 )
 
-func TestCompactPrinter(t *testing.T) {
+func TestPrinter_Compact(t *testing.T) {
 	printer := NewCompactPrinter(t)
 
 	body1 := bytes.NewBufferString("body1")
@@ -25,7 +25,7 @@ func TestCompactPrinter(t *testing.T) {
 	printer.Response(nil, 0)
 }
 
-func TestDebugPrinter(t *testing.T) {
+func TestPrinter_Debug(t *testing.T) {
 	printer := NewDebugPrinter(t, true)
 
 	body1 := bytes.NewBufferString("body1")
diff --git a/request_test.go b/request_test.go
index cfa4f69..78579fa 100644
--- a/request_test.go
+++ b/request_test.go
@@ -20,7 +20,7 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestRequestFailed(t *testing.T) {
+func TestRequest_Failed(t *testing.T) {
 	reporter := newMockReporter(t)
 	chain := newChainWithDefaults("test", reporter)
 	config := newMockConfig(reporter)
@@ -78,7 +78,7 @@ func TestRequestFailed(t *testing.T) {
 	resp.chain.assertFailed(t)
 }
 
-func TestRequestEmpty(t *testing.T) {
+func TestRequest_Empty(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -99,7 +99,7 @@ func TestRequestEmpty(t *testing.T) {
 	resp.chain.assertNotFailed(t)
 }
 
-func TestRequestTime(t *testing.T) {
+func TestRequest_Time(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -120,7 +120,7 @@ func TestRequestTime(t *testing.T) {
 	}
 }
 
-func TestRequestMatchers(t *testing.T) {
+func TestRequest_Matchers(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -149,7 +149,7 @@ func TestRequestMatchers(t *testing.T) {
 	assert.Same(t, resp, resps[0])
 }
 
-func TestRequestTransformers(t *testing.T) {
+func TestRequest_Transformers(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -218,7 +218,7 @@ func TestRequestTransformers(t *testing.T) {
 	})
 }
 
-func TestRequestClient(t *testing.T) {
+func TestRequest_Client(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client1 := &mockClient{}
@@ -246,7 +246,7 @@ func TestRequestClient(t *testing.T) {
 	req3.chain.assertFailed(t)
 }
 
-func TestRequestHandler(t *testing.T) {
+func TestRequest_Handler(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	var hr1 *http.Request
@@ -283,7 +283,7 @@ func TestRequestHandler(t *testing.T) {
 	req3.chain.assertFailed(t)
 }
 
-func TestRequestHandlerResetClient(t *testing.T) {
+func TestRequest_HandlerResetClient(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	var hr *http.Request
@@ -308,7 +308,7 @@ func TestRequestHandlerResetClient(t *testing.T) {
 	assert.Nil(t, client.req)
 }
 
-func TestRequestHandlerResueClient(t *testing.T) {
+func TestRequest_HandlerResueClient(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	handler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
@@ -333,7 +333,7 @@ func TestRequestHandlerResueClient(t *testing.T) {
 	assert.True(t, req.config.Client.(*http.Client).Jar == client.Jar)
 }
 
-func TestRequestProto(t *testing.T) {
+func TestRequest_Proto(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -368,7 +368,7 @@ func TestRequestProto(t *testing.T) {
 	assert.Equal(t, 0, req.httpReq.ProtoMinor)
 }
 
-func TestRequestURLConcatenate(t *testing.T) {
+func TestRequest_URLConcatenate(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -423,7 +423,7 @@ func TestRequestURLConcatenate(t *testing.T) {
 	assert.Equal(t, "http://example.com/", empty3.httpReq.URL.String())
 }
 
-func TestRequestURLOverwrite(t *testing.T) {
+func TestRequest_URLOverwrite(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -461,7 +461,7 @@ func TestRequestURLOverwrite(t *testing.T) {
 	}
 }
 
-func TestRequestURLInterpolate(t *testing.T) {
+func TestRequest_URLInterpolate(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -546,7 +546,7 @@ func TestRequestURLInterpolate(t *testing.T) {
 	r10.chain.assertFailed(t)
 }
 
-func TestRequestURLQuery(t *testing.T) {
+func TestRequest_URLQuery(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -615,7 +615,7 @@ func TestRequestURLQuery(t *testing.T) {
 		WithQueryString("%").chain.assertFailed(t)
 }
 
-func TestRequestHeaders(t *testing.T) {
+func TestRequest_Headers(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -655,7 +655,7 @@ func TestRequestHeaders(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestCookies(t *testing.T) {
+func TestRequest_Cookies(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -691,7 +691,7 @@ func TestRequestCookies(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBasicAuth(t *testing.T) {
+func TestRequest_BasicAuth(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -713,7 +713,7 @@ func TestRequestBasicAuth(t *testing.T) {
 		req.httpReq.Header.Get("Authorization"))
 }
 
-func TestRequestWithHost(t *testing.T) {
+func TestRequest_WithHost(t *testing.T) {
 	factory1 := DefaultRequestFactory{}
 	client1 := &mockClient{}
 	reporter1 := newMockReporter(t)
@@ -776,7 +776,7 @@ func TestRequestWithHost(t *testing.T) {
 	assert.Equal(t, "example1.com", client3.req.Host)
 }
 
-func TestRequestBodyChunked(t *testing.T) {
+func TestRequest_BodyChunked(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -807,7 +807,7 @@ func TestRequestBodyChunked(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyChunkedNil(t *testing.T) {
+func TestRequest_BodyChunkedNil(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -831,7 +831,7 @@ func TestRequestBodyChunkedNil(t *testing.T) {
 	assert.Equal(t, int64(0), client.req.ContentLength)
 }
 
-func TestRequestBodyChunkedProto(t *testing.T) {
+func TestRequest_BodyChunkedProto(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -864,7 +864,7 @@ func TestRequestBodyChunkedProto(t *testing.T) {
 	assert.Equal(t, 0, req2.httpReq.ProtoMinor)
 }
 
-func TestRequestBodyBytes(t *testing.T) {
+func TestRequest_BodyBytes(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -895,7 +895,7 @@ func TestRequestBodyBytes(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyBytesNil(t *testing.T) {
+func TestRequest_BodyBytesNil(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -919,7 +919,7 @@ func TestRequestBodyBytesNil(t *testing.T) {
 	assert.Equal(t, int64(0), client.req.ContentLength)
 }
 
-func TestRequestBodyText(t *testing.T) {
+func TestRequest_BodyText(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -956,7 +956,7 @@ func TestRequestBodyText(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyForm(t *testing.T) {
+func TestRequest_BodyForm(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -996,7 +996,7 @@ func TestRequestBodyForm(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyField(t *testing.T) {
+func TestRequest_BodyField(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1034,7 +1034,7 @@ func TestRequestBodyField(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyFormStruct(t *testing.T) {
+func TestRequest_BodyFormStruct(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1072,7 +1072,7 @@ func TestRequestBodyFormStruct(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyFormCombined(t *testing.T) {
+func TestRequest_BodyFormCombined(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1110,7 +1110,7 @@ func TestRequestBodyFormCombined(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestBodyMultipart(t *testing.T) {
+func TestRequest_BodyMultipart(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1165,7 +1165,7 @@ func TestRequestBodyMultipart(t *testing.T) {
 	assert.True(t, eof == nil)
 }
 
-func TestRequestBodyMultipartFile(t *testing.T) {
+func TestRequest_BodyMultipartFile(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1234,7 +1234,7 @@ func TestRequestBodyMultipartFile(t *testing.T) {
 	assert.True(t, eof == nil)
 }
 
-func TestRequestBodyJSON(t *testing.T) {
+func TestRequest_BodyJSON(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1271,7 +1271,7 @@ func TestRequestBodyJSON(t *testing.T) {
 	assert.Same(t, &client.resp, resp.Raw())
 }
 
-func TestRequestContentLength(t *testing.T) {
+func TestRequest_ContentLength(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1323,7 +1323,7 @@ func TestRequestContentLength(t *testing.T) {
 	assert.True(t, client.req.ContentLength > 0)
 }
 
-func TestRequestContentTypeOverwrite(t *testing.T) {
+func TestRequest_ContentTypeOverwrite(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1371,7 +1371,7 @@ func TestRequestContentTypeOverwrite(t *testing.T) {
 	assert.Equal(t, http.Header{"Content-Type": {"foo", "bar"}}, client.req.Header)
 }
 
-func TestRequestErrorMarshalForm(t *testing.T) {
+func TestRequest_ErrorMarshalForm(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1394,7 +1394,7 @@ func TestRequestErrorMarshalForm(t *testing.T) {
 	assert.True(t, resp.Raw() == nil)
 }
 
-func TestRequestErrorMarshalJSON(t *testing.T) {
+func TestRequest_ErrorMarshalJSON(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{}
@@ -1417,7 +1417,7 @@ func TestRequestErrorMarshalJSON(t *testing.T) {
 	assert.True(t, resp.Raw() == nil)
 }
 
-func TestRequestErrorReadFile(t *testing.T) {
+func TestRequest_ErrorReadFile(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{
@@ -1443,7 +1443,7 @@ func TestRequestErrorReadFile(t *testing.T) {
 	assert.True(t, resp.Raw() == nil)
 }
 
-func TestRequestErrorSend(t *testing.T) {
+func TestRequest_ErrorSend(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{
@@ -1466,7 +1466,7 @@ func TestRequestErrorSend(t *testing.T) {
 	assert.True(t, resp.Raw() == nil)
 }
 
-func TestRequestErrorConflictBody(t *testing.T) {
+func TestRequest_ErrorConflictBody(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{
@@ -1526,7 +1526,7 @@ func TestRequestErrorConflictBody(t *testing.T) {
 	req7.chain.assertFailed(t)
 }
 
-func TestRequestErrorConflictType(t *testing.T) {
+func TestRequest_ErrorConflictType(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{
@@ -1566,7 +1566,7 @@ func TestRequestErrorConflictType(t *testing.T) {
 	req4.chain.assertFailed(t)
 }
 
-func TestRequestErrorConflictMultipart(t *testing.T) {
+func TestRequest_ErrorConflictMultipart(t *testing.T) {
 	factory := DefaultRequestFactory{}
 
 	client := &mockClient{
@@ -1598,7 +1598,7 @@ func TestRequestErrorConflictMultipart(t *testing.T) {
 	req3.chain.assertFailed(t)
 }
 
-func TestRequestRedirect(t *testing.T) {
+func TestRequest_Redirect(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("dont follow redirects policy", func(t *testing.T) {
@@ -2123,7 +2123,7 @@ func TestRequestRedirect(t *testing.T) {
 	})
 }
 
-func TestRequestUsageChecks(t *testing.T) {
+func TestRequest_UsageChecks(t *testing.T) {
 	config := Config{
 		Reporter: newMockReporter(t),
 	}
@@ -2233,7 +2233,7 @@ func TestRequestUsageChecks(t *testing.T) {
 	})
 }
 
-func TestRequestPanics(t *testing.T) {
+func TestRequest_Panics(t *testing.T) {
 	t.Run("newRequest - RequestFactory is nil", func(t *testing.T) {
 		config := Config{
 			RequestFactory:   nil,
@@ -2353,7 +2353,7 @@ func (mt *mockTransportRedirect) WithMaxRedirect(
 	return mt
 }
 
-func TestRequestRetry(t *testing.T) {
+func TestRequest_Retry(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	newNoErrClient := func(cb func(req *http.Request)) *mockClient {
diff --git a/response_test.go b/response_test.go
index 9a303ea..545ed28 100644
--- a/response_test.go
+++ b/response_test.go
@@ -12,7 +12,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestResponseFailed(t *testing.T) {
+func TestResponse_Failed(t *testing.T) {
 	check := func(resp *Response) {
 		resp.chain.assertFailed(t)
 
@@ -96,7 +96,7 @@ func TestResponseFailed(t *testing.T) {
 	})
 }
 
-func TestResponseConstructors(t *testing.T) {
+func TestResponse_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		resp := NewResponse(reporter, &http.Response{})
@@ -110,9 +110,22 @@ func TestResponseConstructors(t *testing.T) {
 		}, &http.Response{})
 		resp.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		reporter := newMockReporter(t)
+		config := newMockConfig(reporter)
+		value := newResponse(responseOpts{
+			config:   config,
+			chain:    chain,
+			httpResp: &http.Response{},
+		})
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestResponseRoundTripTime(t *testing.T) {
+func TestResponse_RoundTripTime(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("set", func(t *testing.T) {
@@ -148,7 +161,7 @@ func TestResponseRoundTripTime(t *testing.T) {
 	})
 }
 
-func TestResponseDuration(t *testing.T) {
+func TestResponse_Duration(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("set", func(t *testing.T) {
@@ -178,7 +191,7 @@ func TestResponseDuration(t *testing.T) {
 	})
 }
 
-func TestResponseStatusRange(t *testing.T) {
+func TestResponse_StatusRange(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	ranges := []StatusRange{
@@ -224,7 +237,7 @@ func TestResponseStatusRange(t *testing.T) {
 	}
 }
 
-func TestResponseStatusList(t *testing.T) {
+func TestResponse_StatusList(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	cases := []struct {
@@ -267,7 +280,7 @@ func TestResponseStatusList(t *testing.T) {
 	}
 }
 
-func TestResponseHeaders(t *testing.T) {
+func TestResponse_Headers(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -306,7 +319,7 @@ func TestResponseHeaders(t *testing.T) {
 	resp.Header("Bad-Header").Empty().chain.assertNotFailed(t)
 }
 
-func TestResponseCookies(t *testing.T) {
+func TestResponse_Cookies(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -352,7 +365,7 @@ func TestResponseCookies(t *testing.T) {
 	assert.True(t, c3.Raw() == nil)
 }
 
-func TestResponseNoCookies(t *testing.T) {
+func TestResponse_NoCookies(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	httpResp := &http.Response{
@@ -374,7 +387,7 @@ func TestResponseNoCookies(t *testing.T) {
 	assert.True(t, c.Raw() == nil)
 }
 
-func TestResponseBody(t *testing.T) {
+func TestResponse_Body(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	httpResp := &http.Response{
@@ -389,7 +402,7 @@ func TestResponseBody(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseBodyClose(t *testing.T) {
+func TestResponse_BodyClose(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	body := newMockBody("test_body")
@@ -407,7 +420,7 @@ func TestResponseBodyClose(t *testing.T) {
 	resp.chain.assertNotFailed(t)
 }
 
-func TestResponseBodyError(t *testing.T) {
+func TestResponse_BodyError(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("read_err", func(t *testing.T) {
@@ -445,7 +458,7 @@ func TestResponseBodyError(t *testing.T) {
 	})
 }
 
-func TestResponseNoContentEmpty(t *testing.T) {
+func TestResponse_NoContentEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -489,7 +502,7 @@ func TestResponseNoContentEmpty(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseNoContentNil(t *testing.T) {
+func TestResponse_NoContentNil(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -533,7 +546,7 @@ func TestResponseNoContentNil(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseNoContentFailed(t *testing.T) {
+func TestResponse_NoContentFailed(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -559,7 +572,7 @@ func TestResponseNoContentFailed(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseContentType(t *testing.T) {
+func TestResponse_ContentType(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -599,7 +612,7 @@ func TestResponseContentType(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseContentTypeEmptyCharset(t *testing.T) {
+func TestResponse_ContentTypeEmptyCharset(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -623,7 +636,7 @@ func TestResponseContentTypeEmptyCharset(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseContentTypeInvalid(t *testing.T) {
+func TestResponse_ContentTypeInvalid(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers1 := map[string][]string{
@@ -659,7 +672,7 @@ func TestResponseContentTypeInvalid(t *testing.T) {
 	resp2.chain.clearFailed()
 }
 
-func TestResponseContentEncoding(t *testing.T) {
+func TestResponse_ContentEncoding(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -687,7 +700,7 @@ func TestResponseContentEncoding(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseTransferEncoding(t *testing.T) {
+func TestResponse_TransferEncoding(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	resp := NewResponse(reporter, &http.Response{
@@ -707,7 +720,7 @@ func TestResponseTransferEncoding(t *testing.T) {
 	resp.chain.clearFailed()
 }
 
-func TestResponseText(t *testing.T) {
+func TestResponse_Text(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -747,7 +760,7 @@ func TestResponseText(t *testing.T) {
 	assert.Equal(t, "hello, world!", resp.Text().Raw())
 }
 
-func TestResponseForm(t *testing.T) {
+func TestResponse_Form(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -792,7 +805,7 @@ func TestResponseForm(t *testing.T) {
 	assert.Equal(t, expected, resp.Form().Raw())
 }
 
-func TestResponseFormBadBody(t *testing.T) {
+func TestResponse_FormBadBody(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -816,7 +829,7 @@ func TestResponseFormBadBody(t *testing.T) {
 	assert.True(t, resp.Form().Raw() == nil)
 }
 
-func TestResponseFormBadType(t *testing.T) {
+func TestResponse_FormBadType(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -840,7 +853,7 @@ func TestResponseFormBadType(t *testing.T) {
 	assert.True(t, resp.Form().Raw() == nil)
 }
 
-func TestResponseJSON(t *testing.T) {
+func TestResponse_JSON(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -881,7 +894,7 @@ func TestResponseJSON(t *testing.T) {
 		map[string]interface{}{"key": "value"}, resp.JSON().Object().Raw())
 }
 
-func TestResponseJSONBadBody(t *testing.T) {
+func TestResponse_JSONBadBody(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -905,7 +918,7 @@ func TestResponseJSONBadBody(t *testing.T) {
 	assert.True(t, resp.JSON().Raw() == nil)
 }
 
-func TestResponseJSONCharsetEmpty(t *testing.T) {
+func TestResponse_JSONCharsetEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -930,7 +943,7 @@ func TestResponseJSONCharsetEmpty(t *testing.T) {
 		map[string]interface{}{"key": "value"}, resp.JSON().Object().Raw())
 }
 
-func TestResponseJSONCharsetBad(t *testing.T) {
+func TestResponse_JSONCharsetBad(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -954,7 +967,7 @@ func TestResponseJSONCharsetBad(t *testing.T) {
 	assert.Equal(t, nil, resp.JSON().Raw())
 }
 
-func TestResponseJSONP(t *testing.T) {
+func TestResponse_JSONP(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -1007,7 +1020,7 @@ func TestResponseJSONP(t *testing.T) {
 	}
 }
 
-func TestResponseJSONPBadBody(t *testing.T) {
+func TestResponse_JSONPBadBody(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -1036,7 +1049,7 @@ func TestResponseJSONPBadBody(t *testing.T) {
 	}
 }
 
-func TestResponseJSONPCharsetEmpty(t *testing.T) {
+func TestResponse_JSONPCharsetEmpty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -1061,7 +1074,7 @@ func TestResponseJSONPCharsetEmpty(t *testing.T) {
 		map[string]interface{}{"key": "value"}, resp.JSONP("foo").Object().Raw())
 }
 
-func TestResponseJSONPCharsetBad(t *testing.T) {
+func TestResponse_JSONPCharsetBad(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	headers := map[string][]string{
@@ -1085,7 +1098,7 @@ func TestResponseJSONPCharsetBad(t *testing.T) {
 	assert.Nil(t, resp.JSONP("foo").Raw())
 }
 
-func TestResponseContentOpts(t *testing.T) {
+func TestResponse_ContentOpts(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	type testCase struct {
@@ -1231,7 +1244,7 @@ func TestResponseContentOpts(t *testing.T) {
 	})
 }
 
-func TestResponseUsageChecks(t *testing.T) {
+func TestResponse_UsageChecks(t *testing.T) {
 	t.Run("NewResponse multiple rtt arguments", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		rtt := []time.Duration{time.Second, time.Second}
diff --git a/string_test.go b/string_test.go
index f16b8fa..d6611ce 100644
--- a/string_test.go
+++ b/string_test.go
@@ -8,7 +8,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestStringFailed(t *testing.T) {
+func TestString_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -46,7 +46,7 @@ func TestStringFailed(t *testing.T) {
 	value.NotIsASCII()
 }
 
-func TestStringConstructors(t *testing.T) {
+func TestString_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		value := NewString(reporter, "Hello")
@@ -62,9 +62,16 @@ func TestStringConstructors(t *testing.T) {
 		value.Equal("Hello")
 		value.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newString(chain, "Hello")
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestStringGetters(t *testing.T) {
+func TestString_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "foo")
@@ -86,7 +93,7 @@ func TestStringGetters(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringLength(t *testing.T) {
+func TestString_Length(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "1234567")
@@ -97,7 +104,7 @@ func TestStringLength(t *testing.T) {
 	assert.Equal(t, 7.0, num.Raw())
 }
 
-func TestStringEmpty(t *testing.T) {
+func TestString_Empty(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewString(reporter, "")
@@ -121,7 +128,7 @@ func TestStringEmpty(t *testing.T) {
 	value2.chain.clearFailed()
 }
 
-func TestStringEqual(t *testing.T) {
+func TestString_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "foo")
@@ -145,7 +152,7 @@ func TestStringEqual(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringEqualFold(t *testing.T) {
+func TestString_EqualFold(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "foo")
@@ -175,7 +182,7 @@ func TestStringEqualFold(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringContains(t *testing.T) {
+func TestString_Contains(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "11-foo-22")
@@ -197,7 +204,7 @@ func TestStringContains(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringContainsFold(t *testing.T) {
+func TestString_ContainsFold(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "11-foo-22")
@@ -227,7 +234,7 @@ func TestStringContainsFold(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringMatchOne(t *testing.T) {
+func TestString_MatchOne(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "http://example.com/users/john")
@@ -247,7 +254,7 @@ func TestStringMatchOne(t *testing.T) {
 		m2.submatches)
 }
 
-func TestStringMatchAll(t *testing.T) {
+func TestString_MatchAll(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter,
@@ -269,7 +276,7 @@ func TestStringMatchAll(t *testing.T) {
 		m[1].submatches)
 }
 
-func TestStringMatchStatus(t *testing.T) {
+func TestString_MatchStatus(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "a")
@@ -302,7 +309,7 @@ func TestStringMatchStatus(t *testing.T) {
 	assert.Equal(t, []Match{}, value.MatchAll(`[^a]`))
 }
 
-func TestStringMatchInvalid(t *testing.T) {
+func TestString_MatchInvalid(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "a")
@@ -320,7 +327,7 @@ func TestStringMatchInvalid(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringIsAscii(t *testing.T) {
+func TestString_IsAscii(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewString(reporter, "Ascii")
@@ -349,7 +356,7 @@ func TestStringIsAscii(t *testing.T) {
 	value5.chain.clearFailed()
 }
 
-func TestStringIsNotAscii(t *testing.T) {
+func TestString_IsNotAscii(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewString(reporter, "Ascii")
@@ -378,7 +385,7 @@ func TestStringIsNotAscii(t *testing.T) {
 	value5.chain.clearFailed()
 }
 
-func TestStringAsNumber(t *testing.T) {
+func TestString_AsNumber(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("default_base", func(t *testing.T) {
@@ -470,7 +477,7 @@ func TestStringAsNumber(t *testing.T) {
 	})
 }
 
-func TestStringAsBoolean(t *testing.T) {
+func TestString_AsBoolean(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	trueValues := []string{"true", "True"}
@@ -503,7 +510,7 @@ func TestStringAsBoolean(t *testing.T) {
 	}
 }
 
-func TestStringAsDateTime(t *testing.T) {
+func TestString_AsDateTime(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewString(reporter, "Tue, 15 Nov 1994 08:12:31 GMT")
@@ -561,7 +568,7 @@ func TestStringAsDateTime(t *testing.T) {
 	}
 }
 
-func TestStringHasPrefix(t *testing.T) {
+func TestString_HasPrefix(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "Hello World")
@@ -603,7 +610,7 @@ func TestStringHasPrefix(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringHasSuffix(t *testing.T) {
+func TestString_HasSuffix(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "Hello World")
@@ -645,7 +652,7 @@ func TestStringHasSuffix(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringHasPrefixFold(t *testing.T) {
+func TestString_HasPrefixFold(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "Hello World")
@@ -683,7 +690,7 @@ func TestStringHasPrefixFold(t *testing.T) {
 	value.chain.clearFailed()
 }
 
-func TestStringHasSuffixFold(t *testing.T) {
+func TestString_HasSuffixFold(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "Hello World")
diff --git a/value_test.go b/value_test.go
index 623bbc3..9e05d85 100644
--- a/value_test.go
+++ b/value_test.go
@@ -10,7 +10,7 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestValueFailed(t *testing.T) {
+func TestValue_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -40,7 +40,7 @@ func TestValueFailed(t *testing.T) {
 	value.NotEqual(nil)
 }
 
-func TestValueConstructors(t *testing.T) {
+func TestValue_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		value := NewValue(reporter, "Test")
@@ -58,9 +58,16 @@ func TestValueConstructors(t *testing.T) {
 		value.chain.assertNotFailed(t)
 		value.String().chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newValue(chain, "Test")
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestValueCastNull(t *testing.T) {
+func TestValue_CastNull(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	var data interface{}
@@ -74,7 +81,7 @@ func TestValueCastNull(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertNotFailed(t)
 }
 
-func TestValueCastIndirectNull(t *testing.T) {
+func TestValue_CastIndirectNull(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	var data []interface{}
@@ -88,7 +95,7 @@ func TestValueCastIndirectNull(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertNotFailed(t)
 }
 
-func TestValueCastBad(t *testing.T) {
+func TestValue_CastBad(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := func() {}
@@ -102,7 +109,7 @@ func TestValueCastBad(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueCastObject(t *testing.T) {
+func TestValue_CastObject(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := map[string]interface{}{}
@@ -116,7 +123,7 @@ func TestValueCastObject(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueCastArray(t *testing.T) {
+func TestValue_CastArray(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := []interface{}{}
@@ -130,7 +137,7 @@ func TestValueCastArray(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueCastString(t *testing.T) {
+func TestValue_CastString(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := ""
@@ -144,7 +151,7 @@ func TestValueCastString(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueCastNumber(t *testing.T) {
+func TestValue_CastNumber(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := 0.0
@@ -158,7 +165,7 @@ func TestValueCastNumber(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueCastBoolean(t *testing.T) {
+func TestValue_CastBoolean(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := false
@@ -172,7 +179,7 @@ func TestValueCastBoolean(t *testing.T) {
 	NewValue(reporter, data).Null().chain.assertFailed(t)
 }
 
-func TestValueGetObject(t *testing.T) {
+func TestValue_GetObject(t *testing.T) {
 	type (
 		myMap map[string]interface{}
 	)
@@ -198,7 +205,7 @@ func TestValueGetObject(t *testing.T) {
 	assert.Equal(t, map[string]interface{}(data2), inner2.Raw())
 }
 
-func TestValueGetArray(t *testing.T) {
+func TestValue_GetArray(t *testing.T) {
 	type (
 		myArray []interface{}
 	)
@@ -224,7 +231,7 @@ func TestValueGetArray(t *testing.T) {
 	assert.Equal(t, []interface{}(data2), inner2.Raw())
 }
 
-func TestValueGetString(t *testing.T) {
+func TestValue_GetString(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewValue(reporter, "foo")
@@ -235,7 +242,7 @@ func TestValueGetString(t *testing.T) {
 	assert.Equal(t, "foo", inner.Raw())
 }
 
-func TestValueGetNumber(t *testing.T) {
+func TestValue_GetNumber(t *testing.T) {
 	type (
 		myInt int
 	)
@@ -270,7 +277,7 @@ func TestValueGetNumber(t *testing.T) {
 	assert.Equal(t, float64(data3), inner3.Raw())
 }
 
-func TestValueGetBoolean(t *testing.T) {
+func TestValue_GetBoolean(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value1 := NewValue(reporter, true)
@@ -288,7 +295,7 @@ func TestValueGetBoolean(t *testing.T) {
 	assert.Equal(t, false, inner2.Raw())
 }
 
-func TestValueEqual(t *testing.T) {
+func TestValue_Equal(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data1 := map[string]interface{}{"foo": "bar"}
@@ -315,7 +322,7 @@ func TestValueEqual(t *testing.T) {
 	NewValue(reporter, data1).NotEqual(func() {}).chain.assertFailed(t)
 }
 
-func TestValuePathObject(t *testing.T) {
+func TestValue_PathObject(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	user0 := map[string]interface{}{"name": "john"}
@@ -352,7 +359,7 @@ func TestValuePathObject(t *testing.T) {
 	}
 }
 
-func TestValuePathArray(t *testing.T) {
+func TestValue_PathArray(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	user0 := map[string]interface{}{"name": "john"}
@@ -373,7 +380,7 @@ func TestValuePathArray(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestValuePathString(t *testing.T) {
+func TestValue_PathString(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := "foo"
@@ -384,7 +391,7 @@ func TestValuePathString(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestValuePathNumber(t *testing.T) {
+func TestValue_PathNumber(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := 123
@@ -395,7 +402,7 @@ func TestValuePathNumber(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestValuePathBoolean(t *testing.T) {
+func TestValue_PathBoolean(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := true
@@ -406,7 +413,7 @@ func TestValuePathBoolean(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestValuePathNull(t *testing.T) {
+func TestValue_PathNull(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewValue(reporter, nil)
@@ -415,7 +422,7 @@ func TestValuePathNull(t *testing.T) {
 	value.chain.assertNotFailed(t)
 }
 
-func TestValuePathError(t *testing.T) {
+func TestValue_PathError(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := "foo"
@@ -431,7 +438,7 @@ func TestValuePathError(t *testing.T) {
 }
 
 // based on github.com/yalp/jsonpath
-func TestValuePathExpressions(t *testing.T) {
+func TestValue_PathExpressions(t *testing.T) {
 	data := map[string]interface{}{
 		"A": []interface{}{
 			"string",
@@ -611,7 +618,7 @@ func TestValuePathExpressions(t *testing.T) {
 	})
 }
 
-func TestValuePathIntFloat(t *testing.T) {
+func TestValue_PathIntFloat(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	data := map[string]interface{}{
@@ -631,7 +638,7 @@ func TestValuePathIntFloat(t *testing.T) {
 	assert.Equal(t, 123.0, b.Raw())
 }
 
-func TestValueSchema(t *testing.T) {
+func TestValue_Schema(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	schema := `{
diff --git a/websocket_codes_test.go b/websocket_codes_test.go
index 74ca709..0dce63b 100644
--- a/websocket_codes_test.go
+++ b/websocket_codes_test.go
@@ -6,13 +6,13 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestWebsocketCodesMessageType(t *testing.T) {
+func TestWebsocketCodes_MessageType(t *testing.T) {
 	for n := 0; n < 100; n++ {
 		assert.NotEmpty(t, wsMessageType(n).String())
 	}
 }
 
-func TestWebsocketCodesCloseCode(t *testing.T) {
+func TestWebsocketCodes_CloseCode(t *testing.T) {
 	for n := 0; n < 2000; n++ {
 		assert.NotEmpty(t, wsCloseCode(n).String())
 	}
diff --git a/websocket_message_test.go b/websocket_message_test.go
index 30e57b1..ae7fd76 100644
--- a/websocket_message_test.go
+++ b/websocket_message_test.go
@@ -4,10 +4,11 @@ import (
 	"testing"
 
 	"github.com/gorilla/websocket"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
-func TestWebsocketMessageFailed(t *testing.T) {
+func TestWebsocketMessage_Failed(t *testing.T) {
 	chain := newMockChain(t)
 	chain.fail(mockFailure())
 
@@ -30,7 +31,7 @@ func TestWebsocketMessageFailed(t *testing.T) {
 	msg.JSON().chain.assertFailed(t)
 }
 
-func TestWebsocketMessageConstructors(t *testing.T) {
+func TestWebsocketMessage_Constructors(t *testing.T) {
 	t.Run("Constructor without config", func(t *testing.T) {
 		reporter := newMockReporter(t)
 		msg := NewWebsocketMessage(reporter, websocket.CloseMessage, nil)
@@ -46,9 +47,16 @@ func TestWebsocketMessageConstructors(t *testing.T) {
 		msg.CloseMessage()
 		msg.chain.assertNotFailed(t)
 	})
+
+	t.Run("chain Constructor", func(t *testing.T) {
+		chain := newMockChain(t)
+		value := newWebsocketMessage(chain, 0, nil)
+		assert.NotSame(t, value.chain, chain)
+		assert.Equal(t, value.chain.context.Path, chain.context.Path)
+	})
 }
 
-func TestWebsocketMessageBadUsage(t *testing.T) {
+func TestWebsocketMessage_BadUsage(t *testing.T) {
 	chain := newMockChain(t)
 
 	msg := newEmptyWebsocketMessage(chain)
@@ -72,7 +80,7 @@ func TestWebsocketMessageBadUsage(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageCloseMessage(t *testing.T) {
+func TestWebsocketMessage_CloseMessage(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	msg := NewWebsocketMessage(reporter, websocket.CloseMessage, nil, 1000)
@@ -134,7 +142,7 @@ func TestWebsocketMessageCloseMessage(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageTextMessage(t *testing.T) {
+func TestWebsocketMessage_TextMessage(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	msg := NewWebsocketMessage(reporter, websocket.TextMessage, nil, 0)
@@ -180,7 +188,7 @@ func TestWebsocketMessageTextMessage(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageBinaryMessage(t *testing.T) {
+func TestWebsocketMessage_BinaryMessage(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	msg := NewWebsocketMessage(reporter, websocket.BinaryMessage, nil, 0)
@@ -226,7 +234,7 @@ func TestWebsocketMessageBinaryMessage(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageMatchTypes(t *testing.T) {
+func TestWebsocketMessage_MatchTypes(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	msg := NewWebsocketMessage(reporter, websocket.TextMessage, nil, 0)
@@ -264,7 +272,7 @@ func TestWebsocketMessageMatchTypes(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageMatchCodes(t *testing.T) {
+func TestWebsocketMessage_MatchCodes(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	msg := NewWebsocketMessage(reporter, websocket.CloseMessage, nil, 10)
@@ -302,7 +310,7 @@ func TestWebsocketMessageMatchCodes(t *testing.T) {
 	msg.chain.clearFailed()
 }
 
-func TestWebsocketMessageCodeAndType(t *testing.T) {
+func TestWebsocketMessage_CodeAndType(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	m1 := NewWebsocketMessage(reporter, websocket.TextMessage, nil, 10)
@@ -326,7 +334,7 @@ func TestWebsocketMessageCodeAndType(t *testing.T) {
 	m2.chain.clearFailed()
 }
 
-func TestWebsocketMessageNoContent(t *testing.T) {
+func TestWebsocketMessage_NoContent(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("text", func(t *testing.T) {
@@ -358,7 +366,7 @@ func TestWebsocketMessageNoContent(t *testing.T) {
 	})
 }
 
-func TestWebsocketMessageBody(t *testing.T) {
+func TestWebsocketMessage_Body(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	body := []byte("test")
@@ -371,7 +379,7 @@ func TestWebsocketMessageBody(t *testing.T) {
 	require.Equal(t, "test", s.Raw())
 }
 
-func TestWebsocketMessageJSON(t *testing.T) {
+func TestWebsocketMessage_JSON(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	t.Run("good", func(t *testing.T) {
diff --git a/websocket_test.go b/websocket_test.go
index 21fe601..6040a56 100644
--- a/websocket_test.go
+++ b/websocket_test.go
@@ -10,7 +10,7 @@ import (
 
 func noWsPreSteps(ws *Websocket) {}
 
-func TestWebsocketFailed(t *testing.T) {
+func TestWebsocket_Failed(t *testing.T) {
 	reporter := newMockReporter(t)
 	chain := newChainWithDefaults("test", reporter)
 	config := newMockConfig(reporter)
@@ -44,7 +44,7 @@ func TestWebsocketFailed(t *testing.T) {
 	ws.Close()
 }
 
-func TestWebsocketNilConn(t *testing.T) {
+func TestWebsocket_NilConn(t *testing.T) {
 	config := Config{
 		Reporter: newMockReporter(t),
 	}
@@ -77,7 +77,7 @@ func TestWebsocketNilConn(t *testing.T) {
 	})
 }
 
-func TestWebsocketMockConn(t *testing.T) {
+func TestWebsocket_MockConn(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	config := Config{
@@ -112,7 +112,7 @@ func TestWebsocketMockConn(t *testing.T) {
 	})
 }
 
-func TestWebsocketExpect(t *testing.T) {
+func TestWebsocket_Expect(t *testing.T) {
 	type args struct {
 		failedChain bool
 		wsConn      WebsocketConn
@@ -201,7 +201,7 @@ func TestWebsocketExpect(t *testing.T) {
 	}
 }
 
-func TestWebsocketClose(t *testing.T) {
+func TestWebsocket_Close(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -272,7 +272,7 @@ func TestWebsocketClose(t *testing.T) {
 	}
 }
 
-func TestWebsocketCloseWithBytes(t *testing.T) {
+func TestWebsocket_CloseWithBytes(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -348,7 +348,7 @@ func TestWebsocketCloseWithBytes(t *testing.T) {
 	}
 }
 
-func TestWebsocketCloseWithText(t *testing.T) {
+func TestWebsocket_CloseWithText(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -424,7 +424,7 @@ func TestWebsocketCloseWithText(t *testing.T) {
 	}
 }
 
-func TestWebsocketCloseWithJSON(t *testing.T) {
+func TestWebsocket_CloseWithJSON(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -518,7 +518,7 @@ func TestWebsocketCloseWithJSON(t *testing.T) {
 	}
 }
 
-func TestWebsocketWriteMessage(t *testing.T) {
+func TestWebsocket_WriteMessage(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -659,7 +659,7 @@ func TestWebsocketWriteMessage(t *testing.T) {
 	}
 }
 
-func TestWebsocketWriteBytesBinary(t *testing.T) {
+func TestWebsocket_WriteBytesBinary(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -721,7 +721,7 @@ func TestWebsocketWriteBytesBinary(t *testing.T) {
 	}
 }
 
-func TestWebsocketWriteBytesText(t *testing.T) {
+func TestWebsocket_WriteBytesText(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -783,7 +783,7 @@ func TestWebsocketWriteBytesText(t *testing.T) {
 	}
 }
 
-func TestWebsocketWriteText(t *testing.T) {
+func TestWebsocket_WriteText(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -845,7 +845,7 @@ func TestWebsocketWriteText(t *testing.T) {
 	}
 }
 
-func TestWebsocketWriteJSON(t *testing.T) {
+func TestWebsocket_WriteJSON(t *testing.T) {
 	type args struct {
 		wsConn     WebsocketConn
 		wsPreSteps func(*Websocket)
@@ -922,7 +922,7 @@ func TestWebsocketWriteJSON(t *testing.T) {
 	}
 }
 
-func TestWebsocketSubprotocol(t *testing.T) {
+func TestWebsocket_Subprotocol(t *testing.T) {
 	subproto := "soap"
 	ws := NewWebsocketC(Config{
 		Reporter: NewAssertReporter(t),
@@ -935,7 +935,7 @@ func TestWebsocketSubprotocol(t *testing.T) {
 	}
 }
 
-func TestWebsocketSetReadDeadline(t *testing.T) {
+func TestWebsocket_SetReadDeadline(t *testing.T) {
 	type args struct {
 		wsConn WebsocketConn
 	}
@@ -980,7 +980,7 @@ func TestWebsocketSetReadDeadline(t *testing.T) {
 	}
 }
 
-func TestWebsocketSetWriteDeadline(t *testing.T) {
+func TestWebsocket_SetWriteDeadline(t *testing.T) {
 	type args struct {
 		wsConn WebsocketConn
 	}
@@ -1025,7 +1025,7 @@ func TestWebsocketSetWriteDeadline(t *testing.T) {
 	}
 }
 
-func TestWebsocketDisconnect(t *testing.T) {
+func TestWebsocket_Disconnect(t *testing.T) {
 	type args struct {
 		wsConn WebsocketConn
 	}
@@ -1076,7 +1076,7 @@ func TestWebsocketDisconnect(t *testing.T) {
 	}
 }
 
-func TestWebsocketPrintRead(t *testing.T) {
+func TestWebsocket_PrintRead(t *testing.T) {
 	reporter := newMockReporter(t)
 	printer := newMockWsPrinter()
 	config := Config{
@@ -1094,7 +1094,7 @@ func TestWebsocketPrintRead(t *testing.T) {
 	}
 }
 
-func TestWebsocketPrintWrite(t *testing.T) {
+func TestWebsocket_PrintWrite(t *testing.T) {
 	reporter := newMockReporter(t)
 	printer := newMockWsPrinter()
 	config := Config{