Skip to content

feat: add tests for guide code snippet#552

Draft
m4tx wants to merge 1 commit intomasterfrom
docs-tests-2
Draft

feat: add tests for guide code snippet#552
m4tx wants to merge 1 commit intomasterfrom
docs-tests-2

Conversation

@m4tx
Copy link
Copy Markdown
Member

@m4tx m4tx commented Apr 12, 2026

This adds a test framework to test the code snippets in the guide (the docs/ directory). Currently, the framework defines four different test configurations:

  • toml, tested by parsing as a Cot config file
  • html.j2, tested by trying to build an Askama template
  • rust, tested by building the snippet as an extension of a default project template (as generated by cot-cli)
  • rust,has_main, a version of the above that also defines its own main function

It should be fairly easy to extend this by defining more configurations, if needed.

The framework defines a number of utilities to make the testing more pleasant:

  • Many symbols are imported by default
  • Similarly to rustdoc, lines can be prepended with # to indicate lines that are not displayed in the guide, but required for the test to build
  • For the Askama tests, there are some dummy files and structures created

This is part of the major effort to make the guide always up-to-date. As a result of this, a number of code snippets were modified as they did not build before.

This concludes the work on #471.

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Refactor / cleanup
  • Performance improvement
  • Other (describe above)

@m4tx m4tx requested review from ElijahAhianyo, Copilot and seqre April 12, 2026 21:45
@github-actions github-actions bot added A-docs Area: Documentation A-deps Area: Dependencies C-lib Crate: cot (main library crate) C-macros Crate: cot-macros labels Apr 12, 2026
This adds a test framework to test the code snippets in the guide (the
docs/ directory). Currently, the framework defines four different
test configurations:

* `toml`, tested by parsing as a Cot config file
* `html.j2`, tested by trying to build an Askama template
* `rust`, tested by building the snippet as an extension of a default
  project template (as generated by `cot-cli`)
* `rust,has_main`, a version of the above that also defines its own
  `main` function

It should be fairly easy to extend this by defining more configurations,
if needed.

The framework defines a number of utilities to make the testing more
pleasant:

* Many symbols are imported by default
* Similarly to rustdoc, lines can be prepended with `# ` to indicate
  lines that are not displayed in the guide, but required for the test
  to build
* For the Askama tests, there are some dummy files and structures created

This is part of the major effort to make the guide always up-to-date. As
a result of this, a number of code snippets were modified as they did
not build before.

This concludes the work on #471.
@m4tx m4tx removed request for ElijahAhianyo and seqre April 12, 2026 21:48
@m4tx m4tx marked this pull request as draft April 12, 2026 21:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an integration-test framework to compile/check code blocks in the docs/ guide, and updates multiple guide snippets so they build under the new framework.

Changes:

  • Introduces cot-test crate + libtest-mimic runner to validate fenced code blocks in docs/*.md (Rust/TOML/Askama templates).
  • Updates many guide snippets (hidden # ... lines, async fixes, etc.) to compile under the new checking approach.
  • Adds supporting glue: just test-docs, nextest concurrency override, and small framework/API touch-ups (e.g., TestRequestBuilder::cache, ForeignKey::new).

Reviewed changes

Copilot reviewed 25 out of 27 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
justfile Adds test-docs task/alias to run the new doc-snippet tests.
docs/upgrade-guide.md Adjusts a Rust code fence and list indentation.
docs/testing.md Updates examples; adds async fixes; minor formatting changes.
docs/templates.md Updates Askama examples and adds extra supporting code for compilation.
docs/static-files.md Adds hidden lines so static-file snippets compile.
docs/site/Cargo.lock Bumps cot-site git rev in the docs site lockfile.
docs/README.md Reworks headings and adds placeholder section for doc-test instructions.
docs/openapi.md Updates OpenAPI examples (return types, derives, route registration) to compile.
docs/introduction.md Adds hidden scaffolding + a rust,has_main snippet for the main example.
docs/forms.md Updates form examples to use newer APIs (into_response()?) and adds hidden scaffolding.
docs/db-models.md Makes DB examples compile (adds hidden model scaffolding; comments out sample URLs).
docs/caching.md Adds hidden scaffolding so cache examples compile.
docs/admin-panel.md Updates admin-panel snippets for newer APIs and adds missing scaffolding.
cot/src/test.rs Adds TestRequestBuilder::cache() behind cache feature.
cot/src/project.rs Updates a panic message to reference cot::Project.
cot/src/db/relations.rs Adds ForeignKey::new(...) convenience constructor.
cot-test/tests/doc_code_blocks.rs New libtest-mimic runner that parses Markdown and runs per-block checks.
cot-test/templates/html_main.rs Template-compilation harness for Askama snippets.
cot-test/templates/base.html Base template used by Askama snippet compilation.
cot-test/src/lib.rs New helper crate that generates a temp project and runs cargo check for snippets.
cot-test/Cargo.toml Defines new internal crate and custom test harness entry.
cot-macros/tests/ui/func_query_invalid_field.stderr Updates expected UI test stderr output wording.
cot-macros/tests/ui/attr_main_args.stderr Updates expected stderr to reference cot::Project.
cot-macros/tests/ui/attr_main_args.rs Updates return type to cot::Project.
Cargo.toml Adds cot-test to workspace + new workspace deps (comrak, libtest-mimic, etc.).
Cargo.lock Updates lockfile for new deps and cot-test crate.
.config/nextest.toml Adds nextest grouping to serialize doc-code-block tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +132 to +135
let final_code = match test_type {
"has_main" => code.to_string(),
_ => Self::wrap_in_main(&preamble, code),
};
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_main snippets skip the generated preamble/common imports entirely (final_code is just code.to_string()). This makes rust,has_main blocks depend on having all imports/allow attributes written explicitly, and currently breaks at least the docs/introduction.md snippet that uses impl Project without importing Project. Consider still prepending the preamble (and the #![allow(...)] attributes) for has_main, while only skipping the wrap_in_main wrapper so snippets can define their own main.

Copilot uses AI. Check for mistakes.
Comment on lines +275 to 280
```rust,has_main
# struct CotTutorialProject;
# impl Project for CotTutorialProject {}
#[cot::main]
fn main() -> impl Project {
CotTutorialProject
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rust,has_main snippet uses impl Project but doesn't import/qualify Project (e.g., use cot::Project; or -> impl cot::Project). As written, it won't compile standalone, and it will also fail the doc-code-block tests unless the harness injects the common imports for has_main blocks.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +14
## Testing the code

TODO
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new "Testing the code" section is left as TODO. Since this PR introduces a doc-snippet test framework (cot-test) and a just test-docs target, it would be better to document the exact command(s) to run and any prerequisites (e.g., just test-docs / cargo nextest run -p cot-test).

Copilot uses AI. Check for mistakes.
"examples/sessions",
"examples/todo-list",
"examples/forms",
"examples/forms", "cot-test",
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workspace member list formatting: "examples/forms", "cot-test" is on a single line while the rest of the members entries are one-per-line. Keeping one entry per line makes future diffs cleaner and matches the surrounding style.

Suggested change
"examples/forms", "cot-test",
"examples/forms",
"cot-test",

Copilot uses AI. Check for mistakes.
Comment on lines +210 to +211
The end-to-end testing framework consists of two parts: the [`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct. The [`cot::e2e_test`](attr@cot::e2e_test) macro allows you to define end-to-end tests that allow you to run your project in the background, while the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct allows you to create a test server that you can send your requests to. An example of how to use the [
`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct is shown below in a simple test that checks if the server is running and returns the `Hello world!` response:
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markdown link markup is broken by the line break after the [. This will likely render incorrectly (or not as a link) in the generated guide. Consider keeping the [...] link text on the same line (or removing the stray [ entirely).

Suggested change
The end-to-end testing framework consists of two parts: the [`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct. The [`cot::e2e_test`](attr@cot::e2e_test) macro allows you to define end-to-end tests that allow you to run your project in the background, while the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct allows you to create a test server that you can send your requests to. An example of how to use the [
`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct is shown below in a simple test that checks if the server is running and returns the `Hello world!` response:
The end-to-end testing framework consists of two parts: the [`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct. The [`cot::e2e_test`](attr@cot::e2e_test) macro allows you to define end-to-end tests that allow you to run your project in the background, while the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct allows you to create a test server that you can send your requests to. An example of how to use the [`cot::e2e_test`](attr@cot::e2e_test) macro and the [`TestServerBuilder`](struct@cot::test::TestServerBuilder) struct is shown below in a simple test that checks if the server is running and returns the `Hello world!` response:

Copilot uses AI. Check for mistakes.
Comment on lines 307 to 316
```rust
use std::fmt::Display;
use cot::Template;

struct Item {
title: String,
}

# struct Item { title: String }
# #[derive(Template)]
# #[template(path = "index.html")]
# struct IndexTemplate { item: Item }
impl Display for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.title)
}
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This snippet uses impl Display for Item but Display isn't imported anywhere in this page anymore. To keep the example copy/pasteable, either qualify it (impl std::fmt::Display for Item) or add a (possibly hidden) use std::fmt::Display; line.

Copilot uses AI. Check for mistakes.

# struct Item;
# impl std::fmt::Display for Item { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } }
impl HtmlSafe for Item {}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This HtmlSafe example no longer imports askama::filters::HtmlSafe, so impl HtmlSafe for Item {} won't compile as-is. Consider qualifying the trait (askama::filters::HtmlSafe) or adding back a (possibly hidden) use askama::filters::HtmlSafe; line.

Suggested change
impl HtmlSafe for Item {}
impl askama::filters::HtmlSafe for Item {}

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

🐰 Bencher Report

Branchdocs-tests-2
Testbedgithub-ubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
empty_router/empty_router📈 view plot
🚷 view threshold
6.72 ms
(+10.72%)Baseline: 6.07 ms
7.37 ms
(91.20%)
json_api/json_api📈 view plot
🚷 view threshold
1.21 ms
(+14.71%)Baseline: 1.06 ms
1.26 ms
(96.48%)
nested_routers/nested_routers📈 view plot
🚷 view threshold
1.08 ms
(+11.40%)Baseline: 0.97 ms
1.15 ms
(94.50%)
single_root_route/single_root_route📈 view plot
🚷 view threshold
1.06 ms
(+13.70%)Baseline: 0.94 ms
1.11 ms
(95.63%)
single_root_route_burst/single_root_route_burst📈 view plot
🚷 view threshold
17.24 ms
(-2.45%)Baseline: 17.68 ms
21.08 ms
(81.80%)
🐰 View full continuous benchmarking report in Bencher

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-deps Area: Dependencies A-docs Area: Documentation C-lib Crate: cot (main library crate) C-macros Crate: cot-macros

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants