From b5daec6e7b19b0ab87e13ef85c4243e6c2916c96 Mon Sep 17 00:00:00 2001
From: Oleksandr Redko <Oleksandr_Redko@epam.com>
Date: Sat, 7 Oct 2023 22:28:36 +0300
Subject: [PATCH] test: Replace ifs with asserts to simplify tests

---
 flags_test.go                                 |   5 +-
 internal/encoding/decoder_test.go             |  32 +-
 internal/encoding/dotenv/codec_test.go        |  24 +-
 internal/encoding/encoder_test.go             |  31 +-
 internal/encoding/hcl/codec_test.go           |  24 +-
 internal/encoding/ini/codec_test.go           |  32 +-
 .../encoding/javaproperties/codec_test.go     |  36 +-
 internal/encoding/json/codec_test.go          |  24 +-
 internal/encoding/toml/codec_test.go          |  24 +-
 internal/encoding/yaml/codec_test.go          |  24 +-
 util_test.go                                  |  27 +-
 viper_test.go                                 | 369 +++++-------------
 12 files changed, 192 insertions(+), 460 deletions(-)

diff --git a/flags_test.go b/flags_test.go
index 171828d..0978439 100644
--- a/flags_test.go
+++ b/flags_test.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/spf13/pflag"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestBindFlagValueSet(t *testing.T) {
@@ -29,9 +30,7 @@ func TestBindFlagValueSet(t *testing.T) {
 	flagValueSet := pflagValueSet{flagSet}
 
 	err := BindFlagValues(flagValueSet)
-	if err != nil {
-		t.Fatalf("error binding flag set, %v", err)
-	}
+	require.NoError(t, err, "error binding flag set")
 
 	flagSet.VisitAll(func(flag *pflag.Flag) {
 		flag.Value.Set(mutatedTestValues[flag.Name])
diff --git a/internal/encoding/decoder_test.go b/internal/encoding/decoder_test.go
index 0cd49fb..7533e47 100644
--- a/internal/encoding/decoder_test.go
+++ b/internal/encoding/decoder_test.go
@@ -1,8 +1,10 @@
 package encoding
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 type decoder struct {
@@ -22,23 +24,17 @@ func TestDecoderRegistry_RegisterDecoder(t *testing.T) {
 		registry := NewDecoderRegistry()
 
 		err := registry.RegisterDecoder("myformat", decoder{})
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 	})
 
 	t.Run("AlreadyRegistered", func(t *testing.T) {
 		registry := NewDecoderRegistry()
 
 		err := registry.RegisterDecoder("myformat", decoder{})
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
 		err = registry.RegisterDecoder("myformat", decoder{})
-		if err != ErrDecoderFormatAlreadyRegistered {
-			t.Fatalf("expected ErrDecoderFormatAlreadyRegistered, got: %v", err)
-		}
+		assert.ErrorIs(t, err, ErrDecoderFormatAlreadyRegistered)
 	})
 }
 
@@ -52,20 +48,14 @@ func TestDecoderRegistry_Decode(t *testing.T) {
 		}
 
 		err := registry.RegisterDecoder("myformat", decoder)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
 		v := map[string]any{}
 
 		err = registry.Decode("myformat", []byte("key: value"), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(decoder.v, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %+v\nexpected: %+v", v, decoder.v)
-		}
+		assert.Equal(t, decoder.v, v)
 	})
 
 	t.Run("DecoderNotFound", func(t *testing.T) {
@@ -74,8 +64,6 @@ func TestDecoderRegistry_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := registry.Decode("myformat", nil, v)
-		if err != ErrDecoderNotFound {
-			t.Fatalf("expected ErrDecoderNotFound, got: %v", err)
-		}
+		assert.ErrorIs(t, err, ErrDecoderNotFound)
 	})
 }
