如何在 Rust 中使用 clap 测试 CLI 参数?

问题描述 投票:0回答:1

使用

clap
为 CLI 程序编写测试的最惯用方法是什么?我目前正在这样做:

#[derive(Debug, Parser)]
#[clap(author, version, about)]
pub struct StructArgs {
    #[clap(subcommand)]
    pub command_type: CommandType,
}

#[derive(Debug, Subcommand)]
pub enum CommandType {
    Command1(Command1Args),
    ...
}

#[derive(Debug, Args)]
pub struct Command1Args {
    pub field: String,
    ...
}

impl Command1Args {
    ...
}

#[test]
fn test_do_stuff() {
    let args = StructArgs::try_parse_from(
        std::iter::once("<PROGRAM NAME>")
        .chain(
            ["<ARG 1>", ..., "<ARG n>"]
            .iter()
            .cloned()
        )
    );

    if let CommandType::Command1(command1_args) = args.command_type {
        // do stuff with command1_args
    } else {
        panic!();
    }
}

基本上,我传递给

clap
一个参数迭代器,然后检查解析的命令结构是否与我期望的
CommandType
匹配,然后继续测试其方法和内部状态。 else 分支中的
panic
表示如果由于某种原因我得到意外的
CommandType
,则测试失败,这意味着很可能我在迭代器中写了错误的内容。

这个可以进一步改进吗?

testing rust command-line-interface clap
1个回答
0
投票

Chayim 说你不应该测试 Clap 确实有道理。但在某些情况下情况并非如此,为使用 clap 实现的 CLI 解析器编写单元测试确实有意义。

就我而言,我想定义一组参数,仅当设置了某个标志时才需要这些参数,如果设置了,则需要该组的所有参数。在 Clap 中定义这并不是一件小事,测试它是有意义的,例如像这样(使用 Clap 4.4):

#[cfg(test)]
mod tests {

  use super::*;

  #[test]
  fn oidc_all_or_nothing() {
    /* Call it without any OIDC args, just graqphiql; must work */
    if let Err(err) = AppConfig::try_parse_from(vec!["aisrv", "--enable-graphiql"].iter()) {
      panic!("Just --enable-graphiql failed: {err}");
    }

    /* Call with only one OIDC arg, must fail */
    if AppConfig::try_parse_from(vec!["aisrv", "--oidc-idp-url", "tescht"].iter()).is_ok() {
      panic!("Just one OIDC arg did not fail!");
    }

    /* Call with all OIDC args, must succeed */
    if let Err(err) = AppConfig::try_parse_from(
      vec![
        "aisrv",
        "--oidc-idp-url",
        "tescht",
        "--oidc-super-admin-user",
        "tescht",
        "--oidc-super-admin-password",
        "tescht",
        "--oidc-super-admin-client-id",
        "tescht",
        "--oidc-super-admin-client-secret",
        "tescht",
        "--oidc-aud",
        "tescht",
      ]
      .iter(),
    ) {
      panic!("All OIDC args passed, but still fails: {err}");
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.