1

The program takes an path to a configuration file. E.g. cargo run -- -c path/to/yaml. This does not however work with cargo test. cargo test -- -c path/to/yaml and following error will occur: error: Unrecognized option: 'c'.

Attempts and research

Clap provide a method fn from_args() -> Self, but did not fully know how this would solve the problem. A similar problem was solved by making it a integration test and add

[[test]]
name = "cpp_test"
# path = "tests/cpp_test.rs"   # This is automatic; you can use a different path if you really want to.
harness = false

to the cargo.toml file.
In my case I want to test some functions and thus unit test. I do not believe this would work.

Eirik
  • 57
  • 1
  • 8
  • I'm not familiar with using cmd args inside test, but this seems really like [this question](https://stackoverflow.com/questions/65791697/passing-custom-command-line-arguments-to-a-rust-test). Hope you can find a solution there. – Campbell He Jun 29 '22 at 16:56
  • It is a similar question, but not quite the solution. I guess theirs solution was to make it a integration test and disable the harness. I also found a [discussion]((https://internals.rust-lang.org/t/test-and-external-test-harnesses/3145) that may be relevant. I will also add this to the question. – Eirik Jun 29 '22 at 18:21

1 Answers1

1

I think the simplest way is to have a fn main_body(args: Args) that does the real work, and then just test main_body by passing the args directly in your source code instead of on the command line.

use clap::Parser; // 3.1.18

#[derive(Parser)]
struct Args {
    #[clap(short, long)]
    name: String,
}

fn main_body(args: Args) -> Result<(), ()> {
    // Your main body here
    Ok(())
}

fn main() -> Result<(), ()> {
    let args = Args::parse();
    main_body(args)
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test() {
        let args = Args { name: "Bob".into() };
        assert_eq!(main_body(args), Ok(()));
    }
}
BallpointBen
  • 9,406
  • 1
  • 32
  • 62
  • Yes that would be possible. But if I want to use a function, e.g. create_connection() that is used for multiple other functions, this would be cumbersome. That means I have to pass args from main, to every other functions that will use create_connection(). – Eirik Jun 30 '22 at 14:02
  • 2
    @Eirik I would argue that that's the correct design. Relying on global, hidden, unvalidated, unparsed state present in `std::env::args()` seems like a much more brittle and difficult-to-understand design than parsing the args once and then passing the resulting data around wherever it's needed. – BallpointBen Jun 30 '22 at 19:36