diff --git a/internal/encoding/dotenv/codec_test.go b/internal/encoding/dotenv/codec_test.go
index f9a6fb4..8a446ed 100644
--- a/internal/encoding/dotenv/codec_test.go
+++ b/internal/encoding/dotenv/codec_test.go
@@ -1,8 +1,10 @@
 package dotenv
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -23,13 +25,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -39,13 +37,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(data, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, data)
-		}
+		assert.Equal(t, data, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -54,9 +48,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/internal/encoding/encoder_test.go b/internal/encoding/encoder_test.go
index 795e868..9dd5e7a 100644
--- a/internal/encoding/encoder_test.go
+++ b/internal/encoding/encoder_test.go
@@ -2,6 +2,9 @@ package encoding
 
 import (
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 type encoder struct {
@@ -17,23 +20,17 @@ func TestEncoderRegistry_RegisterEncoder(t *testing.T) {
 		registry := NewEncoderRegistry()
 
 		err := registry.RegisterEncoder("myformat", encoder{})
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 	})
 
 	t.Run("AlreadyRegistered", func(t *testing.T) {
 		registry := NewEncoderRegistry()
 
 		err := registry.RegisterEncoder("myformat", encoder{})
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
 		err = registry.RegisterEncoder("myformat", encoder{})
-		if err != ErrEncoderFormatAlreadyRegistered {
-			t.Fatalf("expected ErrEncoderFormatAlreadyRegistered, got: %v", err)
-		}
+		assert.ErrorIs(t, err, ErrEncoderFormatAlreadyRegistered)
 	})
 }
 
@@ -45,26 +42,18 @@ func TestEncoderRegistry_Decode(t *testing.T) {
 		}
 
 		err := registry.RegisterEncoder("myformat", encoder)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
 		b, err := registry.Encode("myformat", map[string]any{"key": "value"})
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if string(b) != "key: value" {
-			t.Fatalf("expected 'key: value', got: %#v", string(b))
-		}
+		assert.Equal(t, "key: value", string(b))
 	})
 
 	t.Run("EncoderNotFound", func(t *testing.T) {
 		registry := NewEncoderRegistry()
 
 		_, err := registry.Encode("myformat", map[string]any{"key": "value"})
-		if err != ErrEncoderNotFound {
-			t.Fatalf("expected ErrEncoderNotFound, got: %v", err)
-		}
+		assert.ErrorIs(t, err, ErrEncoderNotFound)
 	})
 }
diff --git a/internal/encoding/hcl/codec_test.go b/internal/encoding/hcl/codec_test.go
index e0b1ebc..8182c66 100644
--- a/internal/encoding/hcl/codec_test.go
+++ b/internal/encoding/hcl/codec_test.go
@@ -1,8 +1,10 @@
 package hcl
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -100,13 +102,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -116,13 +114,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(decoded, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, decoded)
-		}
+		assert.Equal(t, decoded, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -131,9 +125,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/internal/encoding/ini/codec_test.go b/internal/encoding/ini/codec_test.go
index 0b635d1..624e069 100644
--- a/internal/encoding/ini/codec_test.go
+++ b/internal/encoding/ini/codec_test.go
@@ -1,8 +1,10 @@
 package ini
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -48,13 +50,9 @@ func TestCodec_Encode(t *testing.T) {
 		codec := Codec{}
 
 		b, err := codec.Encode(data)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if encoded != string(b) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-		}
+		assert.Equal(t, encoded, string(b))
 	})
 
 	t.Run("Default", func(t *testing.T) {
@@ -70,13 +68,9 @@ func TestCodec_Encode(t *testing.T) {
 		}
 
 		b, err := codec.Encode(data)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if encoded != string(b) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-		}
+		assert.Equal(t, encoded, string(b))
 	})
 }
 
@@ -87,13 +81,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(decoded, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, decoded)
-		}
+		assert.Equal(t, decoded, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -102,9 +92,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/internal/encoding/javaproperties/codec_test.go b/internal/encoding/javaproperties/codec_test.go
index 7c4f898..4d521e8 100644
--- a/internal/encoding/javaproperties/codec_test.go
+++ b/internal/encoding/javaproperties/codec_test.go
@@ -1,8 +1,10 @@
 package javaproperties
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -28,13 +30,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -44,13 +42,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(data, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, data)
-		}
+		assert.Equal(t, data, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -62,9 +56,7 @@ func TestCodec_Decode(t *testing.T) {
 
 		codec.Decode([]byte(``), v)
 
-		if len(v) > 0 {
-			t.Fatalf("expected map to be empty when data is invalid\nactual: %#v", v)
-		}
+		assert.Empty(t, v)
 	})
 }
 
@@ -74,16 +66,10 @@ func TestCodec_DecodeEncode(t *testing.T) {
 	v := map[string]any{}
 
 	err := codec.Decode([]byte(original), v)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if original != string(b) {
-		t.Fatalf("encoded value does not match the original\nactual:   %#v\nexpected: %#v", string(b), original)
-	}
+	assert.Equal(t, original, string(b))
 }
