Repository: pantsbuild/pants

Issue:
Helm Unittest values and snapshot testing issue
**Describe the bug**
Helm unittesting doesn't work if [`values` section](https://github.com/quintush/helm-unittest/blob/master/DOCUMENT.md#test-job) is present in *_test.yaml instead of `set`. 

Another point is that if [snapshotting testing](https://github.com/quintush/helm-unittest#snapshot-testing) is used it seems that snapshots in `__snapshot__/` directory are ignored and any changes to tests or values in `set` section doesn't affect the tests run - it's still successful.

**Pants version**
2.15.1

**OS**
both

**Additional info**
1. Consider the following setup
  ```
  # deployment_test.yaml
  tests:
    - it: checks correct number of replicas
      asserts:
        - equal:
            path: spec.replicas
            value: 2
      values:
        - general_values.yaml
      # IF COMMENT `values` section and uncomment `set` - it works fine.
      # set:
      #   replicaCount: 2
  
  # BUILD
  helm_unittest_tests(
    sources=[
      "*_test.yaml",
      "general_values.yaml"
    ]
  )
  
  # general_values.yaml
  
  replicaCount: 2
  
  serviceAccount:
    name: opa
  ```
  The error occurs:
  ```
  pants test ::
13:07:38.10 [INFO] Completed: Running Helm unittest suite awesome/tests/deployment_test.yaml
13:07:38.11 [ERROR] Completed: Run Helm Unittest - awesome/tests/deployment_test.yaml - failed (exit code 1).

### Chart [ awesome ] awesome

 FAIL  test deployment  awesome/tests/deployment_test.yaml
        - checks correct number of replicas
                Error: open awesome/tests/general_values.yaml: no such file or directory
  ```

2. Snapshot testing is also behaves not as expected. So, according to the documentation you need to generate `.snap` file and put it into `__snapshot__` directory. When test runs it compares the output value with the snapshot. While the manifest is generated during the run it doesn't seem to actually compare the result with the snapshot, because any changes to either to snapshot or to values in `set` section doesn't doesn't impact test results - it's always successful. 

Might be related - https://github.com/pantsbuild/pants/issues/16532

---

I believe both cases are might be related to the same issue and it's related to missing logic on how unittests are integrated into pants. Though I might missing some piece of documentation as well, in that case would appreciate any help :)



Discussion:

Resolving patch:
diff --git a/src/python/pants/backend/helm/dependency_inference/deployment.py b/src/python/pants/backend/helm/dependency_inference/deployment.py
--- a/src/python/pants/backend/helm/dependency_inference/deployment.py
+++ b/src/python/pants/backend/helm/dependency_inference/deployment.py
@@ -132,7 +132,7 @@ async def first_party_helm_deployment_mapping(
     docker_target_addresses = {tgt.address.spec: tgt.address for tgt in docker_targets}
 
     def lookup_docker_addreses(image_ref: str) -> tuple[str, Address] | None:
-        addr = docker_target_addresses.get(str(image_ref), None)
+        addr = docker_target_addresses.get(image_ref, None)
         if addr:
             return image_ref, addr
         return None


Test patch:
diff --git a/src/python/pants/backend/helm/test/unittest.py b/src/python/pants/backend/helm/test/unittest.py
--- a/src/python/pants/backend/helm/test/unittest.py
+++ b/src/python/pants/backend/helm/test/unittest.py
@@ -26,8 +26,9 @@
 from pants.backend.helm.util_rules.tool import HelmProcess
 from pants.base.deprecated import warn_or_error
 from pants.core.goals.test import TestFieldSet, TestRequest, TestResult, TestSubsystem
-from pants.core.target_types import ResourceSourceField
+from pants.core.target_types import FileSourceField, ResourceSourceField
 from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
+from pants.core.util_rules.stripped_source_files import StrippedSourceFiles
 from pants.engine.addresses import Address
 from pants.engine.fs import AddPrefix, Digest, MergeDigests, RemovePrefix, Snapshot
 from pants.engine.process import FallibleProcessResult, ProcessCacheScope
@@ -89,21 +90,18 @@ async def run_helm_unittest(
         raise MissingUnitTestChartDependency(field_set.address)
 
     chart_target = chart_targets[0]
-    chart, chart_root, test_files = await MultiGet(
+    chart, chart_root, test_files, extra_files = await MultiGet(
         Get(HelmChart, HelmChartRequest, HelmChartRequest.from_target(chart_target)),
         Get(HelmChartRoot, HelmChartRootRequest(chart_target[HelmChartMetaSourceField])),
         Get(
             SourceFiles,
+            SourceFilesRequest(sources_fields=[field_set.source]),
+        ),
+        Get(
+            StrippedSourceFiles,
             SourceFilesRequest(
-                sources_fields=[
-                    field_set.source,
-                    *(
-                        tgt.get(SourcesField)
-                        for tgt in transitive_targets.dependencies
-                        if not HelmChartFieldSet.is_applicable(tgt)
-                    ),
-                ],
-                for_sources_types=(HelmUnitTestSourceField, ResourceSourceField),
+                sources_fields=[tgt.get(SourcesField) for tgt in transitive_targets.dependencies],
+                for_sources_types=(ResourceSourceField, FileSourceField),
                 enable_codegen=True,
             ),
         ),
@@ -118,7 +116,7 @@ async def run_helm_unittest(
 
     merged_digests = await Get(
         Digest,
-        MergeDigests([chart.snapshot.digest, stripped_test_files]),
+        MergeDigests([chart.snapshot.digest, stripped_test_files, extra_files.snapshot.digest]),
     )
     input_digest = await Get(Digest, AddPrefix(merged_digests, chart.name))
 
diff --git a/src/python/pants/backend/helm/test/unittest_test.py b/src/python/pants/backend/helm/test/unittest_test.py
--- a/src/python/pants/backend/helm/test/unittest_test.py
+++ b/src/python/pants/backend/helm/test/unittest_test.py
@@ -5,8 +5,12 @@
 
 import pytest
 
-from pants.backend.helm.target_types import HelmChartTarget, HelmUnitTestTestTarget
-from pants.backend.helm.target_types import rules as target_types_rules
+from pants.backend.helm.target_types import (
+    HelmChartTarget,
+    HelmUnitTestTestsGeneratorTarget,
+    HelmUnitTestTestTarget,
+)
+from pants.backend.helm.target_types import rules as helm_target_types_rules
 from pants.backend.helm.test.unittest import HelmUnitTestFieldSet, HelmUnitTestRequest
 from pants.backend.helm.test.unittest import rules as unittest_rules
 from pants.backend.helm.testutil import (
@@ -17,7 +21,14 @@
 )
 from pants.backend.helm.util_rules import chart
 from pants.core.goals.test import TestResult
-from pants.core.util_rules import external_tool, source_files
+from pants.core.target_types import (
+    FilesGeneratorTarget,
+    FileTarget,
+    RelocatedFiles,
+    ResourcesGeneratorTarget,
+)
+from pants.core.target_types import rules as target_types_rules
+from pants.core.util_rules import external_tool, source_files, stripped_source_files
 from pants.engine.addresses import Address
 from pants.engine.rules import QueryRule
 from pants.source.source_root import rules as source_root_rules
@@ -27,13 +38,23 @@
 @pytest.fixture
 def rule_runner() -> RuleRunner:
     return RuleRunner(
-        target_types=[HelmChartTarget, HelmUnitTestTestTarget],
+        target_types=[
+            HelmChartTarget,
+            HelmUnitTestTestTarget,
+            HelmUnitTestTestsGeneratorTarget,
+            ResourcesGeneratorTarget,
+            FileTarget,
+            FilesGeneratorTarget,
+            RelocatedFiles,
+        ],
         rules=[
             *external_tool.rules(),
             *chart.rules(),
             *unittest_rules(),
             *source_files.rules(),
             *source_root_rules(),
+            *helm_target_types_rules(),
+            *stripped_source_files.rules(),
             *target_types_rules(),
             QueryRule(TestResult, (HelmUnitTestRequest.Batch,)),
         ],
@@ -153,3 +174,241 @@ def test_simple_failure(rule_runner: RuleRunner) -> None:
 
     result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
     assert result.exit_code == 1
+
+
+def test_test_with_local_resource_file(rule_runner: RuleRunner) -> None:
+    rule_runner.write_files(
+        {
+            "BUILD": "helm_chart(name='mychart')",
+            "Chart.yaml": HELM_CHART_FILE,
+            "templates/configmap.yaml": dedent(
+                """\
+                apiVersion: v1
+                kind: ConfigMap
+                metadata:
+                  name: foo-config
+                data:
+                  foo_key: {{ .Values.input }}
+                """
+            ),
+            "tests/BUILD": dedent(
+                """\
+                helm_unittest_test(name="test", source="configmap_test.yaml", dependencies=[":values"])
+
+                resources(name="values", sources=["general-values.yml"])
+                """
+            ),
+            "tests/configmap_test.yaml": dedent(
+                """\
+                suite: test config map
+                templates:
+                  - configmap.yaml
+                values:
+                  - general-values.yml
+                tests:
+                  - it: should work
+                    asserts:
+                      - equal:
+                          path: data.foo_key
+                          value: bar_input
+                """
+            ),
+            "tests/general-values.yml": dedent(
+                """\
+                input: bar_input
+                """
+            ),
+        }
+    )
+
+    target = rule_runner.get_target(Address("tests", target_name="test"))
+    field_set = HelmUnitTestFieldSet.create(target)
+
+    result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
+    assert result.exit_code == 0
+
+
+def test_test_with_non_local_resource_file(rule_runner: RuleRunner) -> None:
+    rule_runner.write_files(
+        {
+            "src/helm/BUILD": "helm_chart(name='mychart')",
+            "src/helm/Chart.yaml": HELM_CHART_FILE,
+            "src/helm/templates/configmap.yaml": dedent(
+                """\
+                apiVersion: v1
+                kind: ConfigMap
+                metadata:
+                  name: foo-config
+                data:
+                  foo_key: {{ .Values.input }}
+                """
+            ),
+            "src/helm/tests/BUILD": dedent(
+                """\
+                helm_unittest_test(
+                  name="test",
+                  source="configmap_test.yaml",
+                  dependencies=["//resources/data:values"]
+                )
+                """
+            ),
+            "src/helm/tests/configmap_test.yaml": dedent(
+                """\
+                suite: test config map
+                templates:
+                  - configmap.yaml
+                values:
+                  - ../data/general-values.yml
+                tests:
+                  - it: should work
+                    asserts:
+                      - equal:
+                          path: data.foo_key
+                          value: bar_input
+                """
+            ),
+            "resources/data/BUILD": dedent(
+                """\
+              resources(name="values", sources=["general-values.yml"])
+              """
+            ),
+            "resources/data/general-values.yml": dedent(
+                """\
+                input: bar_input
+                """
+            ),
+        }
+    )
+
+    source_roots = ["resources"]
+    rule_runner.set_options([f"--source-root-patterns={repr(source_roots)}"])
+    target = rule_runner.get_target(Address("src/helm/tests", target_name="test"))
+    field_set = HelmUnitTestFieldSet.create(target)
+
+    result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
+    assert result.exit_code == 0
+
+
+def test_test_with_global_file(rule_runner: RuleRunner) -> None:
+    rule_runner.write_files(
+        {
+            "src/helm/BUILD": "helm_chart(name='mychart')",
+            "src/helm/Chart.yaml": HELM_CHART_FILE,
+            "src/helm/templates/configmap.yaml": dedent(
+                """\
+                apiVersion: v1
+                kind: ConfigMap
+                metadata:
+                  name: foo-config
+                data:
+                  foo_key: {{ .Values.input }}
+                """
+            ),
+            "src/helm/tests/BUILD": dedent(
+                """\
+                helm_unittest_test(
+                  name="test",
+                  source="configmap_test.yaml",
+                  dependencies=["//files/data:values"]
+                )
+                """
+            ),
+            "src/helm/tests/configmap_test.yaml": dedent(
+                """\
+                suite: test config map
+                templates:
+                  - configmap.yaml
+                values:
+                  - ../files/data/general-values.yml
+                tests:
+                  - it: should work
+                    asserts:
+                      - equal:
+                          path: data.foo_key
+                          value: bar_input
+                """
+            ),
+            "files/data/BUILD": dedent(
+                """\
+              files(name="values", sources=["general-values.yml"])
+              """
+            ),
+            "files/data/general-values.yml": dedent(
+                """\
+                input: bar_input
+                """
+            ),
+        }
+    )
+
+    target = rule_runner.get_target(Address("src/helm/tests", target_name="test"))
+    field_set = HelmUnitTestFieldSet.create(target)
+
+    result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
+    assert result.exit_code == 0
+
+
+def test_test_with_relocated_file(rule_runner: RuleRunner) -> None:
+    rule_runner.write_files(
+        {
+            "src/helm/BUILD": "helm_chart(name='mychart')",
+            "src/helm/Chart.yaml": HELM_CHART_FILE,
+            "src/helm/templates/configmap.yaml": dedent(
+                """\
+                apiVersion: v1
+                kind: ConfigMap
+                metadata:
+                  name: foo-config
+                data:
+                  foo_key: {{ .Values.input }}
+                """
+            ),
+            "src/helm/tests/BUILD": dedent(
+                """\
+                helm_unittest_test(
+                  name="test",
+                  source="configmap_test.yaml",
+                  dependencies=[":relocated"]
+                )
+
+                relocated_files(
+                  name="relocated",
+                  files_targets=["//files/data:values"],
+                  src="files/data",
+                  dest="tests"
+                )
+                """
+            ),
+            "src/helm/tests/configmap_test.yaml": dedent(
+                """\
+                suite: test config map
+                templates:
+                  - configmap.yaml
+                values:
+                  - general-values.yml
+                tests:
+                  - it: should work
+                    asserts:
+                      - equal:
+                          path: data.foo_key
+                          value: bar_input
+                """
+            ),
+            "files/data/BUILD": dedent(
+                """\
+              files(name="values", sources=["general-values.yml"])
+              """
+            ),
+            "files/data/general-values.yml": dedent(
+                """\
+                input: bar_input
+                """
+            ),
+        }
+    )
+
+    target = rule_runner.get_target(Address("src/helm/tests", target_name="test"))
+    field_set = HelmUnitTestFieldSet.create(target)
+
+    result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
+    assert result.exit_code == 0