#[cfg(doctest)] is only set in one specific condition: when collecting doctests. That is, when rustdoc is analyzing your crate, not for documenting it, but for pulling doctest code out of items’ documentation. It's more like #[cfg(doc)] than anything else — for both cfgs, no code is actually compiled/run under that cfg. For #[cfg(doc)], the only output is documentation text, and for #[cfg(doctest)], the only output is the source code of doctests.
This means that, if you want to modify your doctests when testing, you can do it, but you do it at the outer level, in the source of the containing Rust program:
That said, I recommend that you avoid or minimize the amount of cfg changes that apply to doctests. The value of doctests as opposed to other kinds of tests is that they are examples that are tested to work. As much as possible, users should be able to copy your example code into their own project and expect it to compile and run in exactly the same way. (Another recent thread on a similar topic, where I said much the same thing.)
Of course, there are other uses of doctests, like compile_fail tests not meant to be read by anyone. #[cfg(doctest)] is perfect for that if you apply it to a dummy item carrying the doctest:
Thank you Kevin.
(Background/rant: Working around Forbidding lints doesn't really work in macros · Issue #110613 · rust-lang/rust · GitHub to have compile_fail doctests fail on violated lints that have deny (or forbid, which is not recommended) issued by macro_rules! defined in another crate. I ended up distributing "frontend" macros in a file, and loading it into client's crate.
So I'll workaround-yet-again by not using #[cfg(doctest)] and the client will indicate it by an optional flag passed to the macro-loading-macro. Otherwise (without the flag) it fails to use #[cfg(test)] for unit tests only.)