创建一个`std :: env :: Args`迭代器进行测试

时间:2017-11-22 18:05:53

标签: unit-testing rust parameter-passing

Rust中是否有办法从std::env::Args创建Vec<String>以便在#[test]函数中使用它?

我希望测试一个以std::env::Args为参数的函数,但我不知道如何使用我为测试提供的参数列表创建这样的对象。

我无法从文档,来源或谷歌搜索中找到这个。

3 个答案:

答案 0 :(得分:9)

std::env::Args的字段未记录,并且似乎不是公共函数来创建具有自定义字段的字段。所以,你在那里运气不好。

但是因为它只是&#34; 对进程参数的迭代器,为每个参数产生String&#34;您的函数可以使用String迭代器或Vec,而不会丢失任何功能或类型安全性。由于它只是String的列表,因此任意将函数限制为恰好来自命令行的字符串并没有多大意义。

浏览Rust's own tests,这就是他们的所作所为。有很多let args: Vec<String> = env::args().collect();

甚至an example in 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人员如何处理这个问题。

答案 1 :(得分:2)

@Schwern's answer很好,它使我想到了这个简单的版本。由于std::env::ArgsIterator实现了Item = String,所以您可以这样做:

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());
}

要进行测试,请在parse上向String提供迭代器:

#[test]
fn test_parse() {
   let args = ["arg1", "arg2"].iter().map(|s| s.to_string());
   parse(args);
}

答案 2 :(得分:0)

基于@Rossman's answer(因此也基于@Schwern's answer,我已经写了一个小宏来简化此操作:谢谢!)

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上尝试一下。

我还不是防锈专家,非常欢迎您提出任何建议:)