GithubHelp home page GithubHelp logo

helm-unittest / helm-unittest Goto Github PK

View Code? Open in Web Editor NEW
750.0 8.0 248.0 1.38 MB

BDD styled unit test framework for Kubernetes Helm charts as a Helm plugin.

License: MIT License

Go 93.30% Makefile 0.92% Shell 2.33% Dockerfile 0.86% Mustache 1.51% Smarty 1.07%
helm kubernetes unittest testing helm-chart helm-plugin

helm-unittest's Introduction

helm unittest

CircleCI Go Report Card Quality Gate Status

Unit test for helm chart in YAML to keep your chart consistent and robust!

Feature:

Documentation

If you are ready for writing tests, check the DOCUMENT for the test API in YAML.

Install

$ helm plugin install https://github.com/helm-unittest/helm-unittest.git

It will install the latest version of binary into helm plugin directory.

Docker Usage

# run help of latest helm with latest helm unittest plugin
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest

# run help of specific helm version with specific helm unittest plugin version
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0

# run unittests of a helm 3 chart
# make sure to mount local folder to /apps in container
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0 .

# run unittests of a helm 3 chart with Junit output for CI validation
# make sure to mount local folder to /apps in container
# the test-output.xml will be available in the local folder.
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0 -o test-output.xml -t junit .

The docker container contains the fully installed helm client, including the helm-unittest plugin.

Get Started

Add tests in .helmignore of your chart, and create the following test file at $YOUR_CHART/tests/deployment_test.yaml:

suite: test deployment
templates:
  - deployment.yaml
tests:
  - it: should work
    set:
      image.tag: latest
    asserts:
      - isKind:
          of: Deployment
      - matchRegex:
          path: metadata.name
          pattern: -my-chart$
      - equal:
          path: spec.template.spec.containers[0].image
          value: nginx:latest

and run:

$ helm unittest $YOUR_CHART

Now there is your first test! ;)

Test Suite File

The test suite file is written in pure YAML, and default placed under the tests/ directory of the chart with suffix _test.yaml. You can also have your own suite files arrangement with -f, --file option of cli set as the glob patterns of test suite files related to chart directory, like:

$ helm unittest -f 'my-tests/*.yaml' -f 'more-tests/**/*.yaml' my-chart

Check DOCUMENT for more details about writing tests.

Templated Test Suites

You may find yourself needing to set up a lots o tests that are a parameterization of a single test. For instance, let's say that you deploy to 3 environments env = dev | staging | prod.

In order to do this, you can actually write your tests as a helm chart as well. If you go about this route, you must set the --chart-tests-path option. Once you have done so, helm unittest will run a standard helm render against the values.yaml in your specified directory.

/my-chart
  /tests-chart
    /Chart.yaml
    /values.yaml
    /templates
      /per_env_snapshots.yaml

  /Chart.yaml
  /values.yaml
  /.helmignore
  /templates
    /actual_template.yaml

In the above example file structure, you would maintain a helm chart that will render out against the Chart.yaml that as provided and the values.yaml. With rendered charts, any test suite that is generated is automatically ran we do not look for a file postfix or glob.

Note: since you can create multiple suites in a single template file, you must provide the suite name, since we can no longer use the test suite file name meaningfully.

Note 2: since you can be running against subcharts and multiple charts, you need to make sure that you do not designate your --chart-tests-path to be the same folder as your other tests. This is because we will try to render those non-helm test folders and fail during the unit test.

