|
| 1 | +# Common workflow language conformance test suite |
| 2 | + |
| 3 | +The conformance tests are intended to test feature coverage of a CWL |
| 4 | +implementation. It uses the module cwltest from https://github.com/common-workflow-language/cwltest/. |
| 5 | + |
| 6 | +## Pre-requisites |
| 7 | + |
| 8 | +You will need both the `cwltest` Python package and the CWL runner you would like to test installed. |
| 9 | + |
| 10 | +Installing the `cwltest` Python package using a virtualenv: |
| 11 | + |
| 12 | +``` |
| 13 | +$ python3 -m venv cwltest_env |
| 14 | +$ source cwltest_env/bin/activate |
| 15 | +$ pip install cwltest |
| 16 | +``` |
| 17 | + |
| 18 | +or via `bioconda` |
| 19 | + |
| 20 | +``` |
| 21 | +$ conda install -c bioconda cwltest |
| 22 | +``` |
| 23 | + |
| 24 | +## Usage |
| 25 | + |
| 26 | +```bash |
| 27 | +$ ./run_test.sh |
| 28 | +--- Running conformance test draft-3 on cwl-runner --- |
| 29 | +Test [49/49] |
| 30 | +All tests passed |
| 31 | +``` |
| 32 | + |
| 33 | + |
| 34 | +## Options |
| 35 | + |
| 36 | +`RUNNER=other-cwl-runner` |
| 37 | + |
| 38 | +The CWL implementation to be tested. |
| 39 | + |
| 40 | +### Test Selection |
| 41 | + |
| 42 | +`--tags` |
| 43 | + |
| 44 | +A comma separated list of [tags](#tags-for-conformance-tests); only tests with these tags will be tested. |
| 45 | +`--tags shell_command` will run all tests with `shell_command` in their `tags` list. |
| 46 | + |
| 47 | +`-n{test_range}` |
| 48 | + |
| 49 | +Run only the specific test numbers. `{test_range}` is a comma separated list of |
| 50 | +single test numbers and/or numeric ranges. |
| 51 | +`-n5-7,15` == only runs the 5th, 6th, 7th, and 15th tests. |
| 52 | + |
| 53 | +`-N{test_range}` |
| 54 | + |
| 55 | +Like the lowercase `-n` option, except that the specified tests will not be run. |
| 56 | +Can be mixed with the other test selectors: `-n5-7,15 -N6` == only runs the 5th, 7th, and 15th tests, skipping the 6th test. |
| 57 | + |
| 58 | +`-s{test_names}` |
| 59 | + |
| 60 | +Run the specific tests according to their `id`s. `{test_names}` is a comma separated list of |
| 61 | +test identifiers (the `id` field). `-scl_optional_bindings_provided,stdout_redirect_docker,expression_any_null` |
| 62 | +achieves the same effect as `-n5-7,15 -N6` and it will still work if the tests are re-ordered. |
| 63 | + |
| 64 | +`-S{test_names}` |
| 65 | + |
| 66 | +Excludes specific tests according to their `id`s. `{test_names}` is a comma separated list of |
| 67 | +test identifiers (the `id` field). `--tags shell_command -Sstderr_redirect_shortcut` |
| 68 | +will run all tests with `expression_tool` in their `tags` list except the test |
| 69 | +with the `id` of `stderr_redirect_shortcut`. |
| 70 | + |
| 71 | +### Misc |
| 72 | + |
| 73 | +`EXTRA="--parallel --singularity"` |
| 74 | + |
| 75 | +Extra options to pass to the CWL runner (check your runner for exact options) |
| 76 | + |
| 77 | +`-j=4` |
| 78 | + |
| 79 | +The number of different tests to run at the same time |
| 80 | + |
| 81 | +`--junit-xml=FILENAME` |
| 82 | + |
| 83 | +Store results in JUnit XML format using the given FILENAME. |
| 84 | + |
| 85 | +`--classname=CLASSNAME` |
| 86 | + |
| 87 | +In the JUnit XML, tag the results with the given CLASSNAME. |
| 88 | +Can be useful when multiple test runs are combined to document the differences in `EXTRA=`. |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +For example, to run conformance test 15,16,17, and 20 against the "cwltool" |
| 93 | +reference implementation using the `podman` container engine |
| 94 | +and parallel execution of workflow steps |
| 95 | + |
| 96 | +```bash |
| 97 | +$ ./run_test.sh RUNNER=cwltool -n15-17,20 EXTRA="--parallel --podman" |
| 98 | +Test [15/49] |
| 99 | +Test [16/49] |
| 100 | +Test [17/49] |
| 101 | +Test [20/49] |
| 102 | +All tests passed |
| 103 | +``` |
| 104 | + |
| 105 | +## OS X / macOS Notes |
| 106 | + |
| 107 | +_NOTE_: For running on OSX systems, you'll need to install coreutils via brew. This will add to your |
| 108 | +system some needed GNU-like tools like `greadlink`. |
| 109 | + |
| 110 | +1. If you haven't already, install [brew](http://brew.sh/) package manager in your mac |
| 111 | +2. Run `brew install coreutils` |
| 112 | + |
| 113 | +## Format of the conformance test file |
| 114 | + |
| 115 | +A single conformance test consist of the path to an input CWL document plus an input CWL object |
| 116 | +and the expected outputs (or `should_fail: true` if the test is deliberately broken) |
| 117 | + |
| 118 | +They are stored in [`conformance_tests.yaml`](https://github.com/common-workflow-language/cwl-v1.2/blob/main/conformance_tests.yaml) |
| 119 | +(or a file `$import`ed into that one) |
| 120 | + |
| 121 | +You can examine [the formal schema of this file](https://github.com/common-workflow-language/cwltest/blob/main/cwltest/cwltest-schema.yml), |
| 122 | +or just continue reading here for an explanation. |
| 123 | + |
| 124 | +The conformance test file is a YAML document: a list of key-value pairs. |
| 125 | + |
| 126 | +We will use this single entry to explain the format |
| 127 | +``` yaml |
| 128 | +- doc: Test command line with optional input (missing) |
| 129 | + id: cl_optional_inputs_missing |
| 130 | + tool: tests/cat1-testcli.cwl |
| 131 | + job: tests/cat-job.json |
| 132 | + output: |
| 133 | + args: [cat, hello.txt] |
| 134 | + tags: [ required, command_line_tool ] |
| 135 | +``` |
| 136 | +- `doc`: A unique, single-line sentence that explain what is being tested. |
| 137 | + Will be printed at test execution time, so please don't make it too long! |
| 138 | + Additional documentation can go as comments in the CWL document itself. |
| 139 | +- `id`: a short list of underscore (`_`) separated words that succinctly identifies and explains the test. |
| 140 | +- `tool` the path to the CWL document to run |
| 141 | +- `job`: the CWL input object in YAML/JSON format. If there are no inputs then use `tests/empty.json`. |
| 142 | +- `output` [the CWL output object expected.](#output-matching) |
| 143 | +- `tags`: a yaml list of tag names, see [the list of canonical tags below](#tags-for-conformance-tests). |
| 144 | + Must include one or more of the following tags: `command_line_tool`, `expression_tool` or `workflow`. |
| 145 | + If the test does not test any optional features, the tag `required` is required. |
| 146 | + |
| 147 | +Because `conformance_tests.yaml` is a `schema-salad` processed document, [`$import`](https://www.commonwl.org/v1.2/SchemaSalad.html#Import) |
| 148 | +can be used to organize the tests into separate files. |
| 149 | + |
| 150 | +Currently, the main file is too big (over 3400 lines); we are slowly re-organizing it. |
| 151 | + |
| 152 | +Eventually it would be good to organize the tests so that the test for each optional feature and other logical groups of tests are in their own separate file; |
| 153 | +with the supporting CWL documents and their inputs in separate sub-folders of `tests` as well. |
| 154 | + |
| 155 | +Example: [`- $import: tests/string-interpolation/test-index.yaml`](https://github.com/common-workflow-language/cwl-v1.2/blob/5f27e234b4ca88ed1280dedf9e3391a01de12912/conformance_tests.yaml#L3395) |
| 156 | +adds all the entries in [`tests/string-interpolation/test-index.yaml`](https://github.com/common-workflow-language/cwl-v1.2/blob/main/tests/string-interpolation/test-index.yaml) |
| 157 | +as entries in the main conformance test file. |
| 158 | + |
| 159 | +## Output matching |
| 160 | + |
| 161 | +In each test entry there is an `output` field that contains a mapping of the expected outputs names and their values. |
| 162 | + |
| 163 | +If a particular value could vary and it doesn't matter to the proper functioning of the test, then it can be represented by the special token `Any`. |
| 164 | + |
| 165 | +At any level, if there is an extra field, then that will be considered an error. |
| 166 | +An exception to this is `class: File` and `class: Directory` objects, the `cwl-runner` under test can add additional fields here without causing a test to fail. |
| 167 | +Likewise, if you don't want to test some aspect of a `class: File` or `class: Directory` object (like `nameext`) you can just omit it. |
| 168 | + |
| 169 | +[According to the CWL standards](https://www.commonwl.org/v1.2/CommandLineTool.html#File), the format of the `location` field in |
| 170 | +`class: File` and `class: Directory` is implementation specific and we should not be testing them. |
| 171 | +Please remember to use `location: Any` for them. |
| 172 | + |
| 173 | +Currently, we do [test the contents of the location field in some older tests, but we should stop](https://github.com/common-workflow-language/common-workflow-language/issues/930) |
| 174 | +If you are editing those old tests, you may be interested in some special processing for `class: File` and `class: Directory` output objects: |
| 175 | +any `location` value specified will succeed if there is either an exact match to the real output, or it matches the end of the real output. |
| 176 | +Additionally, for `class: Directory` the location reported by the actual execution will have any trailing forward slash (`/`) trimmed off before comparison. |
| 177 | + |
| 178 | +Likewise, please do not test the `path` for `class: File` and `class: Directory`. |
| 179 | + |
| 180 | +## Writing a new conformance test |
| 181 | + |
| 182 | +To add a new conformance test: |
| 183 | +1. Ensure the CWL document you have tests the desired feature or aspect. |
| 184 | +2. All `CommandLineTool`s need a software container (via `DockerRequirement`) for better reproducibility, preferably under `hints`. |
| 185 | + Please limit your container usage to the following: |
| 186 | + - `dockerPull: docker.io/alpine:latest` |
| 187 | + - `dockerPull: docker.io/bash:4.4` |
| 188 | + - `dockerPull: docker.io/debian:stable-slim` |
| 189 | + - `dockerPull: docker.io/python:3-slim` |
| 190 | +4. Run your test using the CWL reference runner (`cwltool`) or another CWL runner |
| 191 | + that shows the correct behavior to collect the output, or confirm that validation/execution fails as expected |
| 192 | +3. Add the CWL document and output object to the subdirectory `tests` in this repository. |
| 193 | +4. Fill out a new entry in [conformance_tests.yaml](conformance_tests.yaml) following the [format of the conformance test file](#format-of-the-conformance-test-file) |
| 194 | +5. Send a pull request to [current staging branch for the next revision of the CWL standards](https://github.com/common-workflow-language/cwl-v1.2/tree/1.2.1_proposed) |
| 195 | + with your changes |
| 196 | + |
| 197 | +## Tags for conformance tests |
| 198 | + |
| 199 | +Each test in the [conformance_tests.yaml](conformance_tests.yaml) should be tagged with one or more tags. |
| 200 | + |
| 201 | +1. A `command_line_tool`, `expression_tool` or `workflow` tag to identify whether a CommandLineTool, ExpressionTool |
| 202 | + or Workflow is being tested |
| 203 | +2. If the test does not test any optional features, the tag `required` |
| 204 | +3. The name of any features that are being tested: |
| 205 | + 1. `docker` for DockerRequirement |
| 206 | + 1. `env_var` for EnvVarRequirement |
| 207 | + 1. `format_checking` for checking format requirement annotation on File inputs |
| 208 | + 1. `initial_work_dir` for InitialWorkDirRequirements |
| 209 | + 1. `inline_javascript` for InlineJavascriptRequirement |
| 210 | + 1. `inplace_update` for InplaceUpdateRequirement |
| 211 | + 1. `input_object_requirements` for tests that use cwl:requirements in the input object |
| 212 | + 1. `multiple_input` for MultipleInputFeatureRequirement |
| 213 | + 1. `networkaccess` for NetworkAccess |
| 214 | + 1. `resource` for ResourceRequirement |
| 215 | + 1. `scatter` for ScatterFeatureRequirement |
| 216 | + 1. `schema_def` for SchemaDefRequirement |
| 217 | + 1. `shell_command` for ShellCommandRequirement |
| 218 | + 1. `step_input` for StepInputExpressionRequirement |
| 219 | + 1. `subworkflow` for SubworkflowRequirement |
| 220 | + 1. `timelimit` for ToolTimeLimit |
0 commit comments