英文:
How to write tests for command line tool built with structopt
问题
以下是您要求的翻译:
所以我用 `structopt` 构建了一个小型的 Rust 命令行工具,现在想添加一些测试,但未找到任何有用的文档或示例来编写它。
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(())
}
我即将编写类似于以下的测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid_domain() {
// 示例函数
let cli = Cli::build_command(domain: "google.com");
let output = cli.run_command();
assert!(output.contains("Has data"));
}
}
现在我可以使用 [assert_cmd][1] crate 解决我的问题,以下是一些我的测试
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();
}
}
[1]: https://docs.rs/assert_cmd/latest/assert_cmd/
英文:
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();
}
}
答案1
得分: 2
你可以使用Cli::from_iter(["yourbinary", "your", "arguments"])
来调用解析器,但在那之后,你需要自己处理,因为structopt
仅提供命令行解析。
最好将main
拆分为可测试的函数/方法,如果你按照你的API愿望,可以像这样做:
impl Cli {
fn run_command(&self) -> String {
todo!() // 你的业务逻辑
}
}
然后在测试和main
中使用它,而不是当前的代码。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论