Repository: helm-unittest/helm-unittest

Issue:
Replace gopkg.in/yaml.v3 dependency as it is outdated and unmaintained
**Describe the bug**
There has been no activity on the `gopkg.in/yaml.v3` repo from its maintainers for over two years. There are over 100 open PRs and nearly 300 unresolved issues, including one from a contributor offering to take over maintainership. Most of the mentioned issues indirectly affect helm-unittest.

**To Reproduce**
Go to https://github.com/go-yaml/yaml and see there is no activity from the maintainer.

**Expected behavior**
helm-unittest uses up-to-date and maintained dependencies.



Hints from issue comments:
@ivankatliarchuk: There is no drop-in replacement. 

Example helm uses `sigs.k8s.io/yaml` which is a wrapper/fork `https://github.com/kubernetes-sigs/yaml/tree/master/goyaml.v3`@ivankatliarchuk: 5+ years old unmainted dependent library "https://github.com/dprotaso/go-yit" and 4+ unmainted library "github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"


Problem with `gopkg.in/yaml.v3` it uses no interfaces, so the only way is to rewrite things from the ground@quintush: Hello @V02460 

Thanks for the feedback.
As mentioned by @ivankatliarchuk there are more libraries outdated.

We have started isolating the libraries, and will make contact to other maintainers to see if they are also willing to update their libraries.

Currently some of the used libraries have functionality where I haven't found a replacement for.

Greetings,
@quintush @afalhambra-hivemq: Is there any update about this?@ivankatliarchuk: Helm itself still rely on same dependency https://github.com/helm/helm/blob/4d580c6b95760be89a5131fa4ca7cd9e13cec792/go.mod#L37

I manage to get quite close with https://github.com/goccy/go-yaml, but at the moment not convinced is not going to break things@ivankatliarchuk: Helm recently migrated to https://github.com/yaml/go-yaml/tree/main, is here https://github.com/helm/helm/blob/c5901abba66a634e5854bdc89fa10b0a392ae937/go.mod#L34 and kube yaml is migration to same library https://github.com/kubernetes-sigs/yaml/issues/18

Solution patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index d1abfa8..842b31b 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -117,7 +117,6 @@ jobs:
         image-ref: ${{ env.REGISTRY_IMAGE }}:${{ env.HELM_PLUGIN_VERSION }}
         format: sarif
         output: trivy-results.sarif
-        max_attempts: 3
 
     - name: Upload Trivy scan results to GitHub Security tab
       uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
diff --git a/.gitignore b/.gitignore
index 4c36290..11bd9fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@ _dist
 
 .idea
 
-.direnv
\ No newline at end of file
+.direnv
+cover.out
diff --git a/AlpineTest.Dockerfile b/AlpineTest.Dockerfile
index e8b1448..8891bcc 100644
--- a/AlpineTest.Dockerfile
+++ b/AlpineTest.Dockerfile
@@ -35,7 +35,6 @@ RUN apk upgrade --no-cache && \
 USER helmuser
 
 WORKDIR /apps
-
 VOLUME ["/apps"] 
 
 ENTRYPOINT ["helm", "unittest"]
diff --git a/Makefile b/Makefile
index 309c4f7..e749e9f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 
 # borrowed from https://github.com/technosophos/helm-template
 
-HELM_VERSION := 3.16.3
+HELM_VERSION := 3.16.4
 VERSION := $(shell sed -n -e 's/version:[ "]*\([^"]*\).*/\1/p' plugin.yaml)
 DIST := ./_dist
 LDFLAGS := "-X main.version=${VERSION} -extldflags '-static'"
@@ -28,8 +28,8 @@ help:
 
 .PHONY: plugin-dir
 plugin-dir:
-  HELM_3_PLUGINS := $(shell bash -c 'eval $$(helm env); echo $$HELM_PLUGINS')
-  HELM_PLUGIN_DIR := $(HELM_3_PLUGINS)/helm-unittest
+	HELM_3_PLUGINS := $(shell bash -c 'eval $$(helm env); echo $$HELM_PLUGINS')
+	HELM_PLUGIN_DIR := $(HELM_3_PLUGINS)/helm-unittest
 
 .PHONY: install
 install: bootstrap build plugin-dir
@@ -47,15 +47,20 @@ install-dbg: bootstrap build-debug plugin-dir
 hookInstall: bootstrap build
 
 .PHONY: unittest
-unittest: ## Run unit tests
+unittest: build ## Run unit tests
 	go test ./... -v -cover
 
+.PHONY: test-coverage
+test-coverage: build ## Test coverage with open report in default browser
+	@go test -cover -coverprofile=cover.out -v ./...
+	@go tool cover -html=cover.out
+
 .PHONY: build-debug
 build-debug: ## Compile packages and dependencies with debug flag
 	go build -o untt-dbg -gcflags "all=-N -l" ./cmd/helm-unittest
 
 .PHONY: build
-build: unittest ## Compile packages and dependencies
+build: ## Compile packages and dependencies
 	go build -o untt -ldflags $(LDFLAGS) ./cmd/helm-unittest
 
 .PHONY: dist
@@ -89,7 +94,7 @@ dependency: ## Dependency maintanance
 	go mod tidy
 
 .PHONY: dockerimage
-dockerimage: build
+dockerimage: unittest ## Build docker image
 	docker build --no-cache --build-arg HELM_VERSION=$(HELM_VERSION) -t $(DOCKER):$(VERSION) -f AlpineTest.Dockerfile .
 
 .PHONY: test-docker
@@ -97,6 +102,6 @@ test-docker: dockerimage ## Execute 'helm unittests' in container
 	@for f in $(TEST_NAMES); do \
 		echo "running helm unit tests in folder '$(PROJECT_DIR)/test/data/v3/$${f}'"; \
 		docker run \
