[英]Creating an `std::env::Args` iterator for testing
Rust 有没有办法从Vec<String>
创建std::env::Args
以便在#[test]
函数中使用它?
我希望测试一个将std::env::Args
作为参数的函数,但我不知道如何使用我为测试提供的参数列表创建这样一个对象。
我无法从文档、来源或 Google 搜索中找出这一点。
std::env::Args
的字段没有记录,并且似乎没有公共函数来创建具有自定义字段的字段。 所以,你运气不好。
但由于它只是“对进程参数的迭代器,为每个参数产生一个String
值”,因此您的函数可以采用String
迭代器或Vec
而不会丢失任何功能或类型安全性。 由于它只是一个String
列表,因此将您的函数任意限制为碰巧来自命令行的字符串并没有多大意义。
查看Rust 自己的测试,这就是他们所做的。 有很多let args: Vec<String> = env::args().collect();
在rustbuild
中甚至有一个例子,他们rustbuild
程序的名称,只提供参数列表。
use std::env;
use bootstrap::{Config, Build};
fn main() {
let args = env::args().skip(1).collect::<Vec<_>>();
let config = Config::parse(&args);
Build::new(config).build();
}
bootstrap::Config::parse()
看起来像这样:
impl Config {
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
...
我不是 Rust 专家,但这似乎是 Rust 人员处理问题的方式。
@Schwern 的回答很好,它让我找到了这个更简单的版本。 由于std::env::Args
使用Item = String
实现Iterator
,您可以这样做:
use std::env;
fn parse<T>(args: T)
where
T: Iterator<Item = String>,
{
for arg in args {
// arg: String
print!("{}", arg);
}
}
fn main() {
parse(env::args());
}
要进行测试,您可以通过String
上的迭代器提供parse
:
#[test]
fn test_parse() {
let args = ["arg1", "arg2"].iter().map(|s| s.to_string());
parse(args);
}
我已经写了一个小宏来简化这一过程的基础上, @罗斯曼的答案(因此也是基于@ Schwern拥有的答案;要感谢两者):
macro_rules! make_string_iter {
($($element: expr), *) => {
{
let mut v = Vec::new();
$( v.push(String::from($element)); )*
v.into_iter()
}
};
}
它可以这样使用:
macro_rules! make_string_iter {
($($element: expr), *) => {
{
let mut v = Vec::new();
$( v.push(String::from($element)); )*
v.into_iter()
}
};
}
// We're using this function to test our macro
fn print_args<T: Iterator<Item = String>>(args: T) {
for item in args {
println!("{}", item);
}
}
fn main() {
// Prints a, b and c
print_args(make_string_iter!("a", "b", "c"))
}
或者在Rust Playground上尝试一下。
我(还)不是 Rust 专家,非常欢迎任何建议:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.