Note 3: for snapshot tests, you will need to provide a helm ignore that ignores */__snapshot__/*. Otherwise, subsequent runs will try to render those snapshots.

The command for the above chart and test configuration would be:

helm unittest --chart-tests-path tests-chart my-chart

Usage

$ helm unittest [flags] CHART [...]

This renders your charts locally (without tiller) and runs tests defined in test suite files.

Flags

      --color                  enforce printing colored output even stdout is not a tty. Set to false to disable color
      --strict                 strict parse the testsuites (default false)
  -d  --debugPlugin            enable debug logging (default false)
  -v, --values stringArray     absolute or glob paths of values files location to override helmchart values
  -f, --file stringArray       glob paths of test files location, default to tests\*_test.yaml (default [tests\*_test.yaml])
  -q, --failfast               direct quit testing, when a test is failed (default false)
  -h, --help                   help for unittest
  -t, --output-type string     the file-format where testresults are written in, accepted types are (JUnit, NUnit, XUnit) (default XUnit)
  -o, --output-file string     the file where testresults are written in format specified, defaults no output is written to file
  -u, --update-snapshot        update the snapshot cached if needed, make sure you review the change before update
  -s, --with-subchart charts   include tests of the subcharts within charts folder (default true)
      --chart-tests-path string the folder location relative to the chart where a helm chart to render test suites is located

Yaml JsonPath Support

Now JsonPath is supported for mappings and arrays. This makes it possible to find items in an array, based on JsonPath. For more detail on the jsonPath syntax.

Due to the change to JsonPath, the map keys in path containing periods (.) or special characters (/) are now supported with the use of "":

- equal:
    path: metadata.annotations["kubernetes.io/ingress.class"]
    value: nginx

The next releases it will be possible to validate multiple paths when JsonPath result into multiple results.

DocumentSelector

The test job or assertion can also specify a documentSelector rather than a documentIndex. Note that the documentSelector will always override a documentIndex if a match is found. This field is particularly useful when helm produces multiple templates and the order is not always guaranteed.

The path in the documentSelector has Yaml JsonPath Support, using JsonPath expressions it is possible to filter on multiple fields.

The value in the documentSelector can validate complete yaml objects.

...
tests:
  - it: should pass
    values:
      - ./values/staging.yaml
    set:
      image.pullPolicy: Always
      resources:
        limits:
          memory: 128Mi
    template: deployment.yaml
    documentSelector:
      path: metadata.name
      value: my-service-name
    asserts:
      - equal:
          path: metadata.name
          value: my-deploy

Example

Check test/data/v3/basic/ for some basic use cases of a simple chart.

Snapshot Testing

Sometimes you may just want to keep the rendered manifest not changed between changes without every details asserted. That's the reason for snapshot testing! Check the tests below:

templates:
  - templates/deployment.yaml
tests:
  - it: pod spec should match snapshot
    asserts:
      - matchSnapshot:
          path: spec.template.spec
  # or you can snapshot the whole manifest
  - it: manifest should match snapshot
    asserts:
      - matchSnapshot: {}

The matchSnapshot assertion validate the content rendered the same as cached last time. It fails if the content changed, and you should check and update the cache with -u, --update-snapshot option of cli.

$ helm unittest -u my-chart

The cache files is stored as __snapshot__/*_test.yaml.snap at the directory your test file placed, you should add them in version control with your chart.

Dependent subchart Testing

If you have hard dependency subcharts (installed via helm dependency) existed in charts directory (they don't need to be extracted), it is possible to unittest these from the root chart. This feature can be helpful to validate if good default values are accidentally overwritten within your default helm chart.

# $YOUR_CHART/tests/xxx_test.yaml
templates:
  - charts/postgresql/templates/xxx.yaml
tests:
  - it:
    set:
      # this time required to prefix with "postgresql."
      postgresql.somevalue: should_be_scoped
    asserts:
      - ...

Note 1: if dependent subcharts uses an alias, use the alias name in the templates. Note 2: using the folder structure in templates can also be used to unittest templates which are placed in subfolders or unittest subcharts from the rootchart.

Check test/data/v3/with-subchart/ as an example.

Tests within subchart

If you have customized hard dependency subchart (not installed via helm dependency, but added manually) existed in charts directory, tests inside would also be executed by default. You can disable this behavior by setting --with-subchart=false flag in cli, thus only the tests in root chart will be executed. Notice that the values defined in subchart tests will be automatically scoped, you don't have to add dependency scope yourself:

# with-subchart/charts/child-chart/tests/xxx_test.yaml
templates:
  - templates/xxx.yaml
tests:
  - it:
    set:
      # no need to prefix with "child-chart."
      somevalue: should_be_scoped
    asserts:
      - ...

Check test/data/v3/with-subchart/ as an example.

Test Suite code completion and validation

Most popular IDEs (IntelliJ, Visual Studio Code, etc.) support applying schemas to YAML files using a JSON Schema. This provides comprehensive documentation as well as code completion while editing the test-suite file:

Code completion

In addition, test-suite files can be validated while editing so wrongfully added additional properties or incorrect data types can be detected while editing:

Code Validation

Visual Studio Code

When developing with VSCode, the very popular YAML plug-in (created by RedHat) allows adding references to schemas by adding a comment line on top of the file:

# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json
suite: http-service.configmap_test.yaml
templates: [configmap.yaml]
release:
  name: test-release
  namespace: TEST_NAMESPACE

Alternatively, you can add the schema globally to the IDE, using a well defined pattern:

"yaml.schemas": {
  "https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json": ["charts/*/tests/*_test.yaml"]
}

IntelliJ

Similar to VSCode, IntelliJ allows mapping file patterns to schemas via preferences: Languages & Frameworks -> Schemas and DTDs -> JSON Schema Mappings

Add Json Schema

Frequently Asked Questions

As more people use the unittest plugin, more questions will come. Therefore a Frequently Asked Question page is created to answer the most common questions.

If you are missing an answer to a question, feel free to raise a ticket.

Related Projects / Commands

This plugin is inspired by helm-template, and the idea of snapshot testing and some printing format comes from jest.

And there are some other helm commands you might want to use:

  • helm template: render the chart and print the output.

  • helm lint: examines a chart for possible issues, useful to validate chart dependencies.

  • helm test: test a release with testing pod defined in chart. Note this does create resources on your cluster to verify if your release is correct. Check the doc.

Alternatively, you can also use generic tests frameworks:

License

MIT

Contributing

Issues and PRs are welcome! Before start developing this plugin, you must have Go >= 1.21 installed, and run:

git clone [email protected]:helm-unittest/helm-unittest.git
cd helm-unittest

And please make CI passed when request a PR which would check following things:

  • gofmt no changes needed. Please run gofmt -w -s . before you commit.
  • go test ./pkg/unittest/... passed.

In some cases you might need to manually fix the tests in *_test.go. If the snapshot tests (of the plugin's test code) failed, you need to run:

UPDATE_SNAPSHOTS=true go test ./...

This update the snapshot cache file and please add them before you commit.

helm-unittest's People

Contributors

armingerten avatar aroberts87 avatar cgroschupp avatar chrira avatar fcbry avatar gionn avatar hanseltime avatar hugoshaka avatar iben12 avatar ivankatliarchuk avatar jdiegosierra avatar jgarec avatar jglick avatar johntellsall avatar justusbunsi avatar kdhtrifork avatar kenji-fukasawa avatar krichter722 avatar lrills avatar mavimo avatar mederel avatar mik-laj avatar quintush avatar stavros-k avatar syakovlevdalet avatar tewfik-ghariani avatar thepeak99 avatar x0ddf avatar yariksheptykin avatar zidoshare avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

helm-unittest's Issues

gzip: invalid header

I get this error when testing:

helm unittest ./tests/deployment_test.yaml

### Error:  gzip: invalid header


Charts:      1 failed, 1 errored, 0 passed, 1 total
Test Suites: 0 passed, 0 total
Tests:       0 passed, 0 total
Snapshot:    0 passed, 0 total
Time:        188.52µs

Error: plugin "unittest" exited with error

cygpath not found / Unable to update checked out version

~/.helm/plugins/helm-unittest/install-binary.sh: line 14: type: cygpath: not found shows up during installation on macOS. Does not fail the installation tho.

I had to pass in --version 0.1.1 to get the install working, without it I got the following (i can open up a separate ticket):

helm plugin install https://github.com/lrills/helm-unittest
Error: Unable to update checked out version

Testing empty templates

Assuming I have the following helm template file:

{{- if .Values.something }}
<some Kubernetes manifest file>
 {{- end }}

I want to test that the object exists or not based on something. This is not possible today because the tests are failing with the following error:

        - not includes identity when identity is not set

                - asserts[0] `notEqual` fail

                        Error:
                                assertion.template must be given if testsuite.templates is empty

Templates in subdirectories fail to load

I have a helm chart that uses subdirectories to organize some different services (instead of subcharts):

templates
- web-service
-- deployment.yaml
- database
-- stateful-set.yaml

If I create a test suite similar to:

suite: test stuff
templates:
- web-service/web-deployment.yaml
tests:
...

I get an error:

$ helm unittest -f 'tests/*-test.yaml' .

### Chart [ test-chart ] .

 FAIL  TLS enabled mounts    tests/first-test.yaml
    - Execution Error:
        template file `templates/web-service/web-deployment.yaml` not found in chart

If I modify the test suite to reference the template at web-deployment with no subdir, then the test runs, but fails again while loading another file to create a checksum.

suite: test stuff
templates:
- web-deployment.yaml
tests:
...
$ helm unittest -f 'tests/*-test.yaml' .

### Chart [ test-chart ] .

 FAIL  TLS enabled mounts	tests/first-test.yaml
	- some test
		Error: render error in "immuta/templates/web/web-deployment.yaml": template: test-chart/templates/web/web-deployment.yaml:37:28: executing "test-chart/templates/web/web-deployment.yaml" at <include (print $.Tem...>: error calling include: template: no template "test-chart/templates/web/web-secret.yaml" associated with template "gotpl"

I'm willing to submit a PR, but I figured I'd file an issue before digging into the code base.

Support subchart

Seems helm-unittest doesn't support subchart.
I tried two methods to workaround this, still no good with issue.

1. Add tests directory to subchart and create test file there
The whole chart directory resemble:

mychart/
    Chart.yaml
    values.yaml
    templates/
        _helpers.tpl
        deployment.yaml
        service.yaml
    charts/
        mysubchart/
            Chart.yaml
            templates/
               deployment.yaml
               service.yaml
            tests/
               deployment_test.yaml
               service_test.yaml

And run unittest in subchart:

helm unittest mychart/charts/mysubchart

Error message I got:

### Chart [ mysubchart ] mysubchart

 FAIL  test deployment	mysubchart/tests/deployment_test.yaml
	- should work
		Error: render error in "mysubchart/templates/deployment.yaml": template: mysubchart/templates/deployment.yaml:12:40: executing "mysubchart/templates/deployment.yaml" at <{{template "mychart.co...>: template "mychart.configmap.checksum" not defined

Because I have embed named template in mysubchart/templates/deployment.yaml which defined in parent chart mychart/_helpers.tpl.


2. Add all subchart test file to tests directory of parent chart.
The whole chart directory resemble:

mychart/
    Chart.yaml
    values.yaml
    templates/
        _helpers.tpl
        deployment.yaml
        service.yaml
    tests/
       mysubchart_deployment_test.yaml
       mysubchart_service_test.yaml
    charts/
        mysubchart/
            Chart.yaml
            templates/
               deployment.yaml
               service.yaml               

In the test suite of mychart/tests/mysubchart_deployment_test.yaml, template refer the respective template file of mysubchart, like this:

suite: test mysubchart deployment
templates:
  - ../charts/mysubchart/template/deployment.yaml
tests:
...

And then run helm unittest in parentchart:

helm unittest mychart

Error message I got:

FAIL  test mysubchart deployment	mychart/tests/mysubchart_deployment_test.yaml
	- Execution Error:
		template file `templates/../charts/mysubchart/templates/deployment.yaml` not found in chart

 FAIL  test mysubchart service	mychart/tests/mysubchart_service_test.yaml
	- Execution Error:
		template file `templates/../charts/mysubchart/templates/service.yaml` not found in chart

Actually, the template file templates/../charts/mysubchart/templates/deployment.yaml and templates/../charts/mysubchart/templates/service.yaml do exist.


Expected behivour, create test files in method 1:

Directly run unittest in parent chart, it will include all unittest cases defined in subchart.

Helm v3 Compatibility

It seems this doesn't work with the latest v3-beta3 build failing with the following on install:

$ helm plugin install https://github.com/lrills/helm-unittest
Downloading https://github.com/lrills/helm-unittest/releases/download/v0.1.5/helm-unittest-macos-0.1.5.tgz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   620    0   620    0     0   2668      0 --:--:-- --:--:-- --:--:--  2660
100 3119k  100 3119k    0     0   466k      0  0:00:06  0:00:06 --:--:--  612k
Preparing to install into The Kubernetes package manager
...
Use "helm [command] --help" for more information about a command./plugins/helm-unittest: name too long
Failed to install helm-unittest
For support, go to https://github.com/kubernetes/helm
Error: plugin install hook for "unittest" exited with error

It does appear to be registered with Helm:

$ helm plugin list
NAME            VERSION DESCRIPTION                                                                         
unittest        0.1.5   Unit test for helm chart in YAML with ease to keep your chart functional and robust.

But any time you use it it fails:

$ helm unittest .
Error: fork/exec /Users/john.doe/Library/helm/plugins/helm-unittest/untt: no such file or directory

Environment

  • OS: Mac
  • Helm:
version.BuildInfo{Version:"v3.0.0-beta.3", GitCommit:"5cb923eecbe80d1ad76399aee234717c11931d9a", GitTreeState:"clean", GoVersion:"go1.12.9"}

Forking this project due to inactive maintainer

It seems the maintainer is inactive so I forked the repository to GitLab: https://gitlab.com/walkafwalka/helm-unittest. If the maintainer ever comes back within a reasonable time, I plan to merge my changes back to this one.

I have already fixed all of the current PRs in this project and have gone through the issues and fixed some of the easier ones. If you are still interested in seeing new features or fixing bugs, please post them over there so that I do not have to continue referencing the issues in this project.

The plan is to release 0.2 which is going to be focused on addressing a lot of the current bugs. I will then start releasing actual features in possibly 0.3 or the same release depending on how large the features are.

pre-publish TODO

  • CI
  • helm plugin
  • readme
  • medium article
  • examples
  • detailed cli description

Error rendering nginx-ingress chart

I am fairly new to helm and just discovered the unittest plugin, so sorry in advance if this is a stupid question.

I am trying to get the first test running but I am running in a render error in the nginx-ingress chart we have as a dependency for our own chart:

### Chart [ xxx ] .

 FAIL  engine deployment	tests/engine_test.yaml
	- should render values
		Error: render error in "xxx/charts/nginx-ingress/templates/controller-service.yaml": template: xxx/charts/nginx-ingress/templates/controller-service.yaml:31:49: executing "xxx/charts/nginx-ingress/templates/controller-service.yaml" at <.Capabilities.KubeVe...>: can't evaluate field GitVersion in type *version.Info


Charts:      1 failed, 0 passed, 1 total
Test Suites: 1 failed, 0 passed, 1 total
Tests:       1 failed, 1 errored, 0 passed, 1 total
Snapshot:    0 passed, 0 total
Time:        12.099274ms

Any idea how to resolve this?

requirements.yaml:

dependencies:
  - name: nginx-ingress
    repository: '@stable'
    version: 0.16.0

requirements.lock

dependencies:
- name: nginx-ingress
  repository: https://kubernetes-charts.storage.googleapis.com
  version: 0.16.0
digest: sha256:3a0fa8268f63e59f59afa66445521e249d12ae366aadcc89ac9acf066b3baa86
generated: 2018-05-15T14:28:53.336657485-07:00

Render error when template uses include of a template filename

unittest fails when the template includes a file to create a checksum as described here

 FAIL  test deployment	tests/deployment_test.yaml
	- should work
		Error: render error in "fsjetty/templates/deployment.yaml": template: fsjetty/templates/deployment.yaml:18:28: executing "fsjetty/templates/deployment.yaml" at <include "../template...>: error calling include: template: no template "../templates/configmap.yaml" associated with template "gotpl"

deployment_test.yaml:

suite: test deployment
templates:
  - deployment.yaml
tests:
...

where deployment.yaml has:

annotations:
  checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

Assertion types for flow-control sprig

Description

Make it possible to assert flow-controls (see sprig)

Motivation and Context

It's possible to let the template rendering fail if some conditions are not met: http://masterminds.github.io/sprig/flow_control.html: eg:

{{- fail "something is not ok" }}

Example

_ingress.yaml

...
spec:
  rules:
{{- if not .Values.ingress.hosts }}
{{- fail "please provide hosts in yaml format" }}
{{- else }}
...

ingress_test.yaml

...
  - it: no hosts provided gives error
    values:
      - ./ingress_test_values.yaml
    set:
      ingress:
        hosts: {}
    asserts:
      - fails:
        contains: "please provide hosts in yaml format"
...

error: template "xxx" not exists or not selected in test suite when running on Windows 10 with Gitbash

Running heml unittest . from __fixtures__/basic folder using Gitbash terminal does not work on Windows 10 due to Windows file separators being used to read templates from test suite manifest:

User@pc MINGW64 ~/git/helm-unittest/__fixtures__/basic (master): helm unittest .
....
 FAIL  test service     tests\service_test.yaml
        - should pass

                - asserts[0] `contains` fail

                        Error:
                                template "basic\templates\service.yaml" not exists or not selected in test suite

                - asserts[1] `equal` fail

                        Error:
                                template "basic\templates\service.yaml" not exists or not selected in test suite

                - asserts[2] `equal` fail

                        Error:
                                template "basic\templates\service.yaml" not exists or not selected in test suite

        - should render right if values given

                - asserts[0] `contains` fail

                        Error:
                                template "basic\templates\service.yaml" not exists or not selected in test suite

                - asserts[1] `equal` fail

                        Error:
                                template "basic\templates\service.yaml" not exists or not selected in test suite


Charts:      1 failed, 0 passed, 1 total
Test Suites: 3 failed, 0 passed, 3 total
Tests:       7 failed, 0 passed, 7 total
Snapshot:    0 passed, 0 total
Time:        119.1127ms

Error: plugin "unittest" exited with error

Helper render issue causes failure

Given the following _helper.tpl:

{{- define "ingressClass" -}}
  {{- $ingressClass := .Values.ingress.class -}}
  {{- if .Values.global -}}
    {{- if .Values.global.ingressClass -}}
      {{- $ingressClass = .Values.global.ingressClass -}}
    {{- end -}}
  {{- end -}}
  {{- printf "%s" $ingressClass -}}
{{- end -}}

I actually ran into this issue with helm 2.11 and it was fixed somewhere in 2.12 but not explicitly. My guess is this: helm/helm#5300

In any case, here's what that looks like inside ingress.yaml:

kubernetes.io/ingress.class: {{ template "ingressClass" . }}

And here's the failure on helm unittest $CHARTNAME:

### Chart [ mychart ] ./charts/mychart

 FAIL  test ingress     charts/mychart/tests/ingress_test.yaml
        - should set ingress class to nginx by default
                Error: parse error in "mychart/templates/_helper.tpl": template: collections/templates/_helper.tpl:49: unexpected "=" in operand


Charts:      1 failed, 0 passed, 1 total
Test Suites: 1 failed, 0 passed, 1 total
Tests:       1 failed, 1 errored, 0 passed, 1 total
Snapshot:    0 passed, 0 total
Time:        26.892096ms

Error: plugin "unittest" exited with error

The implication is there's a scope issue where the = inside the nested if doesn't have access to the variable defined in the second line of the helper above. It's imperative that the = work without it being changed to := because that would actually assign a new variable, that wouldn't be available outside the if, and thus couldn't be printed on the second to last line.

tl;dr; I'm wondering if upgrading sprig might fix this, but otherwise there's something else at play and helm fixed it (though perhaps unintentionally, haha).

Alpine linux untt: no such file or directory

bash-4.3# ls -al /root/.helm/plugins/helm-unittest/untt
-rwxr-xr-x    1 root     root       8995465 Jun  5 17:37 /root/.helm/plugins/helm-unittest/untt
bash-4.3# helm unittest -h
Error: fork/exec /root/.helm/plugins/helm-unittest/untt: no such file or directory

untt is built with dynamic linking against gnu libc which is missing on some linux distros, e.g. alpine.

Multiple templates within test suite

I struggle to see the point of multiple templates per test suite. I figured I can use this to test commonalities between the resources, e.g. same labels. But that doesn't work as I have to use the documentIndex.

suite: General Helm Tests
templates:
  - clusterrolebinding.yaml
  - deployment.yaml
tests:
  - it: should have default labels
    asserts:
      - isNotNull:
          path: metadata.labels.app
      - isNotNull:
          path: metadata.labels.chart
      - isNotNull:
          path: metadata.labels.release
      - isNotNull:
          path: metadata.labels.heritage

Is there a way to do this without repeating this all over again?

Mac install error

I'm seeing this issue with installing the plugin on Mac OS

$ helm plugin install https://github.com/lrills/helm-unittest
Downloading https://github.com/lrills/helm-unittest/releases/download/v0.1.2/helm-unittest-macos-0.1.2.tgz
curl: (3) [globbing] bad range in column 82
Failed to install helm-unittest
\tFor support, go to https://github.com/kubernetes/helm.
Error: plugin install hook for "unittest" exited with error

If I run it again:

$ helm plugin install https://github.com/lrills/helm-unittest
Error: plugin already exists

Debug info:

$ helm version 
Client: &version.Version{SemVer:"v2.6.2", GitCommit:"be3ae4ea91b2960be98c07e8f73754e67e87963c", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.6.2", GitCommit:"be3ae4ea91b2960be98c07e8f73754e67e87963c", GitTreeState:"clean"}
$ uname -a
Darwin c4b301cac433 16.7.0 Darwin Kernel Version 16.7.0: Tue Jan 30 11:27:06 PST 2018; root:xnu-3789.73.11~1/RELEASE_X86_64 x86_64

Failed Install

Trying to install it in an Alpine container, hitting

[debug] cloning https://github.com/lrills/helm-unittest to /root/.helm/cache/plugins/https-github.com-lrills-helm-unittest
[debug] setting version to ""
[debug] symlinking /root/.helm/cache/plugins/https-github.com-lrills-helm-unittest to /root/.helm/plugins/helm-unittest
[debug] loading plugin from /root/.helm/plugins/helm-unittest
[debug] running install hook: &{/bin/sh [sh -c $HELM_PLUGIN_DIR/install-binary.sh] []  <nil> <nil> <nil> [] %!s(*syscall.SysProcAttr=<nil>) %!s(*os.Process=<nil>) <nil> <nil> <nil> %!s(bool=false) [] [] [] [] %!s(chan error=<nil>) %!s(chan struct {}=<nil>)}
Downloading
curl: (3) <url> malformed
Failed to install helm-unittest
\tFor support, go to https://github.com/kubernetes/helm.

Container does have curl, trying to find a way to do a set -x before the helm plugin install but it's not working as expected.

Installation issue: it says unittest not found but it actually exist.

Getting error in container using alpine image.

Preparing to install into /root/.helm/plugins/helm-unittest
helm-unittest installed into /root/.helm/plugins/helm-unittest/helm-unittest
/root/.helm/plugins/helm-unittest/install-binary.sh: line 122: /root/.helm/plugins/helm-unittest/untt: No such file or directory
Installed plugin: unittest

I can see the plugin installed but cannot run it. Getting this error:

/home/jenkins/.helm/plugins/helm-unittest/install-binary.sh: line 122: /home/jenkins/.helm/plugins/helm-unittest/untt: No such file or directory

Add ability to test dependent charts defined in requirements.yaml

Hello,

Is it possible to define a test file that supports checking the resolved values that would apply to charts pulled into helm through 'helm dependency update' prior to running unittests?

Suppose I have a chart called my-app-implementation that has a requirements.yaml file that includes a base chart my-app. The base chart for my-app would include its values.yaml file as normal and suppose it sets a values.yml stanza as

deployment:
  resources:
    limits:
      cpu: 100m

which leads that chart to set the proper cpu limit for a Deployment object. When the my-app-implementation chart runs suppose I set its value.yaml file to the following to override that dependent chart's value:

my-app:
  deployment:
    resources: {}

which would lead Helm to override the cpu limit stanza that would have been applied to the nested chart my-app

The issue I am seeing is that since the nested chart only exists as a tarball under the charts/ directory of my-app-implementation my test file within the implementation chart is unable to find the deployments.yaml file as it only exists within the my-app chart under that charts 'templates/` directory

Is it possible to use unittest to assert that a cpu limit must exist in the resulting deployment object for this nested my-app chart by defining something only in a test file within the my-app-implementation chart?

Plugin install error

When run install command

$ helm plugin install https://github.com/lrills/helm-unittest
Error: Unable to update checked out version

and when run this:

$ helm plugin install https://github.com/lrills/helm-unittest --version v0.1.0
/home/-----/.helm/plugins/helm-unittest/install-binary.sh: line 14: type: cygpath: not found
Downloading https://github.com/lrills/helm-unittest/releases/download/v0.1.0/helm-unittest-linux-0.1.0.tgz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   620    0   620    0     0    746      0 --:--:-- --:--:-- --:--:--   746
100 2893k  100 2893k    0     0   750k      0  0:00:03  0:00:03 --:--:-- 1359k
Preparing to install into /home/-----/.helm/plugins/helm-unittest
cp: cannot stat '/tmp/helm-unittest/tpl*': No such file or directory
Failed to install helm-unittest
\tFor support, go to https://github.com/kubernetes/helm.
Error: plugin install hook for "unittest" exited with error

OS and helm versions:

$ lsb_release -a
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.4 LTS
Release:	16.04
Codename:	xenial

$ helm version
Client: &version.Version{SemVer:"v2.8.2", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.8.2", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}

matchSnapshot should allow to test entire file snapshot instead of just the first document

In my scenario, I have multiple documents being declared in the same file.

So my file goes...

my-project.yaml

--- deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
...
--- service
apiVersion: v1
kind: Service
metadata:
...
--- configMap
apiVersion: v1
kind: ConfigMap
metadata:
...

But when I try to test snapshot of this file with matchSnapshot, I always get the deployment object but not the service and configMap objects snapshot. So I can never test snapshots of the service and configMaps.

I know the best practice and workaround to this is to separate the documents into different files but before I go with that approach, is there any way we can add that feature to this plugin easily? I am new to go and I don't have a faintest idea on how to write a new plugin so when I looked at the code, I couldn't understand.

Unable to parse documents with separator in structured annotations

I'm trying to write unit tests for some templates which use ambassador, and I'm getting parsing issues (Error: yaml: line 7: did not find expected <document start>) with a service definition that looks similar to example from here https://www.getambassador.io/user-guide/getting-started#3-creating-your-first-route:

---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  httpbin_mapping
      prefix: /httpbin/
      service: httpbin.org:80
      host_rewrite: httpbin.org
spec:
  ports:
  - name: httpbin
    port: 80

It seems that it's specifically the separator --- in the annotation that is causing parsing issues.

Assertion type `isApiVersion` is invalid, which should be `isAPIVersion `

Have gone through the doc and ind assertion type isApiVersion in:
https://github.com/lrills/helm-unittest/blob/master/DOCUMENT.md#assertion-types

When run helm unittest, got the error:

 FAIL  	mychart/tests/service_test.yaml
	- Execution Error:
		Assertion type `isApiVersion` is invalid

Actually it should be isAPIVersion , find it in test file example:
https://raw.githubusercontent.com/lrills/helm-unittest/master/__fixtures__/basic/tests_failed/deployment_test.yaml

So this is a doc issue.

TAPs or XUNIT output

Would be very nice if I could injest the test output into my CI server (Jenkins) to run build/test reports on.

matchRegex when value is generated in go-template

Hi,
I'm facing sth:
Let's say I've a chart for a secret and somewhere is

stringData:
  database-admin-password: {{ randAlphaNum 16 }}

Regardless what I put into a matchRegex assertion test, it's always true, e.g.

    asserts:
      - matchRegex:
          path: stringData.database-admin-password
          value: ^-blubb$

or

    asserts:
      - matchRegex:
          path: stringData.database-admin-password
          value: ^[a-zA-Z0-9_]{16}

If I e.g. change that to an equal assertion, like

    asserts:
      - equal:
          path: stringData.database-admin-password
          value: blubb

I get

		- asserts[0] `equal` fail

			Path:	stringData.database-admin-password
			Expected:
				blubb
			Actual:
				2L6FR6fz2V7c5Pvs
			Diff:
				--- Expected
				+++ Actual
				@@ -1,2 +1,2 @@
				-blubb
				+2L6FR6fz2V7c5Pvs

Does the matchRegex assertion somehow has a problem with the gotpl randAlphaNum?

Thanks
Markus

debug/verbose output

I'm getting the following result:

FAIL  test deployment	ratpack/tests/deployment_test.yaml
	- should work
		Error: yaml: line 84: found character that cannot start any token

But there is no indication which file has a problem and if that is before or after parsing/merging/templating them. It would be great to have more verbose output as an option to help locate these problems.

Support for multiple resources in a single file

Kubernetes and Helm support multiple kubernetes resources in a single file. It seems that when testing such a file, only the first resource can be processed. Is there a syntax that allows to access additional resources, or does the use of this plugin require structuring helm templates with only one resource per file?

Feature enhancement: containsOnce

I just ran into a test condition where I was using contains to test that my config was present because I didn't care about the rest of the config. Now I'm wishing there was a "containsOnce" because my array had two copies of the configuration I needed, which resulted in an invalid chart.

Expected outcome:

asserts:
  - contains: 
      content: a

on

[ a, a, b, c ]

returns true

but

asserts:
  - containsOnce: 
      content: a

on

[ a, a, b, c ]

returns false

Ability for "fail" assertions

In JUnit and other testing languages, you can create tests that EXPECT/validate failure conditions. I am writing TPL code for my Helm charts, and if user does not provide required parameters, I am calling TPL "fail" method to cause a chart rendering error, thus preventing (accidental/partial) deployment. I.e.

{{- cat "ERROR: Required parameter (" $param ") is not defined" | **fail** -}}

I want to create a test that validates if parameter is not defined, then render error should be expected, and if template somehow SUCCEEDS, then this is an error, which should fail the test. So I guess I am looking for something like:

  • it: if PVC is not defined, it should fail
    asserts:
    • shouldFail:

The same would be true for the built-in "required" (which calls "fail" under the hood) method, i.e.:

someParam: {{ required "Please define X" .Values.X }}

this generates a render error, and I would like to have a test "if notDefined(X) then expectError".

Reuse Assertions across different tests

It would be nice if we could re use the same assertions that are common across different test cases (it). Assume there are 10 assertions a1 to a10 for it1. For it2 there is the same assertions a1 to a10 plus a11. Today, we need to repeat a1 to a10 twice.

untt not found when install this plugin in Docker

Hi,

I'm using Helm in Docker to install this plugin.
It works fine when I install on my Ubuntu 16.04. However, when I tried to install in Docker, I got this error:

$helm unittest
Error: fork/exec /root/.helm/plugins/helm-unittest/untt: no such file or directory

This is strange, because that path is already exist (it's a symlink)

[~/.helm/plugins] $ls -al
helm-unittest -> /root/.helm/cache/plugins/https-github.com-lrills-helm-unittest

My Dockerfile:

FROM alpine:3.7

ENV HELM_VERSION=v2.8.2
ENV HELM_FILENAME=helm-${HELM_VERSION}-linux-amd64.tar.gz

RUN apk add --update ca-certificates \
 && apk add --update -t deps curl  \
 && apk add --update gettext tar gzip git bash \
 && curl -L https://storage.googleapis.com/kubernetes-helm/${HELM_FILENAME} | tar xz && mv linux-amd64/helm /bin/helm && rm -rf linux-amd64 \
 && helm init --client-only \
 && helm plugin install https://github.com/lrills/helm-unittest \
 && apk del --purge deps \
 && rm /var/cache/apk/*

Please help me out.

More assertion types

isSubset

isSubset:
  path: metadata.label
  subset:
    a: b

isNotSubset

isNotSubset:
  path: metadata.label
  subset:
    a: b

evaluate

evaluate:
  expression: len(get("spec.template.spec.initContainers")) >= 2

check https://github.com/Knetic/govaluate for implementation detail

Even the negative test cases are getting passed with warning

Hi Team,

There is an unusual scenario where If I am givign any negative test case, it should fail right?
However it is getting passed with a warning. "Warning: Building values map for chart 'uma'. Skipped value (map[]) for 'image', as it is not a table."

Could you please let me know what mistake I am making.

Below is the snippet.

helm unittest uma

Chart [ uma ] uma

2019/08/29 04:36:05 Warning: Building values map for chart 'uma'. Skipped value (map[]) for 'image', as it is not a table.
PASS test deployment of prometheus uma/tests/deployment_prometheus_test.yaml
2019/08/29 04:36:05 Warning: Building values map for chart 'uma'. Skipped value (map[]) for 'image', as it is not a table.
PASS test deploy,ent uma/tests/deployment_apmia_test.yaml

Charts: 1 passed, 1 total
Test Suites: 2 passed, 2 total
Tests: 4 passed, 4 total
Snapshot: 0 passed, 0 total
Time: 10.129211ms

Feature Enhancement: [notC|c]ontainsAny

Useful for where you need to verify an entry with a particular value does/doesn't exist but not concerned about the other values. E.g.

Input

...
      env:
        - name: MY_PARAM
          value: foo  # don't care about this value

Test

asserts:
  - containsAny:
        path: spec.template.spec.containers[0].env
        content:
          name: MY_PARAM

This is probably more useful for testing the negative when you want to ensure something doesn't exist via notContainsAny when switching on a value. The only way at the moment is verifying the whole structure which can get very verbose and cumbersome to maintain to just check something shouldn't exist.

Install failed when enable debug option

Install helm-unittest v0.1.1 always failed if add --debug option:

[root@mstnode ~]# helm plugin install https://github.com/lrills/helm-unittest --debug --version v0.1.1
[debug] cloning https://github.com/lrills/helm-unittest to /var/lib/helm/cache/plugins/https-github.com-lrills-helm-unittest
[debug] setting version to "v0.1.1"
[debug] symlinking /var/lib/helm/cache/plugins/https-github.com-lrills-helm-unittest to /var/lib/helm/plugins/helm-unittest
[debug] loading plugin from /var/lib/helm/plugins/helm-unittest
[debug] running install hook: &{/usr/bin/sh [sh -c $HELM_PLUGIN_DIR/install-binary.sh] []  <nil> <nil> <nil> [] %!s(*syscall.SysProcAttr=<nil>) %!s(*os.Process=<nil>) <nil> <nil> <nil> %!s(bool=false) [] [] [] [] %!s(chan error=<nil>) %!s(chan struct {}=<nil>)}
/var/lib/helm/plugins/helm-unittest/install-binary.sh: line 14: type: cygpath: not found
Downloading https://github.com/lrills/helm-unittest/releases/download/v0.1.1/helm-unittest-linux-0.1.1.tgz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   620    0   620    0     0    338      0 --:--:--  0:00:01 --:--:--   338
100 2893k  100 2893k    0     0   313k      0  0:00:09  0:00:09 --:--:--  583k
Preparing to install into /var/lib/helm
Repository: /var/lib/helm/repository
RepositoryFile: /var/lib/helm/repository/repositories.yaml
Cache: /var/lib/helm/repository/cache
Stable CacheIndex: /var/lib/helm/repository/cache/stable-index.yaml
Starters: /var/lib/helm/starters
LocalRepository: /var/lib/helm/repository/local
Plugins: /var/lib/helm/plugins/plugins/helm-unittest
cp: cannot create regular file ‘/var/lib/helm\nRepository: /var/lib/helm/repository\nRepositoryFile: /var/lib/helm/repository/repositories.yaml\nCache: /var/lib/helm/repository/cache\nStable CacheIndex: /var/lib/helm/repository/cache/stable-index.yaml\nStarters: /var/lib/helm/starters\nLocalRepository: /var/lib/helm/repository/local\nPlugins: /var/lib/helm/plugins/plugins/helm-unittest’: No such file or directory
Failed to install helm-unittest
\tFor support, go to https://github.com/kubernetes/helm.
Error: plugin install hook for "unittest" exited with error
[root@mstnode ~]# ls -l /var/lib/helm/plugins/plugins/helm-unittest
ls: cannot access /var/lib/helm/plugins/plugins/helm-unittest: No such file or directory

However, it will be all right when install without --debug option:

[root@mstnode ~]# helm plugin install https://github.com/lrills/helm-unittest --version v0.1.1
/var/lib/helm/plugins/helm-unittest/install-binary.sh: line 14: type: cygpath: not found
Downloading https://github.com/lrills/helm-unittest/releases/download/v0.1.1/helm-unittest-linux-0.1.1.tgz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   620    0   620    0     0    338      0 --:--:--  0:00:01 --:--:--   338
100 2893k  100 2893k    0     0   385k      0  0:00:07  0:00:07 --:--:--  724k
Preparing to install into /var/lib/helm/plugins/helm-unittest
helm-unittest installed into /var/lib/helm/plugins/helm-unittest/helm-unittest
...
Installed plugin: unittest

Another issue, does the error message have impact on the plugin? Seems no impact.

/var/lib/helm/plugins/helm-unittest/install-binary.sh: line 14: type: cygpath: not found

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.