diff --git a/internal/encoding/json/codec_test.go b/internal/encoding/json/codec_test.go
index a1ec360..1a05e48 100644
--- a/internal/encoding/json/codec_test.go
+++ b/internal/encoding/json/codec_test.go
@@ -1,8 +1,10 @@
 package json
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // encoded form of the data
@@ -55,13 +57,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -71,13 +69,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(encoded), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(data, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, data)
-		}
+		assert.Equal(t, data, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -86,9 +80,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/internal/encoding/toml/codec_test.go b/internal/encoding/toml/codec_test.go
index b52f117..c03f280 100644
--- a/internal/encoding/toml/codec_test.go
+++ b/internal/encoding/toml/codec_test.go
@@ -1,8 +1,10 @@
 package toml
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -65,13 +67,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -81,13 +79,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(data, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, data)
-		}
+		assert.Equal(t, data, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -96,9 +90,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/internal/encoding/yaml/codec_test.go b/internal/encoding/yaml/codec_test.go
index 1a00a83..4f998c0 100644
--- a/internal/encoding/yaml/codec_test.go
+++ b/internal/encoding/yaml/codec_test.go
@@ -1,8 +1,10 @@
 package yaml
 
 import (
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // original form of the data
@@ -96,13 +98,9 @@ func TestCodec_Encode(t *testing.T) {
 	codec := Codec{}
 
 	b, err := codec.Encode(data)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 
-	if encoded != string(b) {
-		t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", string(b), encoded)
-	}
+	assert.Equal(t, encoded, string(b))
 }
 
 func TestCodec_Decode(t *testing.T) {
@@ -112,13 +110,9 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(original), v)
-		if err != nil {
-			t.Fatal(err)
-		}
+		require.NoError(t, err)
 
-		if !reflect.DeepEqual(decoded, v) {
-			t.Fatalf("decoded value does not match the expected one\nactual:   %#v\nexpected: %#v", v, decoded)
-		}
+		assert.Equal(t, decoded, v)
 	})
 
 	t.Run("InvalidData", func(t *testing.T) {
@@ -127,9 +121,7 @@ func TestCodec_Decode(t *testing.T) {
 		v := map[string]any{}
 
 		err := codec.Decode([]byte(`invalid data`), v)
-		if err == nil {
-			t.Fatal("expected decoding to fail")
-		}
+		require.Error(t, err)
 
 		t.Logf("decoding failed as expected: %s", err)
 	})
diff --git a/util_test.go b/util_test.go
index 400d02d..8d0bda8 100644
--- a/util_test.go
+++ b/util_test.go
@@ -13,10 +13,10 @@ package viper
 import (
 	"os"
 	"path/filepath"
-	"reflect"
 	"testing"
 
 	slog "github.com/sagikazarmark/slog-shim"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestCopyAndInsensitiviseMap(t *testing.T) {
@@ -39,22 +39,15 @@ func TestCopyAndInsensitiviseMap(t *testing.T) {
 
 	got := copyAndInsensitiviseMap(given)
 
-	if !reflect.DeepEqual(got, expected) {
-		t.Fatalf("Got %q\nexpected\n%q", got, expected)
-	}
-
-	if _, ok := given["foo"]; ok {
-		t.Fatal("Input map changed")
-	}
-
-	if _, ok := given["bar"]; ok {
-		t.Fatal("Input map changed")
-	}
+	assert.Equal(t, expected, got)
+	_, ok := given["foo"]
+	assert.False(t, ok)
+	_, ok = given["bar"]
+	assert.False(t, ok)
 
 	m := given["Bar"].(map[any]any)
-	if _, ok := m["ABc"]; !ok {
-		t.Fatal("Input map changed")
-	}
+	_, ok = m["ABc"]
+	assert.True(t, ok)
 }
 
 func TestAbsPathify(t *testing.T) {
@@ -88,8 +81,6 @@ func TestAbsPathify(t *testing.T) {
 
 	for _, test := range tests {
 		got := absPathify(slog.Default(), test.input)
-		if got != test.output {
-			t.Errorf("Got %v\nexpected\n%q", got, test.output)
-		}
+		assert.Equal(t, test.output, got)
 	}
 }
diff --git a/viper_test.go b/viper_test.go
index e88b89f..6b1b316 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -8,7 +8,6 @@ package viper
 import (
 	"bytes"
 	"encoding/json"
-	"errors"
 	"io"
 	"os"
 	"os/exec"
@@ -507,9 +506,7 @@ func TestUnmarshalExact(t *testing.T) {
 	r := bytes.NewReader(yamlExampleWithExtras)
 	vip.ReadConfig(r)
 	err := vip.UnmarshalExact(target)
-	if err == nil {
-		t.Fatal("UnmarshalExact should error when populating a struct from a conf that contains unused fields")
-	}
+	assert.Error(t, err, "UnmarshalExact should error when populating a struct from a conf that contains unused fields")
 }
 
 func TestOverrides(t *testing.T) {
@@ -888,9 +885,7 @@ func TestUnmarshal(t *testing.T) {
 	var C config
 
 	err := Unmarshal(&C)
-	if err != nil {
-		t.Fatalf("unable to decode into struct, %v", err)
-	}
+	require.NoError(t, err, "unable to decode into struct")
 
 	assert.Equal(
 		t,
@@ -905,9 +900,7 @@ func TestUnmarshal(t *testing.T) {
 
 	Set("port", 1234)
 	err = Unmarshal(&C)
-	if err != nil {
-		t.Fatalf("unable to decode into struct, %v", err)
-	}
+	require.NoError(t, err, "unable to decode into struct")
 
 	assert.Equal(
 		t,
@@ -948,9 +941,7 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) {
 	var C config
 
 	err := Unmarshal(&C, opt)
-	if err != nil {
-		t.Fatalf("unable to decode into struct, %v", err)
-	}
+	require.NoError(t, err, "unable to decode into struct")
 
 	assert.Equal(t, &config{
 		Credentials: map[string]string{"foo": "bar"},
@@ -978,9 +969,7 @@ func TestBindPFlags(t *testing.T) {
 	}
 
 	err := v.BindPFlags(flagSet)
-	if err != nil {
-		t.Fatalf("error binding flag set, %v", err)
-	}
+	require.NoError(t, err, "error binding flag set")
 
 	flagSet.VisitAll(func(flag *pflag.Flag) {
 		flag.Value.Set(mutatedTestValues[flag.Name])
@@ -992,7 +981,6 @@ func TestBindPFlags(t *testing.T) {
 	}
 }
 
-//nolint:dupl
 func TestBindPFlagsStringSlice(t *testing.T) {
 	tests := []struct {
 		Expected []string
@@ -1019,17 +1007,14 @@ func TestBindPFlagsStringSlice(t *testing.T) {
 			})
 
 			err := v.BindPFlags(flagSet)
-			if err != nil {
-				t.Fatalf("error binding flag set, %v", err)
-			}
+			require.NoError(t, err, "error binding flag set")
 
 			type TestStr struct {
 				StringSlice []string
 			}
 			val := &TestStr{}
-			if err := v.Unmarshal(val); err != nil {
-				t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
-			}
+			err = v.Unmarshal(val)
+			require.NoError(t, err, "cannot unmarshal")
 			if changed {
 				assert.Equal(t, testValue.Expected, val.StringSlice)
 				assert.Equal(t, testValue.Expected, v.Get("stringslice"))
@@ -1040,7 +1025,6 @@ func TestBindPFlagsStringSlice(t *testing.T) {
 	}
 }
 
-//nolint:dupl
 func TestBindPFlagsStringArray(t *testing.T) {
 	tests := []struct {
 		Expected []string
@@ -1067,17 +1051,14 @@ func TestBindPFlagsStringArray(t *testing.T) {
 			})
 
 			err := v.BindPFlags(flagSet)
-			if err != nil {
-				t.Fatalf("error binding flag set, %v", err)
-			}
+			require.NoError(t, err, "error binding flag set")
 
 			type TestStr struct {
 				StringArray []string
 			}
 			val := &TestStr{}
-			if err := v.Unmarshal(val); err != nil {
-				t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
-			}
+			err = v.Unmarshal(val)
+			require.NoError(t, err, "cannot unmarshal")
 			if changed {
 				assert.Equal(t, testValue.Expected, val.StringArray)
 				assert.Equal(t, testValue.Expected, v.Get("stringarray"))
@@ -1099,18 +1080,11 @@ func TestSliceFlagsReturnCorrectType(t *testing.T) {
 
 	all := v.AllSettings()
 
-	if _, ok := all["int"].([]int); !ok {
-		t.Errorf("unexpected type %T expected []int", all["int"])
-	}
-	if _, ok := all["str"].([]string); !ok {
-		t.Errorf("unexpected type %T expected []string", all["str"])
-	}
-	if _, ok := all["duration"].([]time.Duration); !ok {
-		t.Errorf("unexpected type %T expected []time.Duration", all["duration"])
-	}
+	assert.IsType(t, []int{}, all["int"])
+	assert.IsType(t, []string{}, all["str"])
+	assert.IsType(t, []time.Duration{}, all["duration"])
 }
 
-//nolint:dupl
 func TestBindPFlagsIntSlice(t *testing.T) {
 	tests := []struct {
 		Expected []int
@@ -1136,17 +1110,14 @@ func TestBindPFlagsIntSlice(t *testing.T) {
 			})
 
 			err := v.BindPFlags(flagSet)
-			if err != nil {
-				t.Fatalf("error binding flag set, %v", err)
-			}
+			require.NoError(t, err, "error binding flag set")
 
 			type TestInt struct {
 				IntSlice []int
 			}
 			val := &TestInt{}
-			if err := v.Unmarshal(val); err != nil {
-				t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
-			}
+			err = v.Unmarshal(val)
+			require.NoError(t, err, "cannot unmarshal")
 			if changed {
 				assert.Equal(t, testValue.Expected, val.IntSlice)
 				assert.Equal(t, testValue.Expected, v.Get("intslice"))
@@ -1209,17 +1180,14 @@ func TestBindPFlagStringToString(t *testing.T) {
 			})
 
 			err := v.BindPFlags(flagSet)
-			if err != nil {
-				t.Fatalf("error binding flag set, %v", err)
-			}
+			require.NoError(t, err, "error binding flag set")
 
 			type TestMap struct {
 				StringToString map[string]string
 			}
 			val := &TestMap{}
-			if err := v.Unmarshal(val); err != nil {
-				t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
-			}
+			err = v.Unmarshal(val)
+			require.NoError(t, err, "cannot unmarshal")
 			if changed {
 				assert.Equal(t, testValue.Expected, val.StringToString)
 			} else {
@@ -1256,17 +1224,14 @@ func TestBindPFlagStringToInt(t *testing.T) {
 			})
 
 			err := v.BindPFlags(flagSet)
-			if err != nil {
-				t.Fatalf("error binding flag set, %v", err)
-			}
+			require.NoError(t, err, "error binding flag set")
 
 			type TestMap struct {
 				StringToInt map[string]int
 			}
 			val := &TestMap{}
-			if err := v.Unmarshal(val); err != nil {
-				t.Fatalf("%+#v cannot unmarshal: %s", testValue.Value, err)
-			}
+			err = v.Unmarshal(val)
+			require.NoError(t, err, "cannot unmarshal")
 			if changed {
 				assert.Equal(t, testValue.Expected, val.StringToInt)
 			} else {
@@ -1551,9 +1516,7 @@ var yamlInvalid = []byte(`hash: map
 
 func TestUnwrapParseErrors(t *testing.T) {
 	SetConfigType("yaml")
-	if !errors.As(ReadConfig(bytes.NewBuffer(yamlInvalid)), &ConfigParseError{}) {
-		t.Fatalf("not a ConfigParseError")
-	}
+	assert.ErrorAs(t, ReadConfig(bytes.NewBuffer(yamlInvalid)), &ConfigParseError{})
 }
 
 func TestSub(t *testing.T) {
@@ -1759,17 +1722,12 @@ func TestWriteConfig(t *testing.T) {
 			v.SetConfigType(tc.inConfigType)
 
 			err := v.ReadConfig(bytes.NewBuffer(tc.input))
-			if err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
 			v.SetConfigType(tc.outConfigType)
-			if err := v.WriteConfigAs(tc.fileName); err != nil {
-				t.Fatal(err)
-			}
+			err = v.WriteConfigAs(tc.fileName)
+			require.NoError(t, err)
 			read, err := afero.ReadFile(fs, tc.fileName)
-			if err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
 			assert.Equal(t, tc.expectedContent, read)
 		})
 	}
@@ -1804,12 +1762,9 @@ func TestWriteConfigTOML(t *testing.T) {
 			v.SetConfigName(tc.configName)
 			v.SetConfigType(tc.configType)
 			err := v.ReadConfig(bytes.NewBuffer(tc.input))
-			if err != nil {
-				t.Fatal(err)
-			}
-			if err := v.WriteConfigAs(tc.fileName); err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
+			err = v.WriteConfigAs(tc.fileName)
+			require.NoError(t, err)
 
 			// The TOML String method does not order the contents.
 			// Therefore, we must read the generated file and compare the data.
@@ -1819,9 +1774,7 @@ func TestWriteConfigTOML(t *testing.T) {
 			v2.SetConfigType(tc.configType)
 			v2.SetConfigFile(tc.fileName)
 			err = v2.ReadInConfig()
-			if err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
 
 			assert.Equal(t, v.GetString("title"), v2.GetString("title"))
 			assert.Equal(t, v.GetString("owner.bio"), v2.GetString("owner.bio"))
@@ -1859,12 +1812,9 @@ func TestWriteConfigDotEnv(t *testing.T) {
 			v.SetConfigName(tc.configName)
 			v.SetConfigType(tc.configType)
 			err := v.ReadConfig(bytes.NewBuffer(tc.input))
-			if err != nil {
-				t.Fatal(err)
-			}
-			if err := v.WriteConfigAs(tc.fileName); err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
+			err = v.WriteConfigAs(tc.fileName)
+			require.NoError(t, err)
 
 			// The TOML String method does not order the contents.
 			// Therefore, we must read the generated file and compare the data.
@@ -1874,9 +1824,7 @@ func TestWriteConfigDotEnv(t *testing.T) {
 			v2.SetConfigType(tc.configType)
 			v2.SetConfigFile(tc.fileName)
 			err = v2.ReadInConfig()
-			if err != nil {
-				t.Fatal(err)
-			}
+			require.NoError(t, err)
 
 			assert.Equal(t, v.GetString("title_dotenv"), v2.GetString("title_dotenv"))
 			assert.Equal(t, v.GetString("type_dotenv"), v2.GetString("type_dotenv"))
@@ -1927,13 +1875,10 @@ func TestSafeWriteAsConfig(t *testing.T) {
 	fs := afero.NewMemMapFs()
 	v.SetFs(fs)
 	err := v.ReadConfig(bytes.NewBuffer(yamlExample))
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 	require.NoError(t, v.SafeWriteConfigAs("/test/c.yaml"))
-	if _, err = afero.ReadFile(fs, "/test/c.yaml"); err != nil {
-		t.Fatal(err)
-	}
+	_, err = afero.ReadFile(fs, "/test/c.yaml")
+	require.NoError(t, err)
 }
 
 func TestSafeWriteConfigAsWithExistingFile(t *testing.T) {
@@ -2011,163 +1956,78 @@ var jsonMergeExampleSrc = []byte(`
 func TestMergeConfig(t *testing.T) {
 	v := New()
 	v.SetConfigType("yml")
-	if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil {
-		t.Fatal(err)
-	}
+	err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt))
+	require.NoError(t, err)
 
-	if pop := v.GetInt("hello.pop"); pop != 37890 {
-		t.Fatalf("pop != 37890, = %d", pop)
-	}
+	assert.Equal(t, 37890, v.GetInt("hello.pop"))
+	assert.Equal(t, int32(37890), v.GetInt32("hello.pop"))
+	assert.Equal(t, int64(765432101234567), v.GetInt64("hello.largenum"))
+	assert.Equal(t, uint(37890), v.GetUint("hello.pop"))
+	assert.Equal(t, uint16(37890), v.GetUint16("hello.pop"))
+	assert.Equal(t, uint32(37890), v.GetUint32("hello.pop"))
+	assert.Equal(t, uint64(9223372036854775808), v.GetUint64("hello.num2pow63"))
+	assert.Len(t, v.GetStringSlice("hello.world"), 4)
+	assert.Empty(t, v.GetString("fu"))
 
-	if pop := v.GetInt32("hello.pop"); pop != int32(37890) {
-		t.Fatalf("pop != 37890, = %d", pop)
-	}
+	err = v.MergeConfig(bytes.NewBuffer(yamlMergeExampleSrc))
+	require.NoError(t, err)
 
-	if pop := v.GetInt64("hello.largenum"); pop != int64(765432101234567) {
-		t.Fatalf("int64 largenum != 765432101234567, = %d", pop)
-	}
-
-	if pop := v.GetUint("hello.pop"); pop != 37890 {
-		t.Fatalf("uint pop != 37890, = %d", pop)
-	}
-
-	if pop := v.GetUint16("hello.pop"); pop != uint16(37890) {
-		t.Fatalf("uint pop != 37890, = %d", pop)
-	}
-
-	if pop := v.GetUint32("hello.pop"); pop != 37890 {
-		t.Fatalf("uint32 pop != 37890, = %d", pop)
-	}
-
-	if pop := v.GetUint64("hello.num2pow63"); pop != 9223372036854775808 {
-		t.Fatalf("uint64 num2pow63 != 9223372036854775808, = %d", pop)
-	}
-
-	if world := v.GetStringSlice("hello.world"); len(world) != 4 {
-		t.Fatalf("len(world) != 4, = %d", len(world))
-	}
-
-	if fu := v.GetString("fu"); fu != "" {
-		t.Fatalf("fu != \"\", = %s", fu)
-	}
-
-	if err := v.MergeConfig(bytes.NewBuffer(yamlMergeExampleSrc)); err != nil {
-		t.Fatal(err)
-	}
-
-	if pop := v.GetInt("hello.pop"); pop != 45000 {
-		t.Fatalf("pop != 45000, = %d", pop)
-	}
-
-	if pop := v.GetInt32("hello.pop"); pop != int32(45000) {
-		t.Fatalf("pop != 45000, = %d", pop)
-	}
-
-	if pop := v.GetInt64("hello.largenum"); pop != int64(7654321001234567) {
-		t.Fatalf("int64 largenum != 7654321001234567, = %d", pop)
-	}
-
-	if world := v.GetStringSlice("hello.world"); len(world) != 4 {
-		t.Fatalf("len(world) != 4, = %d", len(world))
-	}
-
-	if universe := v.GetStringSlice("hello.universe"); len(universe) != 2 {
-		t.Fatalf("len(universe) != 2, = %d", len(universe))
-	}
-
-	if ints := v.GetIntSlice("hello.ints"); len(ints) != 2 {
-		t.Fatalf("len(ints) != 2, = %d", len(ints))
-	}
-
-	if fu := v.GetString("fu"); fu != "bar" {
-		t.Fatalf("fu != \"bar\", = %s", fu)
-	}
+	assert.Equal(t, 45000, v.GetInt("hello.pop"))
+	assert.Equal(t, int32(45000), v.GetInt32("hello.pop"))
+	assert.Equal(t, int64(7654321001234567), v.GetInt64("hello.largenum"))
+	assert.Len(t, v.GetStringSlice("hello.world"), 4)
+	assert.Len(t, v.GetStringSlice("hello.universe"), 2)
+	assert.Len(t, v.GetIntSlice("hello.ints"), 2)
+	assert.Equal(t, "bar", v.GetString("fu"))
 }
 
 func TestMergeConfigOverrideType(t *testing.T) {
 	v := New()
 	v.SetConfigType("json")
-	if err := v.ReadConfig(bytes.NewBuffer(jsonMergeExampleTgt)); err != nil {
-		t.Fatal(err)
-	}
+	err := v.ReadConfig(bytes.NewBuffer(jsonMergeExampleTgt))
+	require.NoError(t, err)
 
-	if err := v.MergeConfig(bytes.NewBuffer(jsonMergeExampleSrc)); err != nil {
-		t.Fatal(err)
-	}
+	err = v.MergeConfig(bytes.NewBuffer(jsonMergeExampleSrc))
+	require.NoError(t, err)
 
-	if pop := v.GetString("hello.pop"); pop != "pop str" {
-		t.Fatalf("pop != \"pop str\", = %s", pop)
-	}
-
-	if foo := v.GetString("hello.foo"); foo != "foo str" {
-		t.Fatalf("foo != \"foo str\", = %s", foo)
-	}
+	assert.Equal(t, "pop str", v.GetString("hello.pop"))
+	assert.Equal(t, "foo str", v.GetString("hello.foo"))
 }
 
 func TestMergeConfigNoMerge(t *testing.T) {
 	v := New()
 	v.SetConfigType("yml")
-	if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil {
-		t.Fatal(err)
-	}
+	err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt))
+	require.NoError(t, err)
 
-	if pop := v.GetInt("hello.pop"); pop != 37890 {
-		t.Fatalf("pop != 37890, = %d", pop)
-	}
+	assert.Equal(t, 37890, v.GetInt("hello.pop"))
+	assert.Len(t, v.GetStringSlice("hello.world"), 4)
+	assert.Empty(t, v.GetString("fu"))
 
-	if world := v.GetStringSlice("hello.world"); len(world) != 4 {
-		t.Fatalf("len(world) != 4, = %d", len(world))
-	}
+	err = v.ReadConfig(bytes.NewBuffer(yamlMergeExampleSrc))
+	require.NoError(t, err)
 
-	if fu := v.GetString("fu"); fu != "" {
-		t.Fatalf("fu != \"\", = %s", fu)
-	}
-
-	if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleSrc)); err != nil {
-		t.Fatal(err)
-	}
-
-	if pop := v.GetInt("hello.pop"); pop != 45000 {
-		t.Fatalf("pop != 45000, = %d", pop)
-	}
-
-	if world := v.GetStringSlice("hello.world"); len(world) != 0 {
-		t.Fatalf("len(world) != 0, = %d", len(world))
-	}
-
-	if universe := v.GetStringSlice("hello.universe"); len(universe) != 2 {
-		t.Fatalf("len(universe) != 2, = %d", len(universe))
-	}
-
-	if ints := v.GetIntSlice("hello.ints"); len(ints) != 2 {
-		t.Fatalf("len(ints) != 2, = %d", len(ints))
-	}
-
-	if fu := v.GetString("fu"); fu != "bar" {
-		t.Fatalf("fu != \"bar\", = %s", fu)
-	}
+	assert.Equal(t, 45000, v.GetInt("hello.pop"))
+	assert.Empty(t, v.GetStringSlice("hello.world"))
+	assert.Len(t, v.GetStringSlice("hello.universe"), 2)
+	assert.Len(t, v.GetIntSlice("hello.ints"), 2)
+	assert.Equal(t, "bar", v.GetString("fu"))
 }
 
 func TestMergeConfigMap(t *testing.T) {
 	v := New()
 	v.SetConfigType("yml")
-	if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil {
-		t.Fatal(err)
-	}
+	err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt))
+	require.NoError(t, err)
 
-	assert := func(i int) {
+	assertFn := func(i int) {
 		large := v.GetInt64("hello.largenum")
 		pop := v.GetInt("hello.pop")
-		if large != 765432101234567 {
-			t.Fatal("Got large num:", large)
-		}
-
-		if pop != i {
-			t.Fatal("Got pop:", pop)
-		}
+		assert.Equal(t, int64(765432101234567), large)
+		assert.Equal(t, i, pop)
 	}
 
-	assert(37890)
+	assertFn(37890)
 
 	update := map[string]any{
 		"Hello": map[string]any{
@@ -2178,15 +2038,12 @@ func TestMergeConfigMap(t *testing.T) {
 		},
 	}
 
-	if err := v.MergeConfigMap(update); err != nil {
-		t.Fatal(err)
-	}
+	err = v.MergeConfigMap(update)
+	require.NoError(t, err)
 
-	if rock := v.GetInt("world.rock"); rock != 345 {
-		t.Fatal("Got rock:", rock)
-	}
+	assert.Equal(t, 345, v.GetInt("world.rock"))
 
-	assert(1234)
+	assertFn(1234)
 }
 
 func TestUnmarshalingWithAliases(t *testing.T) {
@@ -2207,9 +2064,7 @@ func TestUnmarshalingWithAliases(t *testing.T) {
 
 	var C config
 	err := v.Unmarshal(&C)
-	if err != nil {
-		t.Fatalf("unable to decode into struct, %v", err)
-	}
+	require.NoError(t, err, "unable to decode into struct")
 
 	assert.Equal(t, &config{ID: 1, FirstName: "Steve", Surname: "Owen"}, &C)
 }
@@ -2218,9 +2073,7 @@ func TestSetConfigNameClearsFileCache(t *testing.T) {
 	SetConfigFile("/tmp/config.yaml")
 	SetConfigName("default")
 	f, err := v.getConfigFile()
-	if err == nil {
-		t.Fatalf("config file cache should have been cleared")
-	}
+	require.Error(t, err, "config file cache should have been cleared")
 	assert.Empty(t, f)
 }
 
@@ -2330,38 +2183,18 @@ func TestCaseInsensitiveSet(t *testing.T) {
 	SetDefault("Number2", 52)
 
 	// Verify SetDefault
-	if v := Get("number2"); v != 52 {
-		t.Fatalf("Expected 52 got %q", v)
-	}
-
-	if v := Get("given2.foo"); v != 52 {
-		t.Fatalf("Expected 52 got %q", v)
-	}
-
-	if v := Get("given2.bar.bcd"); v != "A" {
-		t.Fatalf("Expected A got %q", v)
-	}
-
-	if _, ok := m2["Foo"]; !ok {
-		t.Fatal("Input map changed")
-	}
+	assert.Equal(t, 52, Get("number2"))
+	assert.Equal(t, 52, Get("given2.foo"))
+	assert.Equal(t, "A", Get("given2.bar.bcd"))
+	_, ok := m2["Foo"]
+	assert.True(t, ok)
 
 	// Verify Set
-	if v := Get("number1"); v != 42 {
-		t.Fatalf("Expected 42 got %q", v)
-	}
-
-	if v := Get("given1.foo"); v != 32 {
-		t.Fatalf("Expected 32 got %q", v)
-	}
-
-	if v := Get("given1.bar.abc"); v != "A" {
-		t.Fatalf("Expected A got %q", v)
-	}
-
-	if _, ok := m1["Foo"]; !ok {
-		t.Fatal("Input map changed")
-	}
+	assert.Equal(t, 42, Get("number1"))
+	assert.Equal(t, 32, Get("given1.foo"))
+	assert.Equal(t, "A", Get("given1.bar.abc"))
+	_, ok = m1["Foo"]
+	assert.True(t, ok)
 }
 
 func TestParseNested(t *testing.T) {
@@ -2384,9 +2217,7 @@ func TestParseNested(t *testing.T) {
 
 	var items []item
 	err := v.UnmarshalKey("parent", &items)
-	if err != nil {
-		t.Fatalf("unable to decode into struct, %v", err)
-	}
+	require.NoError(t, err, "unable to decode into struct")
 
 	assert.Len(t, items, 1)
 	assert.Equal(t, 100*time.Millisecond, items[0].Delay)