Reputation: 291
So I built a small Rust CLI tool with structopt
and now want to add some tests but didn't find any useful docs/ examples about how to write it
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "example")]
struct Cli {
domain: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::from_args();
let url = format!("https://example.com/{}", args.domain);
let resp = ureq::get(&url.to_string()).call().into_json()?;
println!("Has data for domain: {}", args.domain);
Ok(())
}
I'm about to have tests something like this
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid_domain() {
// Example functions
let cli = Cli::build_command(domain: "google.com");
let output = cli.run_command();
assert!(output.contains("Has data"));
}
}
I now can resolve my issue with assert_cmd crate, some of my tests
mod tests {
use assert_cmd::Command;
#[test]
fn valid_domain() {
let mut cmd = Command::cargo_bin("example").unwrap();
let output = cmd.arg("google.com").unwrap();
let output_str = String::from_utf8(output.stdout).unwrap();
assert!(output_str.contains("Has data"));
}
#[test]
#[should_panic(expected = "Invalid domain")]
fn invalid_domain() {
Command::cargo_bin("example").unwrap().arg("google").unwrap();
}
}
Upvotes: 0
Views: 142
Reputation: 27538
You can invoke the parser with Cli::from_iter(["yourbinary", "your", "arguments"])
but after that you're on your own since structopt
only provides commandline parsing.
It's probably best to split main
into testable functions/methods, if you go by your wish API something like
impl Cli {
fn run_command(&self) -> String {
todo!() // your business logic
}
}
and use that in the tests and in main
instead of the code you currently have.
Upvotes: 2