You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: subcommands/test.md
+92-19Lines changed: 92 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,7 +73,35 @@ This is a single test named "kitchen_sink" which defines an input matrix that ge
73
73
74
74
If not otherwise specified, a test is considered successful so long as the entrypoint runs to completion, exits without an error, and all outputs are evaluated successfully. For tasks, the test framework assumes the expected exit code is `0`.
75
75
76
-
Fail conditions can be tested by specifying an `assertions:` section for the YAML definition. The assertions available depend on whether the entrypoint is a task or a workflow. At the time of writing, the only assertion available for workflows is `should_fail: <boolean>`. This defaults to `false`, but may be specified as `should_fail: true`, which will invert expectations. The `should_fail` assertion is ignored for task executions. To unit test a fail case for a task entrypoint, a non-zero `exit_code: <integer>` should be specified.
76
+
### Assertions
77
+
78
+
Assertions are available for ensuring more complex expectations than simple "success" remain true. These more complex conditions can be specified with an `assertions:` section for the YAML definition.
79
+
80
+
The assertions available depend on whether the entrypoint is a workflow or a task.
81
+
82
+
For workflows, there is a `should_fail: <boolean>` assertion. This defaults to `false`, but may be specified as `should_fail: true`. The `should_fail` assertion is ignored for task executions.
83
+
84
+
```yaml
85
+
validate_flag_filter: # this is a workflow
86
+
- name: valid_FlagFilter
87
+
inputs:
88
+
flags:
89
+
- include_if_all: "3"
90
+
exclude_if_any: "0xF04"
91
+
include_if_any: "03"
92
+
exclude_if_all: "4095"
93
+
- name: invalid_FlagFilter
94
+
inputs:
95
+
flags:
96
+
- include_if_all: "3"
97
+
exclude_if_any: "0xF04"
98
+
include_if_any: "03"
99
+
exclude_if_all: "whoops! I'll trigger a fail :("
100
+
assertions:
101
+
should_fail: true
102
+
```
103
+
104
+
To unit test a fail case for a task, a non-zero `exit_code: <integer>` can be specified.
77
105
78
106
```yaml
79
107
validate_string_is_12bit_int: # this is a task
@@ -96,28 +124,11 @@ validate_string_is_12bit_int: # this is a task
96
124
- "+1"
97
125
assertions:
98
126
exit_code: 42
99
-
validate_flag_filter: # this is a workflow
100
-
- name: valid_FlagFilter
101
-
inputs:
102
-
flags:
103
-
- include_if_all: "3"
104
-
exclude_if_any: "0xF04"
105
-
include_if_any: "03"
106
-
exclude_if_all: "4095"
107
-
- name: invalid_FlagFilter
108
-
inputs:
109
-
flags:
110
-
- include_if_all: "3"
111
-
exclude_if_any: "0xF04"
112
-
include_if_any: "03"
113
-
exclude_if_all: "whoops! I'll trigger a fail :("
114
-
assertions:
115
-
should_fail: true
116
127
```
117
128
118
129
Assertions are shared by all executions of a test. In the example above, there are 4 executions defined for the `validate_string_is_12bit_int::valid_numbers` test. This test is considered passed if all 4 of those executions evaluate with an exit code of `0`. The `invalid_numbers` test contains 7 executions, and every one of those executions must exit with a code of `42` for the test to be considered a success.
119
130
120
-
At the time of writing, the only other assertions available for tasks are the `stdout` and `stderr` assertions. Both of these work very similarly; they expect a YAML sequence of strings that are interpreted as [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) which should match on the task's STDOUT/STDERR stream. For example:
131
+
Other assertions available for tasks are the `stdout` and `stderr` assertions. Both of these work very similarly; they expect a YAML sequence of strings that are interpreted as [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) which should match on the task's STDOUT/STDERR stream. For example:
It is often important to test for specific properties of the outputs for a WDL task or workflow. This is possible via the `outputs` section of the `assertions` YAML block. Just like other assertions, output assertions are expected to pass for every execution of a test.
151
+
152
+
```yaml
153
+
read_group_to_string:
154
+
- name: valid_read_groups
155
+
inputs:
156
+
read_group:
157
+
- ID: R1
158
+
SM: sampleFoo
159
+
- ID: R1
160
+
SM: sampleFoo
161
+
LB: spaces are allowed in LB
162
+
BC: barcode with a space
163
+
assertions:
164
+
outputs:
165
+
validated_read_group: # this output is of type `String`
166
+
- Contains: R1
167
+
- Contains: sampleFoo
168
+
```
169
+
170
+
Each key under `outputs` should be an exact match to an output of the task or workflow. The assertions available for that output are going to depend on the WDL type of the output. It wouldn't make sense to assert whether a WDL `Float` "contains" a string, so Sprocket will emit an informative error if there are any type mismatches between the assertions used and the expected type of each output.
171
+
172
+
The currently supported basic output assertions are:
173
+
174
+
- `Defined: <boolean>`: is the output defined (i.e. any value other than `None`)?
175
+
- available for all optional WDL types
176
+
- `BoolEquals: <boolean>`: is the output `Boolean` equal to this value?
177
+
- `StrEquals: <string>`: is the output `String` equal to this value?
178
+
- `IntEquals: <integer>`: is the output `Int` equal to this value?
179
+
- `FloatEquals: <float>`: is the output `Float` equal to this value?
180
+
- `Contains: <string>`: does the output `String` contain this substring?
181
+
- `Name: <string>`: does the output `File` or `Directory` have this exact match basename?
182
+
- `Length: <unsigned integer>`: does the output `String`, `Array`, or `Map` have this length?
183
+
- `Empty: <boolean>`: is the output `String`, `Array`, or `Map` empty?
184
+
- "empty"for `String` types means length zero
185
+
186
+
There are also several recursive output assertions which can be combined with the above in order to test properties of compound WDL types:
187
+
188
+
- `First: <inner assertion>`: applies the inner assertion to the first element of an output `Array`
189
+
- `Last: <inner assertion>`: applies the inner assertion to the last element of an output `Array`
190
+
- `Left: <inner assertion>`: applies the inner assertion to the left element of an output `Pair`
191
+
- `Right: <inner assertion>`: applies the inner assertion to the right element of an output `Pair`
192
+
193
+
An example combining these:
194
+
195
+
```yaml
196
+
assertions:
197
+
outputs:
198
+
fusion_bams: # this output is of type `Array[File]`
199
+
- Length: 2
200
+
- First: { Name: fusions_1.bam }
201
+
- Last: { Name: fusions_2.bam }
202
+
```
203
+
204
+
::: tip Other assertions
205
+
206
+
The above assertions are just a starting point! We intend to continue to grow the list of builtin assertions available to `test` in subsequent releases. Please reach out via the [#sprocket channel on the WDL Slack](https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw) or file a feature request on [the Sprocket repository](https://github.com/stjude-rust-labs/sprocket/issues) to let us know what would be most useful to you during WDL development.
207
+
208
+
:::
209
+
137
210
### How to use test fixtures
138
211
139
212
WDL tasks and workflows often take file inputs, so the Sprocket unit testing framework has attempted to make it as easy as possible to reference "test fixtures" from test YAML.
0 commit comments