Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to gate doctests on cfgs #93083

Open
Manishearth opened this issue Jan 19, 2022 · 2 comments
Open

Add ability to gate doctests on cfgs #93083

Manishearth opened this issue Jan 19, 2022 · 2 comments
Labels
A-doctests Area: Documentation tests, run by rustdoc T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@Manishearth
Copy link
Member

Currently, if a doctest uses specific cargo features, you have one of two options for dealing with it:

(A) You can decide to always use --all-features when running cargo test. This is not great: if you want to test specific features you cannot do so. and also not all crates work with --all-features since features may be mutually exclusive.

(B) You can do the following:

/// 
/// ```
/// # #[cfg(feature = "foo)]
/// # {
///  ... doctest goes here ...
/// # }
/// ```

Here, you're conditionally gating the test on the cfg. This works, but it has a major downside: the test will be reported as passing (as opposed to "ignored") in the cargo test output, which is misleading and not at all the behavior you want around tests. It's also hacky boilerplate that is necessary for a rather common task.

rustdoc has access to cfg-parsing, it should be possible for it to compile-time-ignore tests based on a cfg() spec put on top of the code block.

@Manishearth Manishearth added T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. A-doctests Area: Documentation tests, run by rustdoc labels Jan 19, 2022
@mqudsi
Copy link
Contributor

mqudsi commented Jun 30, 2022

There's an alternative approach C that might (or might not!) be considered cleaner, which is to manually lift (just a few) doc comments to doc attributes then left them again via cfg_attr to be contingent on the presence/absence of a feature.

The approach I have been using to include a doctest if feature std is present and exclude it otherwise:

/// This is the documentation for `foo`.
///
/// An example (that's also validated via doctests):
#[cfg_attr(not(feature = "std"), doc = "```ignore")]
#[cfg_attr(feature = "std", doc = "```")]
/// use size::Size;
///
/// // Create a strongly-typed size object. We don't even need to specify a numeric type!
/// let file1_size = Size::from_bytes(200);
/// // Create another Size instance, this time from a floating-point literal:
/// let file2_size = Size::from_kb(20.1);
/// ```
fn foo() {}

which has the added benefit of cargo test reporting that the test was skipped if it wasn't run.

It works well enough by reusing the existing constructs that I would say there's no need to implement any new features if it weren't for the fact that this runs afoul of tools that operate on the source code as-is before any macro/attribute expansions or evaluations; see for example how this approach breaks rustfmt (while @Manishearth's approach B from above doesn't).

@Kixunil
Copy link
Contributor

Kixunil commented Jun 30, 2022

@mqudsi cool trick! rustfmt issue seems to be good enough reason to support gating in language though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-doctests Area: Documentation tests, run by rustdoc T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
Status: No status
Development

No branches or pull requests

3 participants