A version of Parser::parse_from
that reads a mock of the environment, for use in testing
#5104
Closed
2 tasks done
Labels
C-enhancement
Category: Raise on the bar on expectations
Please complete the following tasks
Clap Version
4.3
Describe your use case
I have been using clap for years, and I love it, thank you.
Frequently the pattern with which I use it looks something like this:
That is, I usually derive
Parser
and specify defaults for everything, and then separately implementDefault
myself.Then, in tests that require the config, I usually use
Default
to create the test object, or I use the..Default::default()
syntax:This helps me avoid touching all the tests when a new option is added which doesn't affect most of them.
This is less DRY than skipping
impl Default
and just usingParser::parse_from
in these tests to get default or nearly default configs. But that has the problem that it reads from the environment, and so if a developer sets one of these vars and then runscargo test
, the test may run differently or fail, which can be hard to track down.When I skip the
Parser
machinery and useDefault::default
, then I can write tests that are isolated from the enviornment.However, it is not very dry that I usually end up writing all the defaults out twice, once in
derive(Parser)
and once inimpl Default
, so that feels a bit silly.In another case I ran into, I really did want to write tests of argument parsing:
In this case, I do want to test that I set up the config group properly and it works as expected, but afaict there's no way for me to test this in a way that's isolated from the environment. And so these tests can start failing if one of these env is set, which a developer might easily do for local testing.
This can be worked around of course by unsetting env before parsing:
But this feels dirty, because now I'm manipulating global state in a bunch of tests that are running in parallel, and conceivably they could conflict with eachother. (In my actual use-cases, that is unlikely and this is a fine work around.)
Describe the solution you'd like
One solution that would solve all my problems would be if there were a new function in
trait Parser
, something likewhich would work like
parse_from
, but refer to my hashmap instead of callingstd::env::var
.Then I could write tests that don't implicitly read a bunch of environment variables that I care about.
If this existed, I would also likely stop implementing
Default
on my parsers, and just useparse_from_with_env(["", "my-test", "--param=foo"], Default::default())
when I need to construct configs in tests.Alternatives, if applicable
Another approach, which wouldn't solve all of my problems, but would help me be more DRY, would be:
Make a way to use
clap-derive
to deriveDefault
, based on thedefault-value
that are set.For example it would be cool if this worked:
and produced the impl of
Default
forConfig
that I was going to write, which was based on taking thedefault_value
for each parameter, and running it through thevalue_parser
. (Ideally it wouldn't also look at the os environment.)Additional Context
No response
The text was updated successfully, but these errors were encountered: