Marking a test expected to diff or fail#
The canary.directives.xdiff() and canary.directives.xfail() directives can mark tests that you expect to diff or fail, respectively. For example, the following test is expected to diff:
# Copyright NTESS. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: MIT
import sys
import canary
canary.directives.keywords("fast")
canary.directives.xdiff()
def test():
raise canary.TestDiffed()
if __name__ == "__main__":
sys.exit(test())
$ canary run ./xstatus/xdiff.pyt
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from xstatus
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 'candid-lobo'
INFO: Selecting test cases based on runtime environment
INFO: Starting session 2026-04-21T15-35-40.280028
INFO: Starting process pool with max 2 workers
Job ID Status Queued Elapsed Rank
────────────────────────────────────────────────────────────────────────────────────────────
xdiff 3389dae SUBMITTED 1/1
xdiff 3389dae STARTED 0.3s 1/1
xdiff 3389dae PASS (XDIFF) 0.3s 0.5s 1/1
INFO: 1/1 tests finished with status PASS
INFO: Finished session in 0.53 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/release-26.4.16/src/canary/examples/TestResults
As you can see, the test status was set to xdiff which is considered a successful outcome.
However, if a test that is marked to diff or fail and does not, it will be considered a failure:
# Copyright NTESS. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: MIT
import sys
import canary
canary.directives.keywords("fast")
canary.directives.xfail()
def test():
# This test should fail
return 0
if __name__ == "__main__":
sys.exit(test())
$ canary run ./xstatus/xfail-fail.pyt
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from xstatus
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 'brave-garden'
INFO: Selecting test cases based on runtime environment
INFO: Starting session 2026-04-21T15-35-41.537895
INFO: Starting process pool with max 2 workers
Job ID Status Queued Elapsed Rank
─────────────────────────────────────────────────────────────────────────────────────────────────
xfail-fail 9db7d1b SUBMITTED 1/1
xfail-fail 9db7d1b STARTED 0.3s 1/1
xfail-fail 9db7d1b FAIL (FAILED) 0.3s 0.5s 1/1
┌──────────────┬────────────┬────────────────┬───────────┬───────────┬─────────────────────────────────────────────────┐
│ Job │ ID │ Status │ Queued │ Elapsed │ Details │
├──────────────┼────────────┼────────────────┼───────────┼───────────┼─────────────────────────────────────────────────┤
│ xfail-fail │ 9db7d1b │ FAIL (FAILED) │ 0.0s │ 0.2s │ xfail-fail: expected to exit with code != 0 │
└──────────────┴────────────┴────────────────┴───────────┴───────────┴─────────────────────────────────────────────────┘
1/1 COMPLETE, 1 FAILED, in 00:00:00.47
INFO: Finished session in 0.53 s. with returncode 8
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/release-26.4.16/src/canary/examples/TestResults
Specifying a nonzero exit code#
If a nonzero exit code is expected, use canary.directives.xfail(code), where code is the expected exit code. Any other exit code other than code will be considered a failure.
# Copyright NTESS. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: MIT
import sys
import canary
canary.directives.keywords("fast")
canary.directives.xfail(code=23)
def test():
return 23
if __name__ == "__main__":
sys.exit(test())
$ canary run ./xstatus/xfail-code.pyt
INFO: Initializing empty canary workspace at .
INFO: Collecting generator files from xstatus
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 'lime-veil'
INFO: Selecting test cases based on runtime environment
INFO: Starting session 2026-04-21T15-35-42.800338
INFO: Starting process pool with max 2 workers
Job ID Status Queued Elapsed Rank
─────────────────────────────────────────────────────────────────────────────────────────────────
xfail-code 80a56f0 SUBMITTED 1/1
xfail-code 80a56f0 STARTED 0.3s 1/1
xfail-code 80a56f0 PASS (XFAIL) 0.3s 0.5s 1/1
INFO: 1/1 tests finished with status PASS
INFO: Finished session in 0.53 s. with returncode 0
INFO: Updating view at /home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/release-26.4.16/src/canary/examples/TestResults