Running tests#
Use canary run to run tests.
Basic usage#
$ canary run ./basic
INFO: Collecting generator files from basic
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 2 test specs from 2 generators
INFO: Caching test specs
INFO: Created selection 'blue-river'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-41.150000
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
───────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/2
first 4b172fc STARTED 1/2
first 4b172fc PASS (SUCCESS) 0.6s 1/2
second b1f18b4 SUBMITTED 2/2
second b1f18b4 STARTED 2/2
second b1f18b4 PASS (SUCCESS) 0.3s 2/2
INFO: 2/2 tests finished with status PASS
INFO: Finished session in 1.05 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
Filter tests to run by keyword#
canary run -k KEYWORD_EXPR PATH [PATHS...]
where KEYWORD_EXPR is a Python expression such as -k 'fast and regression'. For example
$ canary run -k first ./basic
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from basic
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 2 test specs from 2 generators
INFO: Caching test specs
INFO: Selecting specs based on 1 rules
INFO: Selected 1 test specs
INFO: Excluded 1 test spec during selection
Reason Count
──────────────────────────────────────────────────
keyword expression 'first' did not match 1
INFO: Created selection 'aquamarine-obsidian'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-43.215538
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
──────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/1
first 4b172fc STARTED 1/1
first 4b172fc PASS (SUCCESS) 0.6s 1/1
INFO: 1/1 tests finished with status PASS
INFO: Finished session in 0.70 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
Limit the number of concurrent tests#
canary run --workers=N PATH [PATHS...]
where N is a number of workers. For example,
$ canary run --workers=1 ./basic
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from basic
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 2 test specs from 2 generators
INFO: Caching test specs
INFO: Created selection 'patient-crow'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-44.929816
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
───────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/2
first 4b172fc STARTED 1/2
first 4b172fc PASS (SUCCESS) 0.6s 1/2
second b1f18b4 SUBMITTED 2/2
second b1f18b4 STARTED 2/2
second b1f18b4 PASS (SUCCESS) 0.3s 2/2
INFO: 2/2 tests finished with status PASS
INFO: Finished session in 1.04 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
Set a timeout on the test session#
canary run --timeout session=T PATH [PATHS...]
where T is a duration in Go’s duration format (40s,, 1h20m, 2h, 4h30m30s, etc.) For example,
$ canary run --timeout session=1m ./basic
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from basic
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 2 test specs from 2 generators
INFO: Caching test specs
INFO: Created selection 'brave-breeze'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-46.993075
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
───────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/2
first 4b172fc STARTED 1/2
first 4b172fc PASS (SUCCESS) 0.6s 1/2
second b1f18b4 SUBMITTED 2/2
second b1f18b4 STARTED 2/2
second b1f18b4 PASS (SUCCESS) 0.3s 2/2
INFO: 2/2 tests finished with status PASS
INFO: Finished session in 1.05 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
Run specific test files#
Run a file directly#
Test files can be run directly by passing their paths to canary run
$ canary run ./basic/first/first.pyt
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from basic/first
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 1 test specs from 1 generators
INFO: Caching test specs
INFO: Created selection 'lucid-kernel'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-48.934884
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
──────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/1
first 4b172fc STARTED 1/1
first 4b172fc PASS (SUCCESS) 0.6s 1/1
INFO: 1/1 tests finished with status PASS
INFO: Finished session in 0.69 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
$ ls -F TestResults
VIEW.TAG
first@
If a path separator is replaced with a colon :, the path is interpreted as root:path. ie, path segments after the : are used as the relative path to the test execution directory:
$ canary run .:basic/first/first.pyt
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from .
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 1 test specs from 1 generators
INFO: Caching test specs
INFO: Created selection 'mellow-night'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-50.527895
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
──────────────────────────────────────────────────────────────────────────────────
first 4b172fc SUBMITTED 1/1
first 4b172fc STARTED 1/1
first 4b172fc PASS (SUCCESS) 0.6s 1/1
INFO: 1/1 tests finished with status PASS
INFO: Finished session in 0.71 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults
$ ls -F TestResults
VIEW.TAG
basic/
Running tests from a file#
Select tests can be executed by specifying their paths in a json or yaml configuration file with the following layout:
testpaths:
- root: <root>
paths:
- <path_1>
- <path_2>
...
- <path_n>
where <root> is a parent directory of the tests and <path_i> are the file paths relative to <root>. If <root> is a relative path, it is considered relative to the path of the configuration file. Consider, for example, the examples directory tree:
$ canary tree --exclude-results .
.
├── analyze_only
│ └── analyze_only.pyt
├── basic
│ ├── first
│ │ └── first.pyt
│ └── second
│ ├── add.py
│ └── second.pyt
├── canary.json
├── centered_space
│ └── centered_space.pyt
├── copy_and_link
│ ├── copy.txt
│ ├── copy_and_link.1.txt
│ ├── copy_and_link.2.txt
│ ├── copy_and_link.pyt
│ └── link.txt
├── ctest
│ ├── CTestTestfile.cmake
│ ├── resource_group_test_1.py
│ └── resource_group_test_2.py
├── depends_on
│ ├── basic
│ │ ├── a.pyt
│ │ └── depends_on_a.pyt
│ ├── multi
│ │ ├── blt.pyt
│ │ ├── green_eggs_and_ham.pyt
│ │ ├── ingredients.pyt
│ │ ├── kitchen_sink.py
│ │ └── kitchen_sink.pyt
│ ├── parameter
│ │ ├── breakfast.pyt
│ │ └── lunch.pyt
│ └── result
│ ├── depends_on_willfail.pyt
│ └── willfail.pyt
├── enable
│ └── enable.pyt
├── execute_and_analyze
│ └── execute_and_analyze.pyt
├── instance_attributes
│ └── instance_attributes.pyt
├── junit.xml
├── parameterize
│ ├── parameterize1.pyt
│ ├── parameterize2.pyt
│ ├── parameterize3.pyt
│ └── parameterize4.pyt
├── plugin
│ └── my_command.py
├── random_space
│ └── random_space.pyt
├── rebaseline
│ ├── rebaseline.pyt
│ └── test.base.out
├── resources
│ └── resources.pyt
├── status
│ ├── diff.pyt
│ ├── fail.pyt
│ ├── pass.pyt
│ ├── skip.pyt
│ └── timeout.pyt
├── tests.json
├── timeoutx
│ └── timeout.pyt
├── vvt
│ └── test_exec_dir.vvt
└── xstatus
├── xdiff-fail.pyt
├── xdiff.pyt
├── xfail-code.pyt
├── xfail-fail.pyt
└── xfail.pyt
To run only centered_space/centered_space.pyt and parameterize/parameterize2.pyt, write the following to tests.json
{
"testpaths": [
{
"root": ".",
"paths": ["centered_space/centered_space.pyt", "parameterize/parameterize2.pyt"]
}
]
}
and pass it to canary run:
$ canary run -f tests.json
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from .
INFO: Collecting generator files from .
INFO: Instantiating generators from collected files
INFO: Generating test specs from generators
INFO: Searching for duplicated tests
INFO: Resolving test spec dependencies
INFO: Generated 12 test specs from 2 generators
INFO: Caching test specs
INFO: Created selection 'raven-pass'
INFO: Selecting test jobs based on runtime environment
INFO: Starting session 2026-06-04T20-45-52.837871
INFO: Starting process pool with max 1 workers
Job ID Status Elapsed Rank
─────────────────────────────────────────────────────────────────────────────────────────────────────
parameterize2.a=1.b=2 b741505 SUBMITTED 1/12
parameterize2.a=1.b=2 b741505 STARTED 1/12
parameterize2.a=1.b=2 b741505 PASS (SUCCESS) 0.7s 1/12
centered_space.a=0.b=0 18d1ae9 SUBMITTED 2/12
centered_space.a=0.b=0 18d1ae9 STARTED 2/12
centered_space.a=0.b=0 18d1ae9 PASS (SUCCESS) 0.4s 2/12
centered_space.a=10.b=0 6fbb430 SUBMITTED 3/12
centered_space.a=10.b=0 6fbb430 STARTED 3/12
centered_space.a=10.b=0 6fbb430 PASS (SUCCESS) 0.4s 3/12
centered_space.a=0.b=2 6c9223c SUBMITTED 4/12
centered_space.a=0.b=2 6c9223c STARTED 4/12
centered_space.a=0.b=2 6c9223c PASS (SUCCESS) 0.4s 4/12
centered_space.a=0.b=1 f237a83 SUBMITTED 5/12
centered_space.a=0.b=1 f237a83 STARTED 5/12
centered_space.a=0.b=1 f237a83 PASS (SUCCESS) 0.4s 5/12
centered_space.a=0.b=-1 4947e35 SUBMITTED 6/12
centered_space.a=0.b=-1 4947e35 STARTED 6/12
centered_space.a=0.b=-1 4947e35 PASS (SUCCESS) 0.4s 6/12
centered_space.a=0.b=-2 071c9c3 SUBMITTED 7/12
centered_space.a=0.b=-2 071c9c3 STARTED 7/12
centered_space.a=0.b=-2 071c9c3 PASS (SUCCESS) 0.4s 7/12
centered_space.a=5.b=0 d8c3599 SUBMITTED 8/12
centered_space.a=5.b=0 d8c3599 STARTED 8/12
centered_space.a=5.b=0 d8c3599 PASS (SUCCESS) 0.4s 8/12
centered_space.a=-5.b=0 c300f2d SUBMITTED 9/12
centered_space.a=-5.b=0 c300f2d STARTED 9/12
centered_space.a=-5.b=0 c300f2d PASS (SUCCESS) 0.4s 9/12
parameterize2.a=5.b=6 95fd37e SUBMITTED 10/12
parameterize2.a=5.b=6 95fd37e STARTED 10/12
parameterize2.a=5.b=6 95fd37e PASS (SUCCESS) 0.4s 10/12
centered_space.a=-10.b=0 9a6e478 SUBMITTED 11/12
centered_space.a=-10.b=0 9a6e478 STARTED 11/12
centered_space.a=-10.b=0 9a6e478 PASS (SUCCESS) 0.4s 11/12
centered_space 97d51af SUBMITTED 12/12
centered_space 97d51af STARTED 12/12
centered_space 97d51af PASS (SUCCESS) 0.5s 12/12
INFO: 12/12 tests finished with status PASS
INFO: Finished session in 5.80 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/src/canary/examples/TestResults