Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/failed template assertion #181

Merged
merged 3 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
0.2.10 / 2022-11-05
==================
- isSubset assertion to handle multiple keys (credits to: @iben12, resolves #162)
- Out Of Bounds array will result in a null value (resolves #167, #174)
- Additional debug option to validate failed tests with same expected and actual results (resolves #180)
- Update documentation based on user questions
- Update packages to latest version

0.2.9 / 2022-09-24
==================
- Add JSON Schema for validating testsuite files (credits to: @armingerten, resolves #161)
Expand Down
29 changes: 15 additions & 14 deletions DOCUMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,28 +163,29 @@ Available assertion types are listed below:

| Assertion Type | Parameters | Description | Example |
|----------------|------------|-------------|---------|
| `containsDocument` | **kind**: *string*. Expected `kind` of manifest.<br/> **apiVersion**: *string*. Expected `apiVersion` of manifest.<br/>**name**: *string, optional*. The value of the `metadata.name`.<br/>**namespace**: *string, optional*. The value of the `metadata.namespace`. | Asserts the documents rendered by the `kind` and `apiVersion` specified. | <pre>containsDocument:<br/> kind: Deployment<br/> apiVersion: apps/v1<br/> name:foo<br/> namespace: bar</pre> |
| `contains` | **path**: *string*. The `set` path to assert, the value must be an *array*. <br/>**content**: *any*. The content to be contained.<br/>**count**: *int, optional*. The count of content to be contained.<br/>**any**: *bool, optional*. ignores any other values within the found content. | Assert the array as the value of specified **path** contains the **content**. |<pre>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> port: 80<br/> targetPort: 80<br/> protocle:TCP<br/><br/>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> count: 1<br/> any: true<br/></pre> |
| `notContains` | **path**: *string*. The `set` path to assert, the value must be an *array*. <br/>**content**: *any*. The content NOT to be contained. | Assert the array as the value of specified **path** NOT contains the **content**. |<pre>notContains:<br/> path: spec.ports<br/> content:<br/> name: server<br/> port: 80<br/> targetPort: 80<br/> protocle: TCP<br/><br/>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> count: 1<br/> any: true<br/></pre> |
| `equal` | **path**: *string*. The `set` path to assert.<br/>**value**: *any*. The expected value. | Assert the value of specified **path** equal to the **value**. | <pre>equal:<br/> path: metadata.name<br/> value: my-deploy</pre> |
| `equalRaw` | <br/>**value**: *string*. Assert the expected value in a NOTES.txt file. | Assert equal to the **value**. | <pre>equalRaw:<br/> value: my-deploy</pre> |
| `notEqual` | **path**: *string*. The `set` path to assert.<br/>**value**: *any*. The value expected not to be. | Assert the value of specified **path** NOT equal to the **value**. | <pre>notEqual:<br/> path: metadata.name<br/> value: my-deploy</pre> |
| `equalRaw` | <br/>**value**: *string*. Assert the expected value in a NOTES.txt file. | Assert equal to the **value**. | <pre>equalRaw:<br/> value: my-deploy</pre> |
| `notEqualRaw` | <br/>**value**: *string*. Assert the expected value in a NOTES.txt file not to be. | Assert equal NOT to the **value**. | <pre>notEqual:<br/> value: my-deploy</pre> |
| `matchRegex` | **path**: *string*. The `set` path to assert, the value must be a *string*. <br/>**pattern**: *string*. The regex pattern to match (without quoting `/`). | Assert the value of specified **path** match **pattern**. | <pre>matchRegex:<br/> path: metadata.name<br/> pattern: -my-chart$</pre> |
| `matchRegexRaw` | **pattern**: *string*. The regex pattern to match (without quoting `/`) in a NOTES.txt file. | Assert the value match **pattern**. | <pre>matchRegexRaw:<br/> pattern: -my-notes$</pre> |
| `notMatchRegex` | **path**: *string*. The `set` path to assert, the value must be a *string*. <br/>**pattern**: *string*. The regex pattern NOT to match (without quoting `/`). | Assert the value of specified **path** NOT match **pattern**. | <pre>notMatchRegex:<br/> path: metadata.name<br/> pattern: -my-chat$</pre> |
| `notMatchRegexRaw` | **pattern**: *string*. The regex pattern NOT to match (without quoting `/`) in a NOTES.txt file. | Assert the value NOT match **pattern**. | <pre>notMatchRegexRaw:<br/> pattern: -my-notes$</pre> |
| `contains` | **path**: *string*. The `set` path to assert, the value must be an *array*. <br/>**content**: *any*. The content to be contained.<br/>**count**: *int, optional*. The count of content to be contained.<br/>**any**: *bool, optional*. ignores any other values within the found content. | Assert the array as the value of specified **path** contains the **content**. |<pre>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> port: 80<br/> targetPort: 80<br/> protocle:TCP<br/><br/>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> count: 1<br/> any: true<br/></pre> |
| `notContains` | **path**: *string*. The `set` path to assert, the value must be an *array*. <br/>**content**: *any*. The content NOT to be contained. | Assert the array as the value of specified **path** NOT contains the **content**. |<pre>notContains:<br/> path: spec.ports<br/> content:<br/> name: server<br/> port: 80<br/> targetPort: 80<br/> protocle: TCP<br/><br/>contains:<br/> path: spec.ports<br/> content:<br/> name: web<br/> count: 1<br/> any: true<br/></pre> |
| `isNull` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is `null`. |<pre>isNull:<br/> path: spec.strategy</pre> |
| `isNotNull` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is NOT `null`. |<pre>isNotNull:<br/> path: spec.replicas</pre> |
| `failedTemplate` | **errorMessage**: *string*. The (human readable) `errorMessage` that should occur. | Assert the value of **errorMessage** is the same as the human readable template rendering error. Also allows to match an error that would happen before template execution (ex: validation of values against schema) | <pre>failedTemplate:<br/> errorMessage: Required value<br/></pre> |
| `hasDocuments` | **count**: *int*. Expected count of documents rendered. | Assert the documents count rendered by the `template` specified. The `documentIndex` option is ignored here. | <pre>hasDocuments:<br/> count: 2</pre> |
| `isAPIVersion` | **of**: *string*. Expected `apiVersion` of manifest. | Assert the `apiVersion` value **of** manifest, is equilevant to:<br/><pre>equal:<br/> path: apiVersion<br/> value: ...<br/> | <pre>isAPIVersion:<br/> of: v2</pre> |
| `isEmpty` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is empty (`null`, `""`, `0`, `[]`, `{}`). |<pre>isEmpty:<br/> path: spec.tls</pre> |
| `isNotEmpty` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is NOT empty (`null`, `""`, `0`, `[]`, `{}`). |<pre>isNotEmpty:<br/> path: spec.selector</pre> |
| `isKind` | **of**: *String*. Expected `kind` of manifest. | Assert the `kind` value **of** manifest, is equilevant to:<br/><pre>equal:<br/> path: kind<br/> value: ...<br/> | <pre>isKind:<br/> of: Deployment</pre> |
| `isAPIVersion` | **of**: *string*. Expected `apiVersion` of manifest. | Assert the `apiVersion` value **of** manifest, is equilevant to:<br/><pre>equal:<br/> path: apiVersion<br/> value: ...<br/> | <pre>isAPIVersion:<br/> of: v2</pre> |
| `hasDocuments` | **count**: *int*. Expected count of documents rendered. | Assert the documents count rendered by the `template` specified. The `documentIndex` option is ignored here. | <pre>hasDocuments:<br/> count: 2</pre> |
| `containsDocument` | **kind**: *string*. Expected `kind` of manifest.<br/> **apiVersion**: *string*. Expected `apiVersion` of manifest.<br/>**name**: *string, optional*. The value of the `metadata.name`.<br/>**namespace**: *string, optional*. The value of the `metadata.namespace`. | Asserts the documents rendered by the `kind` and `apiVersion` specified. | <pre>containsDocument:<br/> kind: Deployment<br/> apiVersion: apps/v1<br/> name:foo<br/> namespace: bar</pre> |
| `isNull` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is `null`. |<pre>isNull:<br/> path: spec.strategy</pre> |
| `isNotNull` | **path**: *string*. The `set` path to assert. | Assert the value of specified **path** is NOT `null`. |<pre>isNotNull:<br/> path: spec.replicas</pre> |
| `isSubset` | **path**: *string*. The `set` path to assert, the value must be an *object*. <br/>**content**: *any*. The content to be contained. | Assert the object as the value of specified **path** that contains the **content**. |<pre>isSubset:<br/> path: spec.template<br/> content:<br/> metadata: <br/> labels: <br/> app: basic<br/> release: MY-RELEASE<br/></pre> |
| `isNotSubset` | **path**: *string*. The `set` path to assert, the value must be an *object*. <br/>**content**: *any*. The content to be contained. | Assert the object as the value of specified **path** that NOT contains the **content**. |<pre>isSubset:<br/> path: spec.template<br/> content:<br/> metadata: <br/> labels: <br/> app: basic<br/> release: MY-RELEASE<br/></pre> |
| `matchRegex` | **path**: *string*. The `set` path to assert, the value must be a *string*. <br/>**pattern**: *string*. The regex pattern to match (without quoting `/`). | Assert the value of specified **path** match **pattern**. | <pre>matchRegex:<br/> path: metadata.name<br/> pattern: -my-chart$</pre> |
| `notMatchRegex` | **path**: *string*. The `set` path to assert, the value must be a *string*. <br/>**pattern**: *string*. The regex pattern NOT to match (without quoting `/`). | Assert the value of specified **path** NOT match **pattern**. | <pre>notMatchRegex:<br/> path: metadata.name<br/> pattern: -my-chat$</pre> |
| `matchRegexRaw` | **pattern**: *string*. The regex pattern to match (without quoting `/`) in a NOTES.txt file. | Assert the value match **pattern**. | <pre>matchRegexRaw:<br/> pattern: -my-notes$</pre> |
| `notMatchRegexRaw` | **pattern**: *string*. The regex pattern NOT to match (without quoting `/`) in a NOTES.txt file. | Assert the value NOT match **pattern**. | <pre>notMatchRegexRaw:<br/> pattern: -my-notes$</pre> |
| `matchSnapshot` | **path**: *string*. The `set` path for snapshot. | Assert the value of **path** is the same as snapshotted last time. Check [doc](./README.md#snapshot-testing) below. | <pre>matchSnapshot:<br/> path: spec</pre> |
| `matchSnapshotRaw` | | Assert the value in the NOTES.txt is the same as snapshotted last time. Check [doc](./README.md#snapshot-testing) below. | <pre>matchSnapshotRaw: {}<br/></pre> |
| `failedTemplate` | **errorMessage**: *string*. The (human readable) `errorMessage` that should occur. | Assert the value of **errorMessage** is the same as the human readable template rendering error. Also allows to match an error that would happen before template execution (ex: validation of values against schema) | <pre>failedTemplate:<br/> errorMessage: Required value<br/></pre> |


### Antonym and `not`

Expand Down
7 changes: 7 additions & 0 deletions FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ $ helm plugin uninstall helm-unittest
```
After the plugin removal, make sure the plugin cache is also cleaned (or at least the folder which contains the unittest plugin). See https://helm.sh/docs/faq/#xdg-base-directory-support for more information to identify the cache location for Helm 2 and Helm 3.

## Debugging
Q: **My test is failing but the expected and actual results are the same, what is happening?** <br/>
A: The error output is formatted for better readabillity. The result of the formatting is that it removes spaces and line endings, which can result in the same values between the expected and actual results.
With the debug option it is possible to see the the expected and actual content before the formatting is done.
```
$ helm helm-unittest ... -d
```
17 changes: 17 additions & 0 deletions cmd/helm-unittest/helm_unittest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"path/filepath"

log "github.com/sirupsen/logrus"

"github.com/lrills/helm-unittest/internal/printer"
"github.com/lrills/helm-unittest/pkg/unittest"
"github.com/lrills/helm-unittest/pkg/unittest/formatter"
Expand All @@ -13,6 +15,7 @@ import (

// testOptions stores options setup by user in command line
type testOptions struct {
debugLogging bool
useHelmV3 bool
useFailfast bool
useStrict bool
Expand Down Expand Up @@ -83,6 +86,15 @@ details about how to write tests.
}
var passed bool

log.SetFormatter(&log.TextFormatter{
DisableColors: !testConfig.colored,
FullTimestamp: true,
})

if testConfig.debugLogging {
log.SetLevel(log.DebugLevel)
}

if !testConfig.useHelmV3 {
passed = runner.RunV2(chartPaths)
} else {
Expand Down Expand Up @@ -154,4 +166,9 @@ func init() {
&testConfig.useFailfast, "failfast", "q", false,
"direct quit testing, when a test is failed",
)

cmd.PersistentFlags().BoolVarP(
&testConfig.debugLogging, "debug", "d", false,
"enable debug logging",
)
}
Loading