-			-v $(PROJECT_DIR)/test/data/v3/$${f}:/apps \
+			-v $(PROJECT_DIR)/test/data/v3/$${f}:/apps:z \
 			--rm  $(DOCKER):$(VERSION) -f tests/*.yaml .;\
 	done
diff --git a/go.mod b/go.mod
index 7fd3916..de9ec2a 100644
--- a/go.mod
+++ b/go.mod
@@ -10,13 +10,14 @@ require (
 	github.com/mitchellh/mapstructure v1.5.0
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
 	github.com/spf13/cobra v1.8.1
-	github.com/stretchr/testify v1.9.0
+	github.com/stretchr/testify v1.10.0
 	github.com/vmware-labs/yaml-jsonpath v0.3.2
 	github.com/yargevad/filepathx v1.0.0
 	gopkg.in/yaml.v3 v3.0.1
-	helm.sh/helm/v3 v3.16.3
-	k8s.io/apimachinery v0.31.3
-	k8s.io/client-go v0.31.3
+	helm.sh/helm/v3 v3.16.4
+	k8s.io/apimachinery v0.32.0
+	k8s.io/client-go v0.32.0
+	sigs.k8s.io/yaml v1.4.0
 )
 
 require (
@@ -25,7 +26,7 @@ require (
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.3.1 // indirect
 	github.com/Masterminds/sprig/v3 v3.3.0 // indirect
-	github.com/cyphar/filepath-securejoin v0.3.4 // indirect
+	github.com/cyphar/filepath-securejoin v0.3.6 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/dprotaso/go-yit v0.0.0-20240618133044-5a0af90af097 // indirect
 	github.com/emicklei/go-restful/v3 v3.12.1 // indirect
@@ -37,7 +38,7 @@ require (
 	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
-	github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
+	github.com/google/gnostic-models v0.6.9 // indirect
 	github.com/google/go-cmp v0.6.0 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/google/uuid v1.6.0 // indirect
@@ -45,7 +46,7 @@ require (
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mailru/easyjson v0.9.0 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/mitchellh/reflectwalk v1.0.2 // indirect
@@ -56,29 +57,28 @@ require (
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/shopspring/decimal v1.4.0 // indirect
 	github.com/sirupsen/logrus v1.9.3
-	github.com/spf13/cast v1.7.0 // indirect
+	github.com/spf13/cast v1.7.1 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
 	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
 	github.com/xeipuuv/gojsonschema v1.2.0
-	golang.org/x/crypto v0.29.0 // indirect
-	golang.org/x/net v0.31.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
 	golang.org/x/oauth2 v0.24.0 // indirect
-	golang.org/x/sys v0.27.0 // indirect
-	golang.org/x/term v0.26.0 // indirect
-	golang.org/x/text v0.20.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.8.0 // indirect
-	google.golang.org/protobuf v1.35.2 // indirect
+	google.golang.org/protobuf v1.36.1 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
-	k8s.io/api v0.31.3 // indirect
-	k8s.io/apiextensions-apiserver v0.31.3 // indirect
+	k8s.io/api v0.32.0 // indirect
+	k8s.io/apiextensions-apiserver v0.32.0 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
-	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
-	k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
+	k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
+	k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
 	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect
-	sigs.k8s.io/yaml v1.4.0
+	sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 545f8bf..dda7f37 100644
--- a/go.sum
+++ b/go.sum
@@ -16,8 +16,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
 github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
-github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
+github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
+github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -64,8 +64,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
-github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU=
-github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M=
+github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
+github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -77,8 +77,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
+github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
+github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -100,8 +100,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
+github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -130,15 +130,15 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
-github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
-github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
+github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
+github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
-github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
-github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
+github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
+github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -153,8 +153,8 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp
 github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
-github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
 github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -168,8 +168,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk=
 github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@@ -188,8 +188,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
-golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -200,8 +200,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
-golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
 golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -225,18 +225,18 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
-golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 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.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
-golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 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.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
-golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
 golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -244,8 +244,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
-golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
+golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
+golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -258,8 +258,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
-google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
+google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -281,25 +281,25 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-helm.sh/helm/v3 v3.16.3 h1:kb8bSxMeRJ+knsK/ovvlaVPfdis0X3/ZhYCSFRP+YmY=
-helm.sh/helm/v3 v3.16.3/go.mod h1:zeVWGDR4JJgiRbT3AnNsjYaX8OTJlIE9zC+Q7F7iUSU=
-k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
-k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
-k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE=
-k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4=
-k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
-k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
-k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4=
-k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs=
+helm.sh/helm/v3 v3.16.4 h1:rBn/h9MACw+QlhxQTjpl8Ifx+VTWaYsw3rguGBYBzr0=
+helm.sh/helm/v3 v3.16.4/go.mod h1:k8QPotUt57wWbi90w3LNmg3/MWcLPigVv+0/X4B8BzA=
+k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
+k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
+k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
+k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
+k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
+k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
+k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
-k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
-k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
-k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
+k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
+k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
+k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/internal/common/utilities.go b/internal/common/utilities.go
index 6f7a412..8506b08 100644
--- a/internal/common/utilities.go
+++ b/internal/common/utilities.go
@@ -3,14 +3,39 @@ package common
 import (
 	"bytes"
 	"strings"
+	"testing"
 
-	yaml "gopkg.in/yaml.v3"
+	"io"
+
+	"github.com/stretchr/testify/assert"
+	yamlv3 "gopkg.in/yaml.v3"
+	yaml "sigs.k8s.io/yaml"
 )
 
+type YamlNode struct {
+	Node yamlv3.Node
+}
+
+func NewYamlNode() YamlNode {
+	return YamlNode{
+		Node: yamlv3.Node{},
+	}
+}
+
+// YamlNewDecoder returns a new decoder that reads from r.
+func YamlNewDecoder(r io.Reader) *yamlv3.Decoder {
+	return yamlv3.NewDecoder(r)
+}
+
+// YamlNewEncoder returns a new encoder that writes to w.
+func YamlNewEncoder(w io.Writer) *yamlv3.Encoder {
+	return yamlv3.NewEncoder(w)
+}
+
 // TrustedMarshalYAML marshal yaml without error returned, if an error happens it panics
 func TrustedMarshalYAML(d interface{}) string {
 	byteBuffer := new(bytes.Buffer)
-	yamlEncoder := yaml.NewEncoder(byteBuffer)
+	yamlEncoder := yamlv3.NewEncoder(byteBuffer)
 	yamlEncoder.SetIndent(YAMLINDENTION)
 	defer yamlEncoder.Close()
 	if err := yamlEncoder.Encode(d); err != nil {
@@ -22,9 +47,39 @@ func TrustedMarshalYAML(d interface{}) string {
 // TrustedUnmarshalYAML unmarshal yaml without error returned, if an error happens it panics
 func TrustedUnmarshalYAML(d string) map[string]interface{} {
 	parsedYaml := K8sManifest{}
-	yamlDecoder := yaml.NewDecoder(strings.NewReader(d))
+	yamlDecoder := yamlv3.NewDecoder(strings.NewReader(d))
 	if err := yamlDecoder.Decode(&parsedYaml); err != nil {
 		panic(err)
 	}
 	return parsedYaml
 }
+
+func YamlToJson(in string) ([]byte, error) {
+	return yaml.YAMLToJSON([]byte(in))
+}
+
+func YmlUnmarshal(in string, out interface{}) error {
+	err := yamlv3.Unmarshal([]byte(in), out)
+	return err
+}
+
+func YmlMarshall(in interface{}) (string, error) {
+	out, err := yaml.Marshal(in)
+	if err != nil {
+		return "", err
+	}
+	return string(out), nil
+}
+
+func YmlUnmarshalTestHelper(input string, out any, t *testing.T) {
+	t.Helper()
+	err := YmlUnmarshal(input, out)
+	assert.NoError(t, err)
+}
+
+func YmlMarshallTestHelper(in interface{}, t *testing.T) string {
+	t.Helper()
+	out, err := yaml.Marshal(in)
+	assert.NoError(t, err)
+	return string(out)
+}
diff --git a/sonar-project.properties b/sonar-project.properties
index 70851fc..a30b898 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -3,7 +3,7 @@ sonar.organization=helm-unittest
 
 # This is the name and version displayed in the SonarCloud UI.
 sonar.projectName=helm-unittest
-sonar.projectVersion=0.7.0
+sonar.projectVersion=0.7.1
  
 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
 # Define all sources and exclude test-, and vendor files.



Test patch:
diff --git a/pkg/unittest/.snapshots/TestV3RunnerOkWithAbsoluteOverrideValuesPassedTests b/pkg/unittest/.snapshots/TestV3RunnerOkWithAbsoluteOverrideValuesPassedTests
index b407d3b..d2f3986 100644
--- a/pkg/unittest/.snapshots/TestV3RunnerOkWithAbsoluteOverrideValuesPassedTests
+++ b/pkg/unittest/.snapshots/TestV3RunnerOkWithAbsoluteOverrideValuesPassedTests
@@ -12,13 +12,14 @@
  PASS  test ingress	../../test/data/v3/basic/tests/ingress_test.yaml
  PASS  test notes	../../test/data/v3/basic/tests/notes_test.yaml
  PASS  test override names and fullNames in Kubernetes resources	../../test/data/v3/basic/tests/namesOverride_test.yaml
+ PASS  test pod disruption budget	../../test/data/v3/basic/tests/pdp_test.yaml
  PASS  test service	../../test/data/v3/basic/tests/service_test.yaml
  PASS  test service account	../../test/data/v3/basic/tests/serviceaccount_test.yaml
 
 
 Charts:      1 passed, 1 total
-Test Suites: 12 passed, 12 total
-Tests:       33 passed, 33 total
+Test Suites: 13 passed, 13 total
+Tests:       41 passed, 41 total
 Snapshot:    4 passed, 4 total
 Time:        XX.XXXms
 
diff --git a/pkg/unittest/.snapshots/TestV3RunnerOkWithOverrideValuesPassedTests b/pkg/unittest/.snapshots/TestV3RunnerOkWithOverrideValuesPassedTests
index b407d3b..d2f3986 100644
--- a/pkg/unittest/.snapshots/TestV3RunnerOkWithOverrideValuesPassedTests
+++ b/pkg/unittest/.snapshots/TestV3RunnerOkWithOverrideValuesPassedTests
@@ -12,13 +12,14 @@
  PASS  test ingress	../../test/data/v3/basic/tests/ingress_test.yaml
  PASS  test notes	../../test/data/v3/basic/tests/notes_test.yaml
  PASS  test override names and fullNames in Kubernetes resources	../../test/data/v3/basic/tests/namesOverride_test.yaml
+ PASS  test pod disruption budget	../../test/data/v3/basic/tests/pdp_test.yaml
  PASS  test service	../../test/data/v3/basic/tests/service_test.yaml
  PASS  test service account	../../test/data/v3/basic/tests/serviceaccount_test.yaml
 
 
 Charts:      1 passed, 1 total
-Test Suites: 12 passed, 12 total
-Tests:       33 passed, 33 total
+Test Suites: 13 passed, 13 total
+Tests:       41 passed, 41 total
 Snapshot:    4 passed, 4 total
 Time:        XX.XXXms
 
diff --git a/pkg/unittest/.snapshots/TestV3RunnerOkWithPassedTests b/pkg/unittest/.snapshots/TestV3RunnerOkWithPassedTests
index b407d3b..d2f3986 100644
--- a/pkg/unittest/.snapshots/TestV3RunnerOkWithPassedTests
+++ b/pkg/unittest/.snapshots/TestV3RunnerOkWithPassedTests
@@ -12,13 +12,14 @@
  PASS  test ingress	../../test/data/v3/basic/tests/ingress_test.yaml
  PASS  test notes	../../test/data/v3/basic/tests/notes_test.yaml
  PASS  test override names and fullNames in Kubernetes resources	../../test/data/v3/basic/tests/namesOverride_test.yaml
+ PASS  test pod disruption budget	../../test/data/v3/basic/tests/pdp_test.yaml
  PASS  test service	../../test/data/v3/basic/tests/service_test.yaml
  PASS  test service account	../../test/data/v3/basic/tests/serviceaccount_test.yaml
 
 
 Charts:      1 passed, 1 total
-Test Suites: 12 passed, 12 total
-Tests:       33 passed, 33 total
+Test Suites: 13 passed, 13 total
+Tests:       41 passed, 41 total
 Snapshot:    4 passed, 4 total
 Time:        XX.XXXms
 
diff --git a/pkg/unittest/assertion_test.go b/pkg/unittest/assertion_test.go
index ad5b51e..148607f 100644
--- a/pkg/unittest/assertion_test.go
+++ b/pkg/unittest/assertion_test.go
@@ -8,7 +8,6 @@ import (
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/results"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/snapshot"
 	"github.com/stretchr/testify/assert"
-	"gopkg.in/yaml.v3"
 )
 
 func validateSucceededTestAssertions(
@@ -18,10 +17,9 @@ func validateSucceededTestAssertions(
 	renderedMap map[string][]common.K8sManifest) {
 
 	assertions := make([]Assertion, assertionCount)
-	err := yaml.Unmarshal([]byte(assertionsYAML), &assertions)
+	common.YmlUnmarshalTestHelper(assertionsYAML, &assertions, t)
 
 	a := assert.New(t)
-	a.Nil(err)
 
 	for idx, assertion := range assertions {
 		result := assertion.Assert(renderedMap, fakeSnapshotComparer(true), true, nil, &results.AssertionResult{Index: idx}, false)
@@ -36,7 +34,7 @@ func validateSucceededTestAssertions(
 	}
 }
 
-func TestAssertionUnmarshaledFromYAML(t *testing.T) {
+func TestAssertionUnmarshalFromYAML(t *testing.T) {
 	assertionsYAML := `
 - equal:
 - notEqual:
@@ -75,11 +73,10 @@ func TestAssertionUnmarshaledFromYAML(t *testing.T) {
 
 	a := assert.New(t)
 	assertionsAsMap := make([]map[string]interface{}, 33)
-	mapErr := yaml.Unmarshal([]byte(assertionsYAML), &assertionsAsMap)
-	a.Nil(mapErr)
+	common.YmlUnmarshalTestHelper(assertionsYAML, &assertionsAsMap, t)
+
 	assertions := make([]Assertion, 33)
-	assErr := yaml.Unmarshal([]byte(assertionsYAML), &assertions)
-	a.Nil(assErr)
+	common.YmlUnmarshalTestHelper(assertionsYAML, &assertions, t)
 
 	for idx, assertion := range assertions {
 		_, ok := assertionsAsMap[idx][assertion.AssertType]
@@ -152,8 +149,7 @@ func TestAssertionUnmarshaledFromYAMLWithNotTrue(t *testing.T) {
 	a := assert.New(t)
 
 	assertions := make([]Assertion, 29)
-	err := yaml.Unmarshal([]byte(assertionsYAML), &assertions)
-	a.Nil(err)
+	common.YmlUnmarshalTestHelper(assertionsYAML, &assertions, t)
 
 	for _, assertion := range assertions {
 		a.True(assertion.Not)
@@ -208,8 +204,7 @@ func TestReverseAssertionTheSameAsOriginalOneWithNotTrue(t *testing.T) {
 	a := assert.New(t)
 
 	assertions := make([]Assertion, 28)
-	err := yaml.Unmarshal([]byte(assertionsYAML), &assertions)
-	a.Nil(err)
+	common.YmlUnmarshalTestHelper(assertionsYAML, &assertions, t)
 
 	for idx := 0; idx < len(assertions); idx += 2 {
 		a.Equal(assertions[idx].Not, !assertions[idx+1].Not)
@@ -335,10 +330,9 @@ template: not-existed.yaml
 equal:
 `
 	assertion := new(Assertion)
-	err := yaml.Unmarshal([]byte(assertionYAML), &assertion)
+	common.YmlUnmarshalTestHelper(assertionYAML, &assertion, t)
 
 	a := assert.New(t)
-	a.Nil(err)
 
 	result := assertion.Assert(renderedMap, fakeSnapshotComparer(true), true, nil, &results.AssertionResult{Index: 0}, false)
 	a.Equal(&results.AssertionResult{
@@ -358,10 +352,9 @@ func TestAssertionAssertWhenTemplateNotSpecifiedAndNoDefault(t *testing.T) {
 	}
 	assertionYAML := "equal:"
 	assertion := new(Assertion)
-	err := yaml.Unmarshal([]byte(assertionYAML), &assertion)
+	common.YmlUnmarshalTestHelper(assertionYAML, &assertion, t)
 
 	a := assert.New(t)
-	a.Nil(err)
 	result := assertion.Assert(renderedMap, fakeSnapshotComparer(true), true, nil, &results.AssertionResult{Index: 0}, false)
 	a.Equal(&results.AssertionResult{
 		Index:      0,
@@ -384,10 +377,9 @@ documentIndex: 1
 equal:
 `
 	assertion := new(Assertion)
-	err := yaml.Unmarshal([]byte(assertionYAML), &assertion)
+	common.YmlUnmarshalTestHelper(assertionYAML, &assertion, t)
 
 	a := assert.New(t)
-	a.Nil(err)
 
 	result := assertion.Assert(renderedMap, fakeSnapshotComparer(true), true, nil, &results.AssertionResult{Index: 0}, false)
 	a.Equal(&results.AssertionResult{
diff --git a/pkg/unittest/files_test.go b/pkg/unittest/files_test.go
index 2736302..ba50ae0 100644
--- a/pkg/unittest/files_test.go
+++ b/pkg/unittest/files_test.go
@@ -1,10 +1,13 @@
 package unittest_test
 
 import (
+	"fmt"
 	"os"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"testing"
+	"testing/fstest"
 
 	. "github.com/helm-unittest/helm-unittest/pkg/unittest"
 	"github.com/stretchr/testify/assert"
@@ -28,6 +31,11 @@ func assertArrayPathOsAgnostic(t *testing.T, expected, actual []string) {
 	assert.Equal(t, want, actual)
 }
 
+func assertArrayContainsOsAgnostic(t *testing.T, actual []string, expected string) {
+	t.Helper()
+	assert.Contains(t, actual, filepath.FromSlash(expected))
+}
+
 func TestGetFiles_ChartWithoutSubCharts(t *testing.T) {
 	filesHelper(t)
 	err := os.Chdir("../../test/data/v3/basic")
@@ -35,7 +43,7 @@ func TestGetFiles_ChartWithoutSubCharts(t *testing.T) {
 
 	actual, err := GetFiles(".", []string{"tests/*_test.yaml"}, false)
 	assert.NoError(t, err)
-	assert.Equal(t, len(actual), 11)
+	assert.Equal(t, len(actual), 12)
 }
 
 func TestGetFiles_ChartWithoutSubChartsNoDuplicates(t *testing.T) {
@@ -158,3 +166,155 @@ func TestGetFiles_ChartWithSubChartPatternMatchingChildTests(t *testing.T) {
 
 	assert.Equal(t, expected, actual)
 }
+
+func TestWithDifferentPatterns(t *testing.T) {
+	tmp := t.TempDir()
+	path := fmt.Sprintf("%s/%s", tmp, "./a/b/c/e")
+	err := os.MkdirAll(path, 0755)
+	assert.NoError(t, err)
+
+	fs := fstest.MapFS{
+		"a/b/c/first.yaml":     {Data: []byte("hi")},
+		"a/b/c/e/second.yaml":  {Data: []byte("hi")},
+		"a/b/third.yaml":       {Data: []byte("hi")},
+		"a/b/c/third.hcl":      {Data: []byte("hi")},
+		"a/b/c/file0.txt":      {Data: []byte("hi")},
+		"a/file1.txt":          {Data: []byte("hi")},
+		"a/b/c/file2.json":     {Data: []byte("hi")},
+		"a/b/file2.json":       {Data: []byte("hi")},
+		"file3.xml":            {Data: []byte("hi")},
+		"a/b/file4_test.csv":   {Data: []byte("hi")},
+		"a/b/c/e/file5.ini":    {Data: []byte("hi")},
+		"a/b/c/e/file6.log":    {Data: []byte("hi")},
+		"a/b/c/e/file7.conf":   {Data: []byte("hi")},
+		"a/b/file6.md":         {Data: []byte("hi")},
+		"a/b/c/e/file8.md":     {Data: []byte("hi")},
+		"a/b/c/e/file9.html":   {Data: []byte("hi")},
+		"a/b/c/e/file10.css":   {Data: []byte("hi")},
+		"a/b/c/file11.js":      {Data: []byte("hi")},
+		"a/b/file12_test.go":   {Data: []byte("hi")},
+		"a/b/c/e/file13.py":    {Data: []byte("hi")},
+		"a/file14_test.rb":     {Data: []byte("hi")},
+		"a/b/c/file15.php":     {Data: []byte("hi")},
+		"a/b/file16.sh":        {Data: []byte("hi")},
+		"a/b/c/e/file17.pl":    {Data: []byte("hi")},
+		"a/b/c/e/file18.rs":    {Data: []byte("hi")},
+		"a/b/c/e/file19.kt":    {Data: []byte("hi")},
+		"a/b/c/e/file20.swift": {Data: []byte("hi")},
+	}
+
+	for path, el := range fs {
+		err := os.WriteFile(filepath.Join(tmp, path), el.Data, 0644)
+		assert.NoError(t, err)
+	}
+
+	tests := []struct {
+		pattern     []string
+		expected    []string
+		skipWindows bool
+	}{
+		{
+			pattern: []string{"**/*.yaml"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/c/first.yaml", tmp),
+				fmt.Sprintf("%s/a/b/c/e/second.yaml", tmp),
+				fmt.Sprintf("%s/a/b/third.yaml", tmp),
+			},
+		},
+		{
+			pattern:  []string{"[a-z\\.\\/]*"},
+			expected: []string{},
+		},
+		{
+			pattern: []string{"/[a-z\\.\\/]*"},
+			expected: []string{
+				"/[a-z\\.\\/]*",
+			},
+			skipWindows: true,
+		},
+		{
+			pattern: []string{"**/*.log"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/c/e/file6.log", tmp),
+			},
+		},
+		{
+			pattern:  []string{"**/*.(json|js|log)"},
+			expected: []string{},
+		},
+		{
+			pattern: []string{"a/*/file*.json", "a/**/file*.txt"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/file2.json", tmp),
+				fmt.Sprintf("%s/a/file1.txt", tmp),
+				fmt.Sprintf("%s/a/b/c/file0.txt", tmp),
+			},
+		},
+		{
+			pattern: []string{"**/*.xml", "**/*.csv"},
+			expected: []string{
+				fmt.Sprintf("%s/file3.xml", tmp),
+				fmt.Sprintf("%s/a/b/file4_test.csv", tmp),
+			},
+		},
+		{
+			pattern:  []string{"a/b/c/e/**.md"},
+			expected: []string{},
+		},
+		{
+			pattern: []string{"a/b/c/e/*.md"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/c/e/file8.md", tmp),
+			},
+		},
+		{
+			pattern: []string{"a/*_test.rb", "a/b/**.rb", "a/b/c/**.php"},
+			expected: []string{
+				fmt.Sprintf("%s/a/file14_test.rb", tmp),
+			},
+		},
+		{
+			pattern: []string{"a/b/*_test.go", ".*11.js"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/file12_test.go", tmp),
+			},
+		},
+		{
+			pattern: []string{fmt.Sprintf("%s/a/b/*.sh", tmp), "**/*.pl"},
+			expected: []string{
+				fmt.Sprintf("%s/a/b/*.sh", tmp),
+				fmt.Sprintf("%s/a/b/c/e/file17.pl", tmp),
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(fmt.Sprintf("with %s identified %d files", strings.Join(tt.pattern, ":"), len(tt.expected)), func(t *testing.T) {
+			if tt.skipWindows && runtime.GOOS == "windows" {
+				t.Skip("Skip this test on Windows")
+			}
+			var escapePattern []string
+			for _, p := range tt.pattern {
+				escapePattern = append(escapePattern, filepath.FromSlash(p))
+			}
+			files, _ := GetFiles(tmp, escapePattern, false)
+			assert.Equal(t, len(tt.expected), len(files))
+			for _, expected := range tt.expected {
+				assert.Contains(t, files, filepath.FromSlash(expected))
+			}
+		})
+	}
+}
+
+func TestGetFiles_GlobError(t *testing.T) {
+	tmp := t.TempDir()
+
+	path := fmt.Sprintf("%s/%s", tmp, "./a/b/c.d/e.f")
+	err := os.MkdirAll(path, 0755)
+	assert.NoError(t, err)
+
+	files, err := GetFiles(path, []string{"[**"}, false)
+	assert.Nil(t, files)
+	assert.Error(t, err)
+	assert.EqualError(t, err, "syntax error in pattern")
+}
diff --git a/pkg/unittest/snapshot/cache.go b/pkg/unittest/snapshot/cache.go
index 4a90a81..0dcbf51 100644
--- a/pkg/unittest/snapshot/cache.go
+++ b/pkg/unittest/snapshot/cache.go
@@ -5,7 +5,7 @@ import (
 	"os"
 
 	"github.com/helm-unittest/helm-unittest/internal/common"
-	yaml "gopkg.in/yaml.v3"
+	yaml "sigs.k8s.io/yaml"
 )
 
 // CompareResult result return by Cache.Compare
