Skip to content

Factor out more mdtest helpers#24754

Merged
ntBre merged 14 commits into
mainfrom
brent/mdtest-run
May 12, 2026
Merged

Factor out more mdtest helpers#24754
ntBre merged 14 commits into
mainfrom
brent/mdtest-run

Conversation

@ntBre

@ntBre ntBre commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

This is a follow-up to #24616 to share a bit more infrastructure between ty_test and the ruff_test crate introduced in #24617. In particular, the primary run function has moved into mdtest, along with the attempt_test, check_panic and snapshot_diagnostics helpers.

You should be able to review commit-by-commit, but the first commit is probably the most important to look at since it moves the tracing setup and inconsistency checks from ty_test::run into ty_test::run_test. I think that narrows the span of the tracing logs a bit, but the important section should still be covered.

The other commits should be pretty straightforward and reviewable as one diff.

Test Plan

Existing tests, as well as rebasing #24617 onto this branch.

@ntBre ntBre added the testing Related to testing Ruff itself label Apr 20, 2026
@astral-sh-bot

astral-sh-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 89.36%. The percentage of expected errors that received a diagnostic held steady at 85.49%. The number of fully passing files held steady at 88/134.

@astral-sh-bot

astral-sh-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Full report with detailed diff (timing results)

@astral-sh-bot

astral-sh-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

ℹ️ ecosystem check encountered format errors. (no format changes; 1 project error)

apache/airflow (error)

ruff format --preview

warning: Detected debug build without --no-cache.
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)
error: Encountered error: No such file or directory (os error 2)

@ntBre ntBre force-pushed the brent/mdtest-run branch 2 times, most recently from 9a92402 to 9287424 Compare April 21, 2026 14:02
@ntBre ntBre marked this pull request as ready for review April 21, 2026 14:26
@astral-sh-bot astral-sh-bot Bot requested a review from oconnor663 April 21, 2026 14:26
Comment thread crates/mdtest/src/lib.rs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you say how much of the code in this file changed? Is it mostly a move, and I don't have to review the code beyond the outer signature, or is there more to it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, sorry, I should have split the commits up a bit more. I just rebased and split out the changes from the moves themselves. It was mostly a move but should be easier to see in the diff now.

Comment thread crates/mdtest/src/lib.rs
@@ -240,14 +353,15 @@ pub(crate) fn apply_snapshot_filters(rendered: &str) -> std::borrow::Cow<'_, str
}

pub fn validate_inline_snapshot(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this function still need to be public? What about other symbols that we made public as part of your last PRs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is currently used in ty_test, but maybe some of your other comments will change this. I went through all of the other symbols and restricted more visibilities.

Comment thread crates/mdtest/src/lib.rs Outdated
continue;
}

let result = run_test(&test, &mut assertion, output_format);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the abstraction here is correct. It is unfortunate that attempt_test needs to be public only because ty_test's pull types

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree that this feels weird, but I didn't really see a good way around it. ty uses attempt_test twice, as you point out, and there doesn't seem to be a good way to roll both the check_file and the pull_types calls into a single attempt_test invocation. I'm definitely happy to revisit it if I'm missing something, though.

Comment thread crates/mdtest/src/parser.rs Outdated
.has_directive_set(MdtestDirective::PullTypesSkip)
}

pub fn check_panic(&self, panic_info: Option<PanicError>) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It feels weird that this is in the parser crate. Is this something we could expose on AttemptTest instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I actually thought this was pretty nice here. This is the parser module within the mdtest crate, not a separate parser crate, in case that makes any difference. So it's exposed as MarkdownTest::check_panic, which gives us access to MarkdownTest::should_expect_panic and MarkdownTest::name. We'd have to pass some of that information separately if we wanted to expose this on AttemptTest.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, this is on test.

Maybe it would be worth moving test out of the parser module. It feels more like a data structure, similar to the AST. Anyway, I don't feel to strongly about that.

I think I'd still prefer making this a standalone function. E.g., it feels a bit off to me that a test file knows how to snapshot diagnostics, or assert the panic info. But I don't feel strongly about it. I guess my biggest concern really is that this logic is in the parser module

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah okay, makes sense. I'll just move these checks to standalone functions for now.

