Quarto Test Patterns
This document describes the standard patterns for writing smoke tests in the Quarto CLI test suite.
Test Structure Overview
Quarto uses Deno for testing with custom verification helpers located in:
tests/test.ts- Core test runner (testQuartoCmd)tests/verify.ts- Verification helpers (fileExists,pathDoNotExists, etc.)tests/utils.ts- Utility functions (docs(),outputForInput(), etc.)
Common Test Patterns
Simple Render Tests
For testing single document rendering with automatic cleanup:
With additional verifiers:
Key points:
testRender()automatically handles output verification and cleanupRespects
QUARTO_TEST_KEEP_OUTPUTSenv var for debuggingSet
noSupportingparameter based on expected output:true- For truly self-contained HTML (no_files/directory, inline everything)false- For HTML with supporting files directory (OJS runtime, widget dependencies, plots, etc.)Most HTML outputs should use
false(only usetruefor formats likehtmlwithself-contained: true)
Pass additional verifiers in the array parameter (optional)
Cleanup happens automatically via
cleanoutput()in teardown
Project Rendering Tests
For testing project rendering (especially website projects):
Key points:
Use
docs()helper to create relative paths fromtests/docs/For website projects, output goes to
_sitesubdirectoryUse absolute paths with
join()for file verificationClean up output directories in teardown
Extension Template Tests
For testing quarto use template:
Key points:
Use
Deno.makeTempDirSync()for isolated test environmentCreate mock template source with test files
Template files get renamed to match target directory name
Use
cwd()function to set working directory for command executionClean up entire temp directory including source files
File verification uses relative paths when checking files in
cwd()
Verification Helpers
Core Verifiers
Path Helpers
Output Directory Patterns
Different project types use different output directories:
Test File Organization
Tests follow this directory structure:
Common Patterns
Cleanup Pattern
Always clean up generated files in teardown:
Multiple Test Cases
When testing multiple scenarios, declare constants at module level:
Path Construction
Absolute paths: Use
join()for all path operationsRelative to docs: Use
docs()helperRelative to cwd: Use plain strings or template literals in template tests
Examples from Codebase
Simple Render Test
See tests/smoke/render/render-plain.test.ts for the simplest render tests (no additional verifiers).
See tests/smoke/render/render-minimal.test.ts for render test with custom HTML element verification.
Project Ignore Test
See tests/smoke/project/project-ignore-dirs.test.ts for testing directory exclusion patterns.
Website Rendering Test
See tests/smoke/project/project-website.test.ts for website project rendering patterns.
Template Usage Test
See tests/smoke/use/template.test.ts for extension template patterns.
Engine-Specific Test Considerations
Shared Test Environments (Critical for quarto-cli Testing)
Quarto-cli test infrastructure uses a SINGLE managed environment for all tests:
Julia:
tests/Project.toml+tests/Manifest.tomlPython:
tests/.venv/(managed by uv/pyproject.toml)R:
tests/renv/+tests/renv.lock
The configure-test-env scripts ONLY manage these main environments. CI builds depend on this structure.
Do NOT create language environment files in test subdirectories:
Why this fails:
Julia searches UP for
Project.tomland uses the first one foundPython/R will use local environments if present
CI scripts won't configure these local environments
Tests will fail in CI even if they work locally
Adding new package dependencies:
For ANY engine (Julia, Python, R), add dependencies to the main tests/ environment:
Note: While Quarto supports local Project.toml files in document directories for production use, the quarto-cli test infrastructure specifically does NOT support this pattern. All test dependencies must be in the main tests/ environment.
Best Practices
Always clean up: Use teardown to remove generated files
Use helpers: Leverage
docs(),fileExists(), etc. instead of manual checksAbsolute paths: Use
join()for all path construction to handle platform differencesTest isolation: Use temp directories for tests that create files
Clear names: Use descriptive variable names like
projectDir,outputDir,templateFolderComment intent: Add comments explaining what should/shouldn't happen
Handle errors: Wrap cleanup in try-catch to avoid test suite failures from cleanup issues
Testing File Exclusion
When testing that files are excluded (like AI config files):
Run test without fix first to verify it fails, then verify it passes with fix.