@@ -125,7 +125,7 @@ func (s *Cache) StoreToFileIfNeeded() (bool, error) {
 
 	if s.IsUpdating || s.insertedCount > 0 || s.VanishedCount() > 0 {
 		byteBuffer := new(bytes.Buffer)
-		yamlEncoder := yaml.NewEncoder(byteBuffer)
+		yamlEncoder := common.YamlNewEncoder(byteBuffer)
 		yamlEncoder.SetIndent(common.YAMLINDENTION)
 		if err := yamlEncoder.Encode(s.current); err != nil {
 			return false, err
diff --git a/pkg/unittest/suits_schema_validation_test.go b/pkg/unittest/suits_schema_validation_test.go
index 05175a1..3b905d6 100644
--- a/pkg/unittest/suits_schema_validation_test.go
+++ b/pkg/unittest/suits_schema_validation_test.go
@@ -6,10 +6,10 @@ import (
 	"path/filepath"
 	"testing"
 
+	"github.com/helm-unittest/helm-unittest/internal/common"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/xeipuuv/gojsonschema"
-	"sigs.k8s.io/yaml"
 )
 
 const testSuiteSchemaLocal string = "../../schema/helm-testsuite.json"
@@ -133,7 +133,7 @@ func TestValidateExampleChartsWithTestSuitsAgainstLocalSchema(t *testing.T) {
 			assert.NoError(t, err)
 			for _, el := range content {
 				for _, content := range el.FileContents {
-					json, err := yaml.YAMLToJSON([]byte(content))
+					json, err := common.YamlToJson(content)
 
 					assert.NoError(t, err)
 					assert.NotEmpty(t, json)
@@ -148,7 +148,7 @@ func TestValidateExampleChartsWithTestSuitsAgainstLocalSchema(t *testing.T) {
 					assert.True(t, result.Valid(), fmt.Sprintf("Schema '%s' and the document '%s' is not valid!!!", fullPath, el.FilePath))
 
 					if !result.Valid() {
-						fmt.Printf("See errors:\n")
+						fmt.Printf("See errors for file%s:\n", el.FilePath)
 						for _, desc := range result.Errors() {
 							fmt.Printf("- %s\n", desc)
 						}
diff --git a/pkg/unittest/test_job.go b/pkg/unittest/test_job.go
index 289c0af..6370964 100644
--- a/pkg/unittest/test_job.go
+++ b/pkg/unittest/test_job.go
@@ -17,8 +17,6 @@ import (
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/valueutils"
 	log "github.com/sirupsen/logrus"
 
-	yaml "gopkg.in/yaml.v3"
-
 	v3chart "helm.sh/helm/v3/pkg/chart"
 	v3util "helm.sh/helm/v3/pkg/chartutil"
 	v3engine "helm.sh/helm/v3/pkg/engine"
@@ -83,7 +81,7 @@ func parseRenderError(regexPattern, errorMessage string) (string, map[string]str
 func parseYamlFile(rendered string) ([]common.K8sManifest, error) {
 	// Replace --- with ---\n to ensure yaml rendering is parsed correctly/
 	rendered = splitterPattern.ReplaceAllString(rendered, "\n---\n")
-	decoder := yaml.NewDecoder(strings.NewReader(rendered))
+	decoder := common.YamlNewDecoder(strings.NewReader(rendered))
 	parsedYamls := make([]common.K8sManifest, 0)
 
 	for {
@@ -208,7 +206,7 @@ func (t *TestJob) RunV3(
 		return result
 	}
 
-	outputOfFiles, renderSucceed, renderError := t.renderV3Chart(targetChart, userValues)
+	outputOfFiles, renderSucceed, renderError := t.renderV3Chart(targetChart, []byte(userValues))
 
 	writeError := writeRenderedOutput(renderPath, outputOfFiles)
 	if writeError != nil {
@@ -243,7 +241,7 @@ func (t *TestJob) RunV3(
 }
 
 // liberally borrows from helm-template
-func (t *TestJob) getUserValues() ([]byte, error) {
+func (t *TestJob) getUserValues() (string, error) {
 	base := map[string]interface{}{}
 	routes := spliteChartRoutes(t.chartRoute)
 
@@ -259,35 +257,36 @@ func (t *TestJob) getUserValues() ([]byte, error) {
 
 		bytes, err := os.ReadFile(valueFilePath)
 		if err != nil {
-			return []byte{}, err
+			return "", err
 		}
 
-		if err := yaml.Unmarshal(bytes, &value); err != nil {
-			return []byte{}, fmt.Errorf("failed to parse %s: %s", specifiedPath, err)
+		if err := common.YmlUnmarshal(string(bytes), &value); err != nil {
+			return "", fmt.Errorf("failed to parse %s: %s", specifiedPath, err)
 		}
-		base = valueutils.MergeValues(base, scopeValuesWithRoutes(routes, value))
+
+		base = v3util.MergeTables(scopeValuesWithRoutes(routes, value), base)
 	}
 
 	// Merge global set values before merging the other set values
 	for path, values := range t.globalSet {
 		setMap, err := valueutils.BuildValueOfSetPath(values, path)
 		if err != nil {
-			return []byte{}, err
+			return "", err
 		}
 
-		base = valueutils.MergeValues(base, scopeValuesWithRoutes(routes, setMap))
+		base = v3util.MergeTables(scopeValuesWithRoutes(routes, setMap), base)
 	}
 
 	for path, values := range t.Set {
 		setMap, err := valueutils.BuildValueOfSetPath(values, path)
 		if err != nil {
-			return []byte{}, err
+			return "", err
 		}
 
-		base = valueutils.MergeValues(base, scopeValuesWithRoutes(routes, setMap))
+		base = v3util.MergeTables(scopeValuesWithRoutes(routes, setMap), base)
 	}
 	log.WithField(LOG_TEST_JOB, "get-user-values").Debug("values ", base)
-	return yaml.Marshal(base)
+	return common.YmlMarshall(base)
 }
 
 // render the chart and return result map
diff --git a/pkg/unittest/test_job_test.go b/pkg/unittest/test_job_test.go
index 2cb58ae..08603e5 100644
--- a/pkg/unittest/test_job_test.go
+++ b/pkg/unittest/test_job_test.go
@@ -3,16 +3,17 @@ package unittest_test
 import (
 	"fmt"
 	"os"
+	"path"
 
 	"testing"
 	"time"
 
 	"github.com/bradleyjkemp/cupaloy/v2"
+	"github.com/helm-unittest/helm-unittest/internal/common"
 	. "github.com/helm-unittest/helm-unittest/pkg/unittest"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/results"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/snapshot"
 	"github.com/stretchr/testify/assert"
-	"gopkg.in/yaml.v3"
 	v3chart "helm.sh/helm/v3/pkg/chart"
 	"helm.sh/helm/v3/pkg/chart/loader"
 )
@@ -39,10 +40,9 @@ asserts:
       pattern: /z/
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	a := assert.New(t)
-	a.Nil(err)
 	a.Equal(tj.Name, "should do something")
 	a.Equal(tj.Values, []string{"values.yaml"})
 	a.Equal(tj.Set, map[string]interface{}{
@@ -50,14 +50,14 @@ asserts:
 		"x.y.z": "XYZ",
 	})
 	assertions := make([]*Assertion, 2)
-	assErr := yaml.Unmarshal([]byte(`
+	assErr := common.YmlUnmarshal(`
   - equal:
       path: a.b
       value: c
   - matchRegex:
       path: x.y
       pattern: /z/
-`), &assertions)
+`, &assertions)
 	a.Nil(assErr)
 	a.Equal(tj.Assertions, assertions)
 }
@@ -80,12 +80,11 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -112,13 +111,12 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, renderPath, &results.TestJobResult{})
 	defer os.RemoveAll(renderPath)
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -143,12 +141,11 @@ asserts:
       pattern: -basic$
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -173,12 +170,11 @@ asserts:
       pattern: -basic
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -206,12 +202,11 @@ asserts:
       path: metadata.name
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -232,12 +227,11 @@ asserts:
       errorMessage: The externalPort is required
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -262,13 +256,12 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, false, "", &results.TestJobResult{})
 	// Write Buffer
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -293,13 +286,12 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 	// Write Buffer
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -321,12 +313,11 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -349,33 +340,21 @@ asserts:
 `
 	a := assert.New(t)
 
-	file, fileErr := os.Create("testjob_test_TestRunJobWithValuesFile.yaml")
-	if fileErr != nil {
-		a.FailNow("Failed to create file")
-	}
-	_, writeErr := file.WriteString("nameOverride: mary-jane")
-	if writeErr != nil {
-		a.FailNow("Failed to write to file")
-	}
-	closeErr := file.Close()
-	if closeErr != nil {
-		a.FailNow("Failed to close file")
-	}
+	file := path.Join("_scratch", "testjob_test_TestRunJobWithValuesFile.yaml")
+	a.Nil(writeToFile("nameOverride: mary-jane", file))
+	defer os.RemoveAll(file)
 
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(fmt.Sprintf(manifest, file.Name())), &tj)
-	a.Nil(err)
+	common.YmlUnmarshalTestHelper(fmt.Sprintf(manifest, file), &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
-	a.FileExists(file.Name())
+	a.FileExists(file)
 	a.Nil(testResult.ExecError)
 	a.True(testResult.Passed)
 	a.Equal(1, len(testResult.AssertsResult))
-
-	os.Remove(file.Name())
 }
 
 func TestV3RunJobWithReleaseSettings(t *testing.T) {
@@ -393,12 +372,11 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -416,12 +394,11 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -441,12 +418,11 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.NotNil(testResult.ExecError)
@@ -468,15 +444,13 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
-
-	a := assert.New(t)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
+	a := assert.New(t)
 	a.Nil(testResult.ExecError)
 	a.True(testResult.Passed)
 	a.Equal(1, len(testResult.AssertsResult))
@@ -496,12 +470,11 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
-
-	a := assert.New(t)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, nil, true, "", &results.TestJobResult{})
+
+	a := assert.New(t)
 	a.False(testResult.Passed)
 	a.Equal(0, len(tj.Capabilities.APIVersions))
 }
@@ -519,13 +492,11 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
-
-	a := assert.New(t)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, nil, true, "", &results.TestJobResult{})
 
+	a := assert.New(t)
 	a.False(testResult.Passed)
 	a.Equal([]string{}, tj.Capabilities.APIVersions)
 	a.Equal("12", tj.Capabilities.MinorVersion)
@@ -543,14 +514,11 @@ asserts:
     template: templates/crd_backup.yaml
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
-
-	a := assert.New(t)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, nil, true, "", &results.TestJobResult{})
-	a.False(testResult.Passed)
-	a.Equal("7", tj.Capabilities.MinorVersion)
+	assert.False(t, testResult.Passed)
+	assert.Equal(t, "7", tj.Capabilities.MinorVersion)
 }
 
 func TestV3RunJobWithChartSettings(t *testing.T) {
@@ -573,14 +541,13 @@ asserts:
     template: templates/deployment.yaml
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
-	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
+	a := assert.New(t)
 	a.Nil(testResult.ExecError)
 	a.True(testResult.Passed)
 	a.Equal(2, len(testResult.AssertsResult))
@@ -597,12 +564,11 @@ asserts:
       errorMessage:	"error calling include: template: no template \"non-existing-named-template\" associated with template \"gotpl\""
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -620,12 +586,11 @@ asserts:
       errorMessage: "values don't meet the specifications of the schema(s) in the following chart(s):\nwith-schema:\n- (root): image is required\n"
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.NotNil(testResult.ExecError)
@@ -646,14 +611,13 @@ asserts:
   - failedTemplate: {}
 `
 	var tj TestJob
-	err := unmarshalJob(manifest, &tj)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
-	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
+	a := assert.New(t)
 	a.NotNil(testResult.ExecError)
 	a.True(testResult.Passed)
 	a.Equal(1, len(testResult.AssertsResult))
@@ -672,12 +636,11 @@ asserts:
   - notFailedTemplate: {}
 `
 	var tj TestJob
-	err := yaml.Unmarshal([]byte(manifest), &tj)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
-	a.Nil(err)
 	cupaloy.SnapshotT(t, makeTestJobResultSnapshotable(testResult))
 
 	a.Nil(testResult.ExecError)
@@ -701,8 +664,7 @@ asserts:
 `
 	var tj TestJob
 	a := assert.New(t)
-	err := unmarshalJob(manifest, &tj)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
@@ -724,15 +686,13 @@ asserts:
       pattern: "(.*-)?postgresql-0.8.3"
 `
 	var tj TestJob
-	a := assert.New(t)
-	err := unmarshalJob(manifest, &tj)
-	a.Nil(err)
+	unmarshalJobTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
-	a.Nil(testResult.ExecError)
-	a.True(testResult.Passed)
-	a.Equal(1, len(testResult.AssertsResult))
+	assert.Nil(t, testResult.ExecError)
+	assert.True(t, testResult.Passed)
+	assert.Equal(t, 1, len(testResult.AssertsResult))
 }
 
 func TestModifyChartMetadataVersions(t *testing.T) {
@@ -847,8 +807,7 @@ asserts:
 `
 	var tj TestJob
 	assert := assert.New(t)
-	err := yaml.Unmarshal([]byte(manifest), &tj)
-	assert.NoError(err)
+	common.YmlUnmarshalTestHelper(manifest, &tj, t)
 
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
@@ -869,8 +828,7 @@ asserts:
   - notSupportedAssert:
 `
 	var tj TestJob
-	yaml.Unmarshal([]byte(manifest), &tj)
-
+	common.YmlUnmarshal(manifest, &tj)
 	testResult := tj.RunV3(c, &snapshot.Cache{}, true, "", &results.TestJobResult{})
 
 	a := assert.New(t)
@@ -880,3 +838,94 @@ asserts:
 	a.Equal(testResult.AssertsResult[0].AssertType, "equal")
 	a.NotEqual(testResult.AssertsResult[0].AssertType, "notSupportedAssert")
 }
+
+func TestV3RunJobPatchArrayValue(t *testing.T) {
+	c, _ := loader.Load(testV3BasicChart)
+	manifest := `
+it: should patch second element
+template: templates/configmap.yaml
+values:
+- %s
+set:
+ ingress:
+  hosts[1]: should-override-second.local
+asserts:
+  - exists:
+      path: data["my.ingress.hosts"]
+  - notEqual:
+      path: data["my.ingress.hosts"]
+      value:
+      - null
+      - should-override-second.local
+  - equal:
+      path: data["my.ingress.hosts"]
+      value:
+      - chart-example-first.local
+      - chart-example-second.local
+      - chart-example-third.local
+`
+	a := assert.New(t)
+	file := path.Join("_scratch", "test_tmp_values.yaml")
+	a.Nil(writeToFile(`
+ingress:
+  hosts:
+    - chart-example-first.local
+    - chart-example-second.local
+    - chart-example-third.local
+`, file))
+	defer os.RemoveAll(file)
+
+	var tj TestJob
+	unmarshalJobTestHelper(fmt.Sprintf(manifest, file), &tj, t)
+
+	testResult := tj.RunV3(c, nil, true, "", &results.TestJobResult{})
+
+	assert.Nil(t, testResult.ExecError)
+	assert.True(t, testResult.Passed)
+	assert.Equal(t, 3, len(testResult.AssertsResult))
+}
+
+func TestV3RunJobPatchPointArrayValue(t *testing.T) {
+	c, _ := loader.Load(testV3BasicChart)
+	manifest := `
+it: should patch second element
+template: templates/configmap.yaml
+values:
+- %s
+set:
+ ingress.hosts[1]: should-override-second.local
+asserts:
+  - exists:
+      path: data["my.ingress.hosts"]
+  - equal:
+      path: data["my.ingress.hosts"]
+      value:
+      - null
+      - should-override-second.local
+  - notEqual:
+      path: data["my.ingress.hosts"]
+      value:
+      - chart-example-first.local
+      - should-override-second.local
+      - chart-example-third.local
+`
+	a := assert.New(t)
+	file := path.Join("_scratch", "test_tmp_values.yaml")
+	a.Nil(writeToFile(`
+ingress:
+  hosts:
+    - chart-example-first.local
+    - chart-example-second.local
+    - chart-example-third.local
+`, file))
+	defer os.RemoveAll(file)
+
+	var tj TestJob
+	unmarshalJobTestHelper(fmt.Sprintf(manifest, file), &tj, t)
+
+	testResult := tj.RunV3(c, nil, true, "", &results.TestJobResult{})
+
+	assert.Nil(t, testResult.ExecError)
+	assert.True(t, testResult.Passed)
+	assert.Equal(t, 3, len(testResult.AssertsResult))
+}
diff --git a/pkg/unittest/test_suite.go b/pkg/unittest/test_suite.go
index 01ffda1..4b67473 100644
--- a/pkg/unittest/test_suite.go
+++ b/pkg/unittest/test_suite.go
@@ -13,7 +13,6 @@ import (
 	"github.com/helm-unittest/helm-unittest/internal/common"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/results"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/snapshot"
-	"gopkg.in/yaml.v3"
 	v3loader "helm.sh/helm/v3/pkg/chart/loader"
 	v3util "helm.sh/helm/v3/pkg/chartutil"
 	v3engine "helm.sh/helm/v3/pkg/engine"
@@ -75,7 +74,7 @@ func createTestSuite(suiteFilePath string, chartRoute string, content string, st
 	}
 
 	// Use decoder to setup strict or unstrict
-	yamlDecoder := yaml.NewDecoder(strings.NewReader(content))
+	yamlDecoder := common.YamlNewDecoder(strings.NewReader(content))
 	yamlDecoder.KnownFields(strict)
 	if err := yamlDecoder.Decode(&suite); err != nil {
 		return &suite, err
diff --git a/pkg/unittest/test_suite_test.go b/pkg/unittest/test_suite_test.go
index 5965ee9..87cdd43 100644
--- a/pkg/unittest/test_suite_test.go
+++ b/pkg/unittest/test_suite_test.go
@@ -4,16 +4,15 @@ import (
 	"fmt"
 	"os"
 	"path"
-	"path/filepath"
 	"testing"
 	"time"
 
 	"github.com/bradleyjkemp/cupaloy/v2"
+	"github.com/helm-unittest/helm-unittest/internal/common"
 	. "github.com/helm-unittest/helm-unittest/pkg/unittest"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/results"
 	"github.com/helm-unittest/helm-unittest/pkg/unittest/snapshot"
 	"github.com/stretchr/testify/assert"
-	yaml "gopkg.in/yaml.v3"
 )
 
 // Most used test files
@@ -49,32 +48,6 @@ func makeTestSuiteResultSnapshotable(result *results.TestSuiteResult) *results.T
 	return result
 }
 
-// writeToFile writes the provided string data to a file with the given filename.
-// It returns an error if the file cannot be created or if there is an error during writing.
-func writeToFile(data string, filename string) error {
-	err := os.MkdirAll(filepath.Dir(filename), 0755)
-	if err != nil {
-		fmt.Println("Error creating folders for file:", err)
-		return err
-	}
-
-	// Create the file with an absolute path
-	file, err := os.Create(filename)
-	if err != nil {
-		fmt.Println("Error creating file:", err)
-		return err
-	}
-	defer file.Close()
-
-	_, err = file.WriteString(data)
-	if err != nil {
-		fmt.Println("Error writing to file:", err)
-		return err
-	}
-
-	return nil
-}
-
 func validateTestResultAndSnapshots(
 	t *testing.T,
 	suiteResult *results.TestSuiteResult,
@@ -98,7 +71,7 @@ func validateTestResultAndSnapshots(
 }
 
 // Helper metheod for the render process
-func getExpectedRenderedTestSuites(customSnapshotIds bool) map[string]*TestSuite {
+func getExpectedRenderedTestSuites(customSnapshotIds bool, t *testing.T) map[string]*TestSuite {
 	// multiple_suites_snapshot.yaml assertions
 	createSnapshotTestYaml := func(env string) string {
 		return fmt.Sprintf(`
@@ -109,9 +82,9 @@ asserts:
     - matchSnapshot: {}`, env)
 	}
 	snapshotDevTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(createSnapshotTestYaml("dev")), &snapshotDevTest)
+	common.YmlUnmarshalTestHelper(createSnapshotTestYaml("dev"), &snapshotDevTest, t)
 	snapshotProdTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(createSnapshotTestYaml("prod")), &snapshotProdTest)
+	common.YmlUnmarshalTestHelper(createSnapshotTestYaml("prod"), &snapshotProdTest, t)
 	// multiple_test_suites.yaml assertions
 	crateMultipleTestSuitesYaml := func(env string) string {
 		return fmt.Sprintf(`
@@ -132,9 +105,9 @@ asserts:
         decodeBase64: true`, env, env)
 	}
 	multipleTestSuitesDevTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(crateMultipleTestSuitesYaml("dev")), &multipleTestSuitesDevTest)
+	common.YmlUnmarshalTestHelper(crateMultipleTestSuitesYaml("dev"), &multipleTestSuitesDevTest, t)
 	multipleTestSuitesProdTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(crateMultipleTestSuitesYaml("prod")), &multipleTestSuitesProdTest)
+	common.YmlUnmarshalTestHelper(crateMultipleTestSuitesYaml("prod"), &multipleTestSuitesProdTest, t)
 	// multiple_tests_test.yaml assertions
 	var secretNameEqualsYaml = func(env string) string {
 		return fmt.Sprintf(`
@@ -150,16 +123,16 @@ asserts:
           - secretName: %s-my-tls-secret`, env, env, env)
 	}
 	multipleTestsDevTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(secretNameEqualsYaml("dev")), &multipleTestsDevTest)
+	common.YmlUnmarshalTestHelper(secretNameEqualsYaml("dev"), &multipleTestsDevTest, t)
 	multipleTestsProdTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(secretNameEqualsYaml("prod")), &multipleTestsProdTest)
+	common.YmlUnmarshalTestHelper(secretNameEqualsYaml("prod"), &multipleTestsProdTest, t)
 	const multipleTestsFirstTestYaml = `
 it: should render nothing if not enabled
 asserts:
     - hasDocuments:
         count: 0`
 	multipleTestsFirstTest := TestJob{}
-	_ = yaml.Unmarshal([]byte(multipleTestsFirstTestYaml), &multipleTestsFirstTest)
+	common.YmlUnmarshalTestHelper(multipleTestsFirstTestYaml, &multipleTestsFirstTest, t)
 
 	// Set up snapshotId values
 	// Note, this is completely based on the order of the yaml in a single suite template file
@@ -312,7 +285,7 @@ func TestV3RenderSuitesUnstrictFileOk(t *testing.T) {
 
 	a.Nil(err)
 
-	expectedSuites := getExpectedRenderedTestSuites(false)
+	expectedSuites := getExpectedRenderedTestSuites(false, t)
 
 	for _, suite := range suites {
 		a.Contains(expectedSuites, suite.Name, "Unexpected test suite"+suite.Name)
@@ -349,7 +322,7 @@ func TestV3RenderSuitesStrictFileOk(t *testing.T) {
 
 	a.Nil(err)
 
-	expectedSuites := getExpectedRenderedTestSuites(false)
+	expectedSuites := getExpectedRenderedTestSuites(false, t)
 
 	for _, suite := range suites {
 		a.Contains(expectedSuites, suite.Name, "Unexpected test suite"+suite.Name)
@@ -368,7 +341,7 @@ func TestV3RenderSuitesCustomSnapshotIdOk(t *testing.T) {
 
 	a.Nil(err)
 
-	expectedSuites := getExpectedRenderedTestSuites(true)
+	expectedSuites := getExpectedRenderedTestSuites(true, t)
 
 	for _, suite := range suites {
 		a.Contains(expectedSuites, suite.Name, "Unexpected test suite"+suite.Name)
@@ -387,8 +360,7 @@ tests:
     asserts:
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_noasserts_template_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
@@ -427,8 +399,7 @@ tests:
       - matchSnapshot: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_multiple_template_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
@@ -452,8 +423,7 @@ tests:
       - matchSnapshot: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_suite_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
@@ -489,8 +459,7 @@ tests:
       - matchSnapshot: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_suite_override_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
@@ -513,8 +482,7 @@ tests:
           value: Pod
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_failed_suite_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
@@ -537,8 +505,7 @@ tests:
       - matchSnapshot: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_subfolder_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3WithSubFolderChart, cache, true, "", &results.TestSuiteResult{})
@@ -560,8 +527,7 @@ tests:
       - matchSnapshot: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_subchart_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3WithSubChart, cache, true, "", &results.TestSuiteResult{})
@@ -585,8 +551,7 @@ tests:
         pattern: "(.*-)?postgresql-1.2.3"
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	suiteResult := testSuite.RunV3(testV3WithSubChart, &snapshot.Cache{}, true, "", &results.TestSuiteResult{})
 	assert.True(t, suiteResult.Passed)
@@ -606,8 +571,7 @@ tests:
       - notFailedTemplate: {}
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_subchartwithtrimming_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3WithSubChart, cache, true, "", &results.TestSuiteResult{})
@@ -637,8 +601,7 @@ tests:
           count: 0
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_subchartwithalias_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3WithSubChart, cache, true, "", &results.TestSuiteResult{})
@@ -664,8 +627,7 @@ tests:
           value: postgresql-0.8.3
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	suiteResult := testSuite.RunV3(testV3WithSubChart, &snapshot.Cache{}, true, "", &results.TestSuiteResult{})
 
@@ -693,8 +655,7 @@ tests:
           value: postgresql-0.6.3
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	suiteResult := testSuite.RunV3(testV3WithSubChart, &snapshot.Cache{}, true, "", &results.TestSuiteResult{})
 
@@ -724,8 +685,7 @@ tests:
           value: postgresql-0.7.1
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	suiteResult := testSuite.RunV3(testV3WithSubChart, &snapshot.Cache{}, true, "", &results.TestSuiteResult{})
 
@@ -748,8 +708,7 @@ tests:
           errorMessage: nameOverride cannot be longer than 20 characters
 `
 	testSuite := TestSuite{}
-	err := yaml.Unmarshal([]byte(suiteDoc), &testSuite)
-	assert.Nil(t, err)
+	common.YmlUnmarshalTestHelper(suiteDoc, &testSuite, t)
 
 	cache, _ := snapshot.CreateSnapshotOfSuite(path.Join(tmpdir, "v3_nameoverride_failed_suite_test.yaml"), false)
 	suiteResult := testSuite.RunV3(testV3BasicChart, cache, true, "", &results.TestSuiteResult{})
diff --git a/pkg/unittest/utils_test.go b/pkg/unittest/utils_test.go
index 3c22896..ef90d41 100644
--- a/pkg/unittest/utils_test.go
+++ b/pkg/unittest/utils_test.go
@@ -1,22 +1,51 @@
 package unittest_test
 
 import (
-	"gopkg.in/yaml.v3"
+	"fmt"
+	"os"
+	"path/filepath"
+	"testing"
 
+	"github.com/helm-unittest/helm-unittest/internal/common"
 	. "github.com/helm-unittest/helm-unittest/pkg/unittest"
+	"github.com/stretchr/testify/assert"
 )
 
-// UnmarshalJob unmarshall a YAML-encoded string into a TestJob struct.
+// unmarshalJobTestHelper unmarshall a YAML-encoded string into a TestJob struct.
 // It extracts the majorVersion, minorVersion, and apiVersions fields from
 // CapabilitiesFields and populates the corresponding fields in Capabilities.
 // If apiVersions is nil, it sets APIVersions to nil. If it's a slice,
 // it appends string values to APIVersions. Returns an error if unmarshaling
 // or processing fails.
-func unmarshalJob(input string, out *TestJob) error {
-	err := yaml.Unmarshal([]byte(input), &out)
+func unmarshalJobTestHelper(input string, out *TestJob, t *testing.T) {
+	t.Helper()
+	err := common.YmlUnmarshal(input, &out)
+	assert.NoError(t, err)
+	out.SetCapabilities()
+}
+
+// writeToFile writes the provided string data to a file with the given filename.
+// It returns an error if the file cannot be created or if there is an error during writing.
+func writeToFile(data string, filename string) error {
+	err := os.MkdirAll(filepath.Dir(filename), 0755)
 	if err != nil {
+		fmt.Println("Error creating folders for file:", err)
 		return err
 	}
-	out.SetCapabilities()
+
+	// Create the file with an absolute path
+	file, err := os.Create(filename)
+	if err != nil {
+		fmt.Println("Error creating file:", err)
+		return err
+	}
+	defer file.Close()
+
+	_, err = file.WriteString(data)
+	if err != nil {
+		fmt.Println("Error writing to file:", err)
+		return err
+	}
+
 	return nil
 }
diff --git a/pkg/unittest/validators/equal_or_greater_validator_test.go b/pkg/unittest/validators/equal_or_greater_validator_test.go
index 5fb8a46..5aec7fc 100644
--- a/pkg/unittest/validators/equal_or_greater_validator_test.go
+++ b/pkg/unittest/validators/equal_or_greater_validator_test.go
@@ -218,6 +218,29 @@ spec:
 	assert.Equal(t, []string{}, diff)
 }
 
+func TestEqualOrGreaterValidator_TODO(t *testing.T) {
+	var actual = `
+kind: PodDisruptionBudget
+metadata:
+  name: 'greaterorequal-test-pdb'
+spec:
+  minAvailable: 2
+  unhealthyPodEvictionPolicy: AlwaysAllow
+`
+	manifest := makeManifest(actual)
+
+	v := EqualOrGreaterValidator{
+		Path:  "spec.minAvailable",
+		Value: 1,
+	}
+	pass, _ := v.Validate(&ValidateContext{
+		Docs:     []common.K8sManifest{manifest},
+		Negative: false,
+	})
+
+	assert.False(t, pass)
+}
+
 func TestEqualOrGreaterValidatorWhenTypesDoNotMatch(t *testing.T) {
 	tests := []struct {
 		name, doc, path string
diff --git a/pkg/unittest/valueutils/valueutils.go b/pkg/unittest/valueutils/valueutils.go
index bbff582..ef58336 100644
--- a/pkg/unittest/valueutils/valueutils.go
+++ b/pkg/unittest/valueutils/valueutils.go
@@ -8,7 +8,6 @@ import (
 
 	"github.com/helm-unittest/helm-unittest/internal/common"
 	"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
-	yaml "gopkg.in/yaml.v3"
 )
 
 // GetValueOfSetPath get the value of the `--set` format path from a manifest
@@ -21,8 +20,8 @@ func GetValueOfSetPath(manifest common.K8sManifest, path string) ([]interface{},
 	byteBuffer := new(bytes.Buffer)
 
 	// Convert K8Manifest to yaml.Node
-	var rawManifest yaml.Node
-	yamlEncoder := yaml.NewEncoder(byteBuffer)
+	node := common.NewYamlNode()
+	yamlEncoder := common.YamlNewEncoder(byteBuffer)
 	yamlEncoder.SetIndent(common.YAMLINDENTION)
 
 	err := yamlEncoder.Encode(manifest)
@@ -30,9 +29,9 @@ func GetValueOfSetPath(manifest common.K8sManifest, path string) ([]interface{},
 		return nil, err
 	}
 
-	yamlDecoder := yaml.NewDecoder(byteBuffer)
+	yamlDecoder := common.YamlNewDecoder(byteBuffer)
 
-	if err := yamlDecoder.Decode(&rawManifest); err != nil {
+	if err := yamlDecoder.Decode(&node.Node); err != nil {
 		return nil, err
 	}
 
@@ -43,7 +42,7 @@ func GetValueOfSetPath(manifest common.K8sManifest, path string) ([]interface{},
 	}
 
 	// Search for nodes
-	manifestParts, err := yamlPath.Find(&rawManifest)
+	manifestParts, err := yamlPath.Find(&node.Node)
 	if err != nil {
 		return nil, err
 	}
@@ -72,41 +71,9 @@ func BuildValueOfSetPath(val interface{}, path string) (map[string]interface{},
 	return tr.getBuildedData(), nil
 }
 
-// MergeValues deeply merge values, copied from helm
-func MergeValues(dest map[string]interface{}, src map[string]interface{}) map[string]interface{} {
-	for k, v := range src {
-		// If the key doesn't exist already, then just set the key to that value
-		if _, exists := dest[k]; !exists {
-			dest[k] = v
-			continue
-		}
-		nextMap, ok := v.(map[string]interface{})
-		// If it isn't another map, overwrite the value
-		if !ok {
-			dest[k] = v
-			continue
-		}
-		// If the key doesn't exist already, then just set the key to that value
-		if _, exists := dest[k]; !exists {
-			dest[k] = nextMap
-			continue
-		}
-		// Edge case: If the key exists in the destination, but isn't a map
-		destMap, isMap := dest[k].(map[string]interface{})
-		// If the source map has a map for this key, prefer it
-		if !isMap {
-			dest[k] = v
-			continue
-		}
-		// If we got to this point, it is a map in both, so merge them
-		dest[k] = MergeValues(destMap, nextMap)
-	}
-	return dest
-}
-
 type parseTraverser interface {
-	traverseMapKey(string) error
-	traverseListIdx(int) error
+	traverseMapKey(string)
+	traverseListIdx(int)
 }
 
 type buildTraverser struct {
@@ -114,14 +81,12 @@ type buildTraverser struct {
 	cursors []interface{}
 }
 
-func (tr *buildTraverser) traverseMapKey(key string) error {
+func (tr *buildTraverser) traverseMapKey(key string) {
 	tr.cursors = append(tr.cursors, key)
-	return nil
 }
 
-func (tr *buildTraverser) traverseListIdx(idx int) error {
+func (tr *buildTraverser) traverseListIdx(idx int) {
 	tr.cursors = append(tr.cursors, idx)
-	return nil
 }
 
 func (tr buildTraverser) getBuildedData() map[string]interface{} {
@@ -170,7 +135,8 @@ func traverseSetPath(in io.RuneReader, traverser parseTraverser, state int) erro
 		if err == io.EOF {
 			switch {
 			case len(k) != 0 && state == expectKey:
-				return traverser.traverseMapKey(string(k))
+				traverser.traverseMapKey(string(k))
+				return nil
 			case len(k) == 0 && state == expectDenotation:
 				return nil
 			default:
@@ -210,9 +176,7 @@ func handleExpectIndex(k []rune, last rune, traverser parseTraverser) (int, erro
 	if idxErr != nil {
 		return -1, idxErr
 	}
-	if e := traverser.traverseListIdx(idx); e != nil {
-		return -1, e
-	}
+	traverser.traverseListIdx(idx)
 	return expectDenotation, nil
 }
 
@@ -230,18 +194,14 @@ func handleExpectDenotation(last rune) (int, error) {
 func handleExpectKey(k []rune, last rune, traverser parseTraverser) (int, error) {
 	switch last {
 	case '.':
-		if e := traverser.traverseMapKey(string(k)); e != nil {
-			return -1, e
-		}
+		traverser.traverseMapKey(string(k))
 		return expectKey, nil
 	case '[':
 		if len(k) == 0 {
 			bufferedMapKey = ""
 			return expectEscaping, nil
 		}
-		if e := traverser.traverseMapKey(string(k)); e != nil {
-			return -1, e
-		}
+		traverser.traverseMapKey(string(k))
 		return expectIndex, nil
 	default:
 		return -1, fmt.Errorf("invalid key %s", string(last))
@@ -255,9 +215,7 @@ func handleExpectEscaping(k []rune, last rune, traverser parseTraverser) (int, e
 		return expectEscaping, nil
 	case ']':
 		bufferedMapKey += string(k)
-		if e := traverser.traverseMapKey(bufferedMapKey); e != nil {
-			return -1, e
-		}
+		traverser.traverseMapKey(bufferedMapKey)
 		return expectDenotation, nil
 	default:
 		return -1, fmt.Errorf("invalid escaping token %s", string(last))
@@ -273,12 +231,6 @@ func runesUntil(in io.RuneReader, stop map[rune]bool) ([]rune, rune, error) {
 			return v, r, e
 		case inMap(r, stop):
 			return v, r, nil
-		case r == '\\':
-			next, _, e := in.ReadRune()
-			if e != nil {
-				return v, next, e
-			}
-			v = append(v, next)
 		default:
 			v = append(v, r)
 		}
diff --git a/pkg/unittest/valueutils/valueutils_handlers_test.go b/pkg/unittest/valueutils/valueutils_handlers_test.go
new file mode 100644
index 0000000..414da63
--- /dev/null
+++ b/pkg/unittest/valueutils/valueutils_handlers_test.go
@@ -0,0 +1,239 @@
+// Need to restructure to run these tests in the valueutils package
+package valueutils
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+type mockTraverser struct {
+	err error
+	buildTraverser
+	traverseMapKeyCount  int
+	traverseListIdxCount int
+}
+
+func newMockTraverser() *mockTraverser {
+	return &mockTraverser{
+		buildTraverser: buildTraverser{},
+	}
+}
+
+func (m *mockTraverser) traverseMapKey(key string) {
+	m.traverseMapKeyCount++
+	m.buildTraverser.traverseMapKey(key)
+	if key == "key-error" {
+		m.err = fmt.Errorf("traverser error")
+	}
+}
+
+func (m *mockTraverser) traverseListIdx(idx int) {
+	m.traverseListIdxCount++
+	m.buildTraverser.traverseListIdx(idx)
+	if idx == 6897 {
+		m.err = fmt.Errorf("traverser error")
+	}
+}
+
+func TestHandleExpectIndex_ErrorCases(t *testing.T) {
+	tr := newMockTraverser()
+	tests := []struct {
+		name                 string
+		runes                []rune
+		lastRune             rune
+		errMsg               string
+		traverseListIdxCount int
+	}{
+		{
+			name:                 "missing index value",
+			errMsg:               "missing index value",
+			runes:                []rune(""),
+			lastRune:             'a',
+			traverseListIdxCount: 0,
+		},
+		{
+			name:                 "invalid index value",
+			errMsg:               "invalid syntax",
+			runes:                []rune("abc"),
+			lastRune:             ']',
+			traverseListIdxCount: 0,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			state, err := handleExpectIndex(tt.runes, tt.lastRune, tr)
+			assert.Error(t, err)
+			assert.Equal(t, tt.traverseListIdxCount, tr.traverseListIdxCount)
+			assert.Equal(t, -1, state)
+		})
+	}
+}
+
+func TestHandleExpectIndex_OkCases(t *testing.T) {
+	tr := &mockTraverser{}
+	tests := []struct {
+		name     string
+		runes    []rune
+		lastRune rune
+	}{
+		{
+			name:     "valid index value",
+			runes:    []rune("123"),
+			lastRune: ']',
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			state, err := handleExpectIndex(tt.runes, tt.lastRune, tr)
+			assert.NoError(t, err)
+			assert.Equal(t, expectDenotation, state)
+		})
+	}
+}
+
+func TestHandleExpectDenotation_ValidDotToken(t *testing.T) {
+	tests := []struct {
+		name     string
+		lastRune rune
+		expected int
+	}{
+		{
+			name:     "valid token",
+			lastRune: '.',
+			expected: expectKey,
+		},
+		{
+			name:     "valid open bracket token",
+			lastRune: '[',
+			expected: expectIndex,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			state, err := handleExpectDenotation(tt.lastRune)
+			assert.NoError(t, err)
+			assert.Equal(t, tt.expected, state)
+		})
+	}
+}
+
+func TestHandleExpectDenotation_InvalidToken(t *testing.T) {
+	state, err := handleExpectDenotation('a')
+	assert.Error(t, err)
+	assert.EqualError(t, err, "invalid denotation token a")
+	assert.Equal(t, -1, state)
+}
+
+func TestHandleExpectKey_OkCases(t *testing.T) {
+	tests := []struct {
+		name     string
+		runes    []rune
+		lastRune rune
+		expected int
+	}{
+		{
+			name:     "valid dot token",
+			lastRune: '.',
+			runes:    []rune("key"),
+			expected: expectKey,
+		},
+		{
+			name:     "valid open bracket token with empty key",
+			lastRune: '[',
+			runes:    []rune(""),
+			expected: expectEscaping,
+		},
+		{
+			name:     "valid open bracket token with non-empty key",
+			lastRune: '[',
+			runes:    []rune("key"),
+			expected: expectIndex,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			tr := newMockTraverser()
+			state, err := handleExpectKey(tt.runes, tt.lastRune, tr)
+			assert.NoError(t, err)
+			assert.Equal(t, tt.expected, state)
+		})
+	}
+}
+
+func TestHandleExpectKey_ErrorCases(t *testing.T) {
+	tests := []struct {
+		name        string
+		runes       []rune
+		lastRune    rune
+		errorString string
+	}{
+		{
+			name:        "invalid token",
+			lastRune:    'a',
+			runes:       []rune("key"),
+			errorString: "invalid key a",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			tr := newMockTraverser()
+			state, err := handleExpectKey(tt.runes, tt.lastRune, tr)
+			assert.Error(t, err)
+			assert.Equal(t, tt.errorString, err.Error())
+			assert.Equal(t, -1, state)
+		})
+	}
+}
+
+// last
+func TestHandleExpectEscaping_OkCases(t *testing.T) {
+	tests := []struct {
+		name        string
+		runes       []rune
+		lastRune    rune
+		expected    int
+		bufferedKey string
+	}{
+		{
+			name:        "valid dot token",
+			lastRune:    '.',
+			runes:       []rune("key"),
+			expected:    expectEscaping,
+			bufferedKey: "key.",
+		},
+		{
+			name:        "valid close bracket token",
+			lastRune:    ']',
+			runes:       []rune("key"),
+			expected:    expectDenotation,
+			bufferedKey: "key",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			bufferedMapKey = ""
+			tr := newMockTraverser()
+			state, err := handleExpectEscaping(tt.runes, tt.lastRune, tr)
+			assert.NoError(t, err)
+			assert.Equal(t, tt.expected, state)
+			assert.Equal(t, tt.bufferedKey, bufferedMapKey)
+		})
+	}
+}
+
+func TestHandleExpectEscaping_InvalidToken(t *testing.T) {
+	tr := &mockTraverser{}
+	bufferedMapKey = ""
+	state, err := handleExpectEscaping([]rune("key"), 'a', tr)
+	assert.Error(t, err)
+	assert.EqualError(t, err, "invalid escaping token a")
+	assert.Equal(t, -1, state)
+}
diff --git a/pkg/unittest/valueutils/valueutils_test.go b/pkg/unittest/valueutils/valueutils_test.go
index 2b922a7..e98e7b6 100644
--- a/pkg/unittest/valueutils/valueutils_test.go
+++ b/pkg/unittest/valueutils/valueutils_test.go
@@ -1,11 +1,14 @@
 package valueutils_test
 
 import (
+	"fmt"
 	"testing"
 
 	"github.com/helm-unittest/helm-unittest/internal/common"
 	. "github.com/helm-unittest/helm-unittest/pkg/unittest/valueutils"
 	"github.com/stretchr/testify/assert"
+
+	v3util "helm.sh/helm/v3/pkg/chartutil"
 )
 
 func TestGetValueOfSetPathWithSingleResults(t *testing.T) {
@@ -77,15 +80,128 @@ func TestBuildValueOfSetPath(t *testing.T) {
 	}
 }
 
+func TestBuildValueOfSetPath_V1(t *testing.T) {
+
+	t.Run("path is empty", func(t *testing.T) {
+		_, err := BuildValueOfSetPath(nil, "")
+		assert.Error(t, err)
+		assert.EqualError(t, err, "set path is empty")
+	})
+
+	t.Run("value is empty", func(t *testing.T) {
+		actual, err := BuildValueOfSetPath(nil, "some.path")
+		assert.NoError(t, err)
+		assert.Equal(t, map[string]interface{}{
+			"some": map[string]interface{}{
+				"path": nil,
+			},
+		}, actual)
+	})
+
+	t.Run("some path", func(t *testing.T) {
+		expected := map[string]interface{}{
+			"b": map[string]interface{}{
+				"c": map[string]interface{}{
+					"a": 1,
+					"b": map[string]interface{}{
+						"c": 2,
+					}}}}
+		val := map[string]interface{}{
+			"a": 1,
+			"b": map[string]interface{}{
+				"c": 2,
+			},
+		}
+		path := "b.c"
+		result, err := BuildValueOfSetPath(val, path)
+		assert.NoError(t, err)
+		assert.Equal(t, expected, result)
+	})
+
+	t.Run("path is not in data", func(t *testing.T) {
+		expected := map[string]interface{}{
+			"some": map[string]interface{}{
+				"path": map[string]interface{}{
+					"ingress": map[string]interface{}{
+						"hosts[1]": "example.local",
+					},
+				},
+			},
+		}
+		var data = map[string]interface{}{
+			"ingress": map[string]interface{}{"hosts[1]": "example.local"},
+		}
+		actual, err := BuildValueOfSetPath(data, "some.path")
+		assert.NoError(t, err)
+		assert.Equal(t, expected, actual)
+	})
+
+	t.Run("path is in values", func(t *testing.T) {
+		expected := map[string]interface{}{
+			"hosts": map[string]interface{}{
+				"ingress": map[string]interface{}{
+					"hosts[1]": "example.local",
+				},
+			},
+		}
+		var data = map[string]interface{}{
+			"ingress": map[string]interface{}{"hosts[1]": "example.local"},
+		}
+		actual, err := BuildValueOfSetPath(data, "hosts")
+		assert.NoError(t, err)
+		assert.Equal(t, expected, actual)
+	})
+
+	t.Run("property testing", func(t *testing.T) {
+		data := map[string]interface{}{"foo": "bar"}
+		cases := []struct {
+			input  map[string]interface{}
+			path   string
+			exp    map[string]interface{}
+			expStr string
+		}{
+			{
+				path:   "a.b",
+				input:  map[string]interface{}{"a": map[string]interface{}{"b": data}},
+				exp:    map[string]interface{}{"a": map[string]interface{}{"b": map[string]interface{}{"a": map[string]interface{}{"b": data}}}},
+				expStr: "map[a:map[b:map[a:map[b:map[foo:bar]]]]]",
+			},
+			{
+				path:   "a[1]",
+				input:  map[string]interface{}{"a": []interface{}{nil, data}},
+				exp:    map[string]interface{}{"a": []interface{}{interface{}(nil), map[string]interface{}{"a": []interface{}{interface{}(nil), data}}}},
+				expStr: "map[a:[<nil> map[a:[<nil> map[foo:bar]]]]]",
+			},
+			{
+				path:   "a[1].b",
+				input:  map[string]interface{}{"a": []interface{}{nil, map[string]interface{}{"b": data}}},
+				exp:    map[string]interface{}{"a": []interface{}{interface{}(nil), map[string]interface{}{"b": map[string]interface{}{"a": []interface{}{interface{}(nil), map[string]interface{}{"b": data}}}}}},
+				expStr: "map[a:[<nil> map[b:map[a:[<nil> map[b:map[foo:bar]]]]]]]",
+			},
+		}
+		for _, test := range cases {
+			t.Run(fmt.Sprintf("path %s and values '%v", test.path, test.input), func(t *testing.T) {
+				actual, err := BuildValueOfSetPath(test.input, test.path)
+				assert.NoError(t, err)
+				assert.Equal(t, test.exp, actual)
+				assert.Equal(t, test.expStr, fmt.Sprintf("%v", actual))
+			})
+		}
+	})
+}
+
 func TestBuildValueSetPathError(t *testing.T) {
 	a := assert.New(t)
 	data := map[string]interface{}{"foo": "bar"}
 
 	var expectionsMapping = map[string]string{
-		"":   "set path is empty",
-		"{":  "invalid token found {",
-		"[[": "invalid escaping token [",
-		"..": "unexpected end of",
+		"":         "set path is empty",
+		"{":        "invalid token found {",
+		"[[":       "invalid escaping token [",
+		"..":       "unexpected end of",
+		"foo[1.1]": "missing index value",
+		"foo[]":    "strconv.Atoi: parsing \"\": invalid syntax",
+		"foo]":     "invalid key ]",
 	}
 
 	for path, expect := range expectionsMapping {
@@ -97,13 +213,13 @@ func TestBuildValueSetPathError(t *testing.T) {
 
 func TestMergeValues(t *testing.T) {
 	a := assert.New(t)
-	dest := map[string]interface{}{
+	src := map[string]interface{}{
 		"a": map[string]interface{}{
 			"b":   []interface{}{"_", map[string]interface{}{"c": "yes"}},
 			"e.f": "false",
 		},
 	}
-	src := map[string]interface{}{
+	dest := map[string]interface{}{
 		"a": map[string]interface{}{
 			"b":   []interface{}{"_", map[string]interface{}{"c": "no"}, "a"},
 			"d":   "no",
@@ -117,6 +233,360 @@ func TestMergeValues(t *testing.T) {
 			"e.f": "yes",
 		},
 	}
-	actual := MergeValues(dest, src)
+	actual := v3util.MergeTables(dest, src)
 	a.Equal(expected, actual)
 }
+
+func TestMergeValues_Cases(t *testing.T) {
+
+	t.Run("SimpleMerge", func(t *testing.T) {
+		src := map[string]interface{}{"a": 1, "b": 2}
+		dest := map[string]interface{}{"c": 3, "d": 4}
+		expected := map[string]interface{}{"a": 1, "b": 2, "c": 3, "d": 4}
+		result := v3util.MergeTables(dest, src)
+		assert.Equal(t, expected, result)
+	})
+
+	t.Run("OverwriteExistingValue", func(t *testing.T) {
+		src := map[string]interface{}{"a": 1}
+		dest := map[string]interface{}{"a": 2}
+		expected := map[string]interface{}{"a": 2}
+		result := v3util.MergeTables(dest, src)
+		assert.Equal(t, expected, result)
+	})
+
+	t.Run("MergeNestedMaps", func(t *testing.T) {
+		src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+		dest := map[string]interface{}{"a": map[string]interface{}{"c": 2}}
+		expected := map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}
+		result := v3util.MergeTables(dest, src)
+		assert.Equal(t, expected, result)
+	})
+
+	t.Run("OverwriteNestedMap", func(t *testing.T) {
+		src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+		dest := map[string]interface{}{"a": 2}
+		expected := map[string]interface{}{"a": 2}
+		result := v3util.MergeTables(dest, src)
+		assert.Equal(t, expected, result)
+	})
+
+	t.Run("MergeComplexMaps", func(t *testing.T) {
+		src := map[string]interface{}{
+			"a": 1,
+			"b": map[string]interface{}{
+				"c": 2,
+			},
+		}
+		dest := map[string]interface{}{
+			"a": 3,
+			"b": map[string]interface{}{
+				"d": 4,
+			},
+			"e": 5,
+		}
+		expected := map[string]interface{}{
+			"a": 3,
+			"b": map[string]interface{}{
+				"c": 2,
+				"d": 4,
+			},
+			"e": 5,
+		}
+		result := v3util.MergeTables(dest, src)
+		assert.Equal(t, expected, result)
+	})
+}
+
+func TestMergeValues_YamlValues(t *testing.T) {
+	t.Run("first", func(t *testing.T) {
+		yamlSrc := `
+a:
+  b:
+   foo: bar
+`
+		yamlDst := `
+a:
+  hosts[0]: abrakadabra
+`
+		expected := `
+a:
+  b:
+   foo: bar
+  hosts[0]: abrakadabra
+`
+		var dataSrc map[string]interface{}
+		common.YmlUnmarshalTestHelper(yamlSrc, &dataSrc, t)
+		var dataDst map[string]interface{}
+		common.YmlUnmarshalTestHelper(yamlDst, &dataDst, t)
+
+		output := v3util.MergeTables(dataDst, dataSrc)
+		out, _ := common.YmlMarshall(&output)
+		assert.YAMLEq(t, expected, out)
+	})
+
+	t.Run("second", func(t *testing.T) {
+		yamlSrc := `
+a:
+  b:
+   hosts:
+   - foo
+   - bar
+`
+		yamlDst := `
+a:
+  b:
+   hosts[0]: abrakadabra
+`
+		expected := `
+a:
+  b:
+   hosts:
+   - foo
+   - bar
+   hosts[0]: abrakadabra
+`
+		var dataSrc map[string]interface{}
+		common.YmlUnmarshalTestHelper(yamlSrc, &dataSrc, t)
+		var dataDst map[string]interface{}
+		common.YmlUnmarshalTestHelper(yamlDst, &dataDst, t)
+
+		output := v3util.MergeTables(dataDst, dataSrc)
+		out := common.YmlMarshallTestHelper(&output, t)
+		assert.YAMLEq(t, expected, out)
+	})
+}
+
+func TestGetValueOfSetPath(t *testing.T) {
+	t.Run("invalid-path", func(t *testing.T) {
+		yml := `
+kind: Deployment
+metadata:
+  name: my-deployment
+`
+		var dataDst map[string]interface{}
+		common.YmlUnmarshalTestHelper(yml, &dataDst, t)
+
+		actual, err := GetValueOfSetPath(dataDst, "invalid.path")
+		assert.NoError(t, err)
+		assert.Empty(t, actual)
+	})
+
+	t.Run("valid-path", func(t *testing.T) {
+		yml := `
+kind: Deployment
+metadata:
+  name: my-deployment
+`
+		var dataDst map[string]interface{}
+		common.YmlUnmarshalTestHelper(yml, &dataDst, t)
+
+		actual, err := GetValueOfSetPath(dataDst, "metadata.name")
+		assert.NoError(t, err)
+		assert.Equal(t, []interface{}{"my-deployment"}, actual)
+	})
+}
+
+func TestBuildValueOfSetPath_EmptyPath(t *testing.T) {
+	_, err := BuildValueOfSetPath(nil, "")
+	assert.Error(t, err)
+	assert.EqualError(t, err, "set path is empty")
+}
+
+func TestBuildValueOfSetPath_ValidPath(t *testing.T) {
+	data := map[string]interface{}{"foo": "bar"}
+	expected := map[string]interface{}{"a": map[string]interface{}{"b": data}}
+	actual, err := BuildValueOfSetPath(data, "a.b")
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
+
+func TestBuildValueOfSetPath_InvalidToken(t *testing.T) {
+	data := map[string]interface{}{"foo": "bar"}
+	_, err := BuildValueOfSetPath(data, "{")
+	assert.Error(t, err)
+	assert.EqualError(t, err, "invalid token found {")
+}
+
+func TestBuildValueOfSetPath_UnexpectedEnd(t *testing.T) {
+	data := map[string]interface{}{"foo": "bar"}
+	_, err := BuildValueOfSetPath(data, "a[")
+	assert.Error(t, err)
+	assert.EqualError(t, err, "unexpected end of")
+}
+
+func TestBuildValueOfSetPath_NestedPath(t *testing.T) {
+	data := map[string]interface{}{"foo": "bar"}
+	expected := map[string]interface{}{
+		"a": map[string]interface{}{
+			"b": map[string]interface{}{
+				"c": data,
+			},
+		},
+	}
+	actual, err := BuildValueOfSetPath(data, "a.b.c")
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
+
+// merge values
+func TestMergeValues_EmptySource(t *testing.T) {
+	src := map[string]interface{}{"a": 1}
+	dest := map[string]interface{}{}
+	expected := map[string]interface{}{"a": 1}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_EmptyDestination(t *testing.T) {
+	src := map[string]interface{}{}
+	dest := map[string]interface{}{"a": 1}
+	expected := map[string]interface{}{"a": 1}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_NilDestination(t *testing.T) {
+	src := map[string]interface{}{"a": 1}
+	dest := map[string]interface{}{}
+	expected := map[string]interface{}{"a": 1}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_NilSource(t *testing.T) {
+	src := map[string]interface{}{}
+	dest := map[string]interface{}{"a": 1}
+	expected := map[string]interface{}{"a": 1}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_OverwriteWithNonMap(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	dest := map[string]interface{}{"a": 2}
+	expected := map[string]interface{}{"a": 2}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_DeepMerge(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	dest := map[string]interface{}{"a": map[string]interface{}{"c": 2}}
+	expected := map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_ComplexMerge(t *testing.T) {
+	src := map[string]interface{}{
+		"a": 1,
+		"b": map[string]interface{}{
+			"c": 2,
+		},
+	}
+	dest := map[string]interface{}{
+		"a": 3,
+		"b": map[string]interface{}{
+			"d": 4,
+		},
+		"e": 5,
+	}
+	expected := map[string]interface{}{
+		"a": 3,
+		"b": map[string]interface{}{
+			"c": 2,
+			"d": 4,
+		},
+		"e": 5,
+	}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+// new
+func TestMergeValues_KeyExistsButNotMap(t *testing.T) {
+	src := map[string]interface{}{
+		"a": 1,
+	}
+	dest := map[string]interface{}{
+		"a": map[string]interface{}{"b": 2},
+	}
+	expected := map[string]interface{}{
+		"a": map[string]interface{}{"b": 2},
+	}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_KeyExistsAndIsMap(t *testing.T) {
+	src := map[string]interface{}{
+		"a": map[string]interface{}{"b": 1},
+	}
+	dest := map[string]interface{}{
+		"a": map[string]interface{}{"c": 2},
+	}
+	expected := map[string]interface{}{
+		"a": map[string]interface{}{"b": 1, "c": 2},
+	}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_EmptySourceAndDestination(t *testing.T) {
+	src := map[string]interface{}{}
+	dest := map[string]interface{}{}
+	expected := map[string]interface{}{}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_DestinationWithNilValue(t *testing.T) {
+	src := map[string]interface{}{"a": 1}
+	dest := map[string]interface{}{"b": nil}
+	expected := map[string]interface{}{"a": 1, "b": nil}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_SourceWithNilValue(t *testing.T) {
+	src := map[string]interface{}{"a": nil}
+	dest := map[string]interface{}{"b": 2}
+	expected := map[string]interface{}{"a": nil, "b": 2}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_NestedMapWithEmptyMap(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	dest := map[string]interface{}{"a": map[string]interface{}{}}
+	expected := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_EmptyNestedMap(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{}}
+	dest := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	expected := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_OverwriteWithEmptyMap(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	dest := map[string]interface{}{"a": map[string]interface{}{"b": nil}}
+	expected := map[string]interface{}{"a": map[string]interface{}{"b": nil}}
+	// expected := map[string]interface{}{"a": map[string]interface{}{}}
+	// this is the expected result when v3util.CoalesceTables is used
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
+
+func TestMergeValues_OverwriteWithNil(t *testing.T) {
+	src := map[string]interface{}{"a": map[string]interface{}{"b": 1}}
+	dest := map[string]interface{}{"a": nil}
+	expected := map[string]interface{}{"a": nil}
+	actual := v3util.MergeTables(dest, src)
+	assert.Equal(t, expected, actual)
+}
diff --git a/test/data/v3/basic/templates/configmap.yaml b/test/data/v3/basic/templates/configmap.yaml
index 163d7e5..79cdd5f 100644
--- a/test/data/v3/basic/templates/configmap.yaml
+++ b/test/data/v3/basic/templates/configmap.yaml
@@ -24,3 +24,10 @@ data:
   special.array:
     - phony-service.phony:graphql
   my.camelcase: {{ .Values.configTests.camelcaseValue | camelcase }}
+  {{- if .Values.ingress.hosts }}
+  my.ingress.hosts:
+  {{- range $host := .Values.ingress.hosts }}
+  - {{ $host }}
+  {{- end -}}
+  {{- end -}}
+
diff --git a/test/data/v3/basic/templates/deployment.yaml b/test/data/v3/basic/templates/deployment.yaml
index 53dc1fd..a784136 100644
--- a/test/data/v3/basic/templates/deployment.yaml
+++ b/test/data/v3/basic/templates/deployment.yaml
@@ -19,7 +19,7 @@ spec:
         app: {{ template "basic.name" . }}
         release: {{ .Release.Name }}
     spec:
-      {{- if .Values.runAsUser }}
+      {{- if hasKey .Values "runAsUser" }}
       securityContext:
         runAsUser: {{ .Values.runAsUser }}
       {{- end }}
diff --git a/test/data/v3/basic/templates/pdp.yaml b/test/data/v3/basic/templates/pdp.yaml
new file mode 100644
index 0000000..36d6ef5
--- /dev/null
+++ b/test/data/v3/basic/templates/pdp.yaml
@@ -0,0 +1,7 @@
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+  name: {{ template "basic.fullname" . }}
+spec:
+  minAvailable: 2
+  unhealthyPodEvictionPolicy: AlwaysAllow
diff --git a/test/data/v3/basic/templates/servicemonitor.yaml b/test/data/v3/basic/templates/servicemonitor.yaml
index 017caaf..4b1e106 100644
--- a/test/data/v3/basic/templates/servicemonitor.yaml
+++ b/test/data/v3/basic/templates/servicemonitor.yaml
@@ -14,4 +14,4 @@ spec:
   namespaceSelector:
     matchNames:
       - prometheus
-  {{- end }}
+{{- end }}
diff --git a/test/data/v3/basic/tests/__snapshot__/deployment_test.yaml.snap b/test/data/v3/basic/tests/__snapshot__/deployment_test.yaml.snap
index 6fbadc0..6e095b8 100644
--- a/test/data/v3/basic/tests/__snapshot__/deployment_test.yaml.snap
+++ b/test/data/v3/basic/tests/__snapshot__/deployment_test.yaml.snap
@@ -22,3 +22,5 @@ should pass all kinds of assertion:
                 path: /
                 port: 8080
             resources: {}
+        securityContext:
+          runAsUser: 1000
diff --git a/test/data/v3/basic/tests/configmap_test.yaml b/test/data/v3/basic/tests/configmap_test.yaml
index 6977c49..d892b4f 100644
--- a/test/data/v3/basic/tests/configmap_test.yaml
+++ b/test/data/v3/basic/tests/configmap_test.yaml
@@ -4,6 +4,10 @@ templates:
 chart:
   appVersion: 1.0.1
   version: 0.1.0
+set:
+  # issue https://github.com/helm-unittest/helm-unittest/issues/471
+  ingress:
+    hosts[1]: override-example-global-1.local
 tests:
   - it: should NOT configure ssl params if NOT set to be exposed
     asserts:
@@ -83,3 +87,83 @@ tests:
       - equal:
           path: data["my.camelcase"]
           value: Camelcase
+
+  - it: should validate ingress hosts with root values
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - chart-example.local
+
+  - it: should override ingress hosts with set when array
+    set:
+      ingress:
+        hosts:
+        - override-example.local
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - override-example.local
+
+  - it: should patch ingress hosts
+    set:
+      ingress.hosts[0]: override-example-patch-0.local
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - override-example-patch-0.local
+
+# issue https://github.com/helm-unittest/helm-unittest/issues/471
+  - it: should patch ingress hosts with append.
+    set:
+      ingress.hosts[1]: override-example-patch-1.local
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - null
+            - override-example-patch-1.local
+
+  - it: "should have values set from file"
+    values:
+    - values/hosts.yaml
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - chart-example-first.local
+            - chart-example-second.local
+            - chart-example-third.local
+
+# issue https://github.com/helm-unittest/helm-unittest/issues/471
+  - it: "should have values set from file and patch second host"
+    values:
+    - values/hosts.yaml
+    set:
+      ingress.hosts[1]: override-example-patch-1.local
+    asserts:
+      - exists:
+          path: data["my.ingress.hosts"]
+      - equal:
+          path: data["my.ingress.hosts"]
+          value:
+            - null
+            - override-example-patch-1.local
+      - notEqual:
+          path: data["my.ingress.hosts"]
+          value:
+            - chart-example-first.local
+            - override-example-patch-1.local
+            - chart-example-third.local
diff --git a/test/data/v3/basic/tests/deployment_test.yaml b/test/data/v3/basic/tests/deployment_test.yaml
index cb2e574..9ccb2a9 100644
--- a/test/data/v3/basic/tests/deployment_test.yaml
+++ b/test/data/v3/basic/tests/deployment_test.yaml
@@ -35,6 +35,9 @@ tests:
       - notMatchRegex:
           path: metadata.name
           pattern: ^.*-foobar$
+      - equal:
+          path: spec.template.spec.securityContext.runAsUser
+          value: 1000
       - contains:
           path: spec.template.spec.containers[?(@.name == "basic")].ports
           content:
@@ -147,3 +150,12 @@ tests:
       - notGreaterOrEqual:
           path: spec.template.spec.containers[?(@.name == "basic")].resources.requests.memory
           value: "101Mi"
+
+  - it: should pass with no securityContext as runAsUser is removed
+    set:
+      runAsUser: null
+    template: templates/deployment.yaml
+    documentIndex: 0
+    asserts:
+      - notExists:
+          path: spec.template.spec.securityContext
diff --git a/test/data/v3/basic/tests/pdp_test.yaml b/test/data/v3/basic/tests/pdp_test.yaml
new file mode 100644
index 0000000..9311a2d
--- /dev/null
+++ b/test/data/v3/basic/tests/pdp_test.yaml
@@ -0,0 +1,11 @@
+suite: test pod disruption budget
+templates:
+  - templates/pdp.yaml
+tests:
+  - it: should pass all kinds of assertion
+    asserts:
+      - exists:
+          path: spec.minAvailable
+      - greaterOrEqual:
+          path: spec.minAvailable
+          value: 2
diff --git a/test/data/v3/basic/tests/secret_test.yaml b/test/data/v3/basic/tests/secret_test.yaml
index 0c08e0f..6b5de2d 100644
--- a/test/data/v3/basic/tests/secret_test.yaml
+++ b/test/data/v3/basic/tests/secret_test.yaml
@@ -3,8 +3,6 @@ templates:
   - templates/secret.yaml
 tests:
   - it: should use root values file with set few attributes in test
-    values:
-      - ../values.yaml
     set:
       secret:
         name: override-super-secret
@@ -25,8 +23,6 @@ templates:
   - templates/secret.yaml
 tests:
   - it: should use values file that not contains base64 values
-    values:
-      - ../values.yaml
     set:
       secret:
         password: somepassword
diff --git a/test/data/v3/basic/tests/values/hosts.yaml b/test/data/v3/basic/tests/values/hosts.yaml
new file mode 100644
index 0000000..40dd15c
--- /dev/null
+++ b/test/data/v3/basic/tests/values/hosts.yaml
@@ -0,0 +1,5 @@
+ingress:
+  hosts:
+    - chart-example-first.local
+    - chart-example-second.local
+    - chart-example-third.local
diff --git a/test/data/v3/basic/tests_failed/__snapshot__/deployment_test.yaml.snap b/test/data/v3/basic/tests_failed/__snapshot__/deployment_test.yaml.snap
index 4aa0289..6ede394 100644
--- a/test/data/v3/basic/tests_failed/__snapshot__/deployment_test.yaml.snap
+++ b/test/data/v3/basic/tests_failed/__snapshot__/deployment_test.yaml.snap
@@ -22,6 +22,8 @@ should fail all kinds of assertion:
                 path: /
                 port: 8080
             resources: {}
+        securityContext:
+          runAsUser: 1000
   2: |
     replicas: 1
     template:
diff --git a/test/data/v3/basic/values.yaml b/test/data/v3/basic/values.yaml
index d5f8854..1703e3e 100644
--- a/test/data/v3/basic/values.yaml
+++ b/test/data/v3/basic/values.yaml
@@ -44,3 +44,5 @@ configTests:
   camelcaseValue: camelcase
 
 supportPod: {}
+
+runAsUser: 1000