Comment thread crates/mdtest/src/lib.rs
test_name: &str,
crate_name: &str,
suite: &parser::MarkdownTestSuite<'_, C>,
mut run_test: impl FnMut(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if we should make this a trait, where C is an associated type. Maybe it's not worth it. I'm just thinking about how we could share more of run_test between crates. It probably requires something where the trait has a set_up() method that returns a TestRun (yay, more associated types), where TestRun has a check_file function. set_up would contain the logic to set up the Db etc.

For now, I think either a function or a trait is fine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My feeling was that it was not worth it to factor out much more of the two run_test versions because they end up being pretty different. The last chunk of code I'd really like to share is this:

let diagnostics = match mdtest_result {
Ok(diagnostics) => diagnostics,
Err(failures) => {
if test.should_expect_panic().is_ok() {
panic_info = Some(failures.info);
return None;
}
return Some(failures.into_file_failures(db, "run mdtest", None));
}
};
let failure = match matcher::match_file(db, test_file.file, &diagnostics).and_then(
|inline_diagnostics| {
mdtest::validate_inline_snapshot(
&resolver,
"ruff",
test_file,
&inline_diagnostics,
&mut markdown_edits,
)
},
) {
Ok(()) => None,
Err(line_failures) => Some(FileFailures {
backtick_offsets: test_file.to_code_block_backtick_offsets(),
by_line: line_failures,
}),
};
all_diagnostics.extend(diagnostics);
failure

but it was only ~30 lines and with a couple of small differences. I can still look into this, though. It would probably be better than the snapshot_diagnostics and check_panic methods anyway.

@ntBre ntBre force-pushed the brent/mdtest-run branch from 9287424 to e3fb85f Compare April 22, 2026 15:10
@ntBre ntBre marked this pull request as draft April 28, 2026 22:25
@ntBre ntBre force-pushed the brent/mdtest-run branch from 61c2a49 to ca5cf14 Compare May 11, 2026 19:05
@ntBre ntBre marked this pull request as ready for review May 11, 2026 19:23
@astral-sh-bot astral-sh-bot Bot requested a review from charliermarsh May 11, 2026 19:23
@ntBre ntBre removed the request for review from charliermarsh May 11, 2026 19:23
@ntBre ntBre assigned MichaReiser and unassigned charliermarsh May 11, 2026
Comment thread crates/mdtest/src/parser.rs Outdated
.has_directive_set(MdtestDirective::PullTypesSkip)
}

pub fn check_panic(&self, panic_info: Option<PanicError>) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, this is on test.

Maybe it would be worth moving test out of the parser module. It feels more like a data structure, similar to the AST. Anyway, I don't feel to strongly about that.

I think I'd still prefer making this a standalone function. E.g., it feels a bit off to me that a test file knows how to snapshot diagnostics, or assert the panic info. But I don't feel strongly about it. I guess my biggest concern really is that this logic is in the parser module

@ntBre ntBre merged commit 961f533 into main May 12, 2026
91 of 92 checks passed
@ntBre ntBre deleted the brent/mdtest-run branch May 12, 2026 14:24
thejchap pushed a commit to thejchap/ruff that referenced this pull request May 23, 2026
## Summary

This is a follow-up to astral-sh#24616 to
share a bit more infrastructure between `ty_test` and the `ruff_test`
crate introduced in astral-sh#24617. In
particular, the primary `run` function has moved into `mdtest`, along
with the `attempt_test`, `check_panic` and `snapshot_diagnostics`
helpers.

You should be able to review commit-by-commit, but the first commit is
probably the most important to look at since it moves the `tracing`
setup and inconsistency checks from `ty_test::run` into
`ty_test::run_test`. I think that narrows the span of the `tracing` logs
a bit, but the important section should still be covered.

The other commits should be pretty straightforward and reviewable as one
diff.

## Test Plan

Existing tests, as well as rebasing astral-sh#24617 onto this branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

testing Related to testing Ruff itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants