如何对命令行界面进行单元测试

时间:2013-02-01 10:19:34

标签: unit-testing language-agnostic command-line-interface

我编写了一个我想测试的命令行工具(我不打算从命令行运行单元测试)。我想将一组特定的输入选项映射到特定的输出。我还没有找到任何现有的工具。该应用程序只是一个二进制文件,可以用任何语言编写,但它接受POSIX选项并写入标准输出。

有些事情:

  • 对于每组已知的输入选项:
    1. 使用指定的输入启动应用程序。
    2. 管道输出到文件。
    3. 将输出差异输出到存储的(所需)输出。
    4. 如果diff不为空,则记录错误。

(顺便说一句,这就是你所说的集成测试而不是单元测试?)

编辑:我知道如何为此编写自己的工具,我不需要代码的帮助。我想学的是如果已经完成的话。

5 个答案:

答案 0 :(得分:5)

DejaGnu是一个用于为CLI程序编写测试套件的成熟且有些标准的框架。

以下是从此tutorial获取的示例测试:

# send a string to the running program being tested:
send "echo Hello world!\n"

# inspect the output and determine whether the test passes or fails:
expect {
    -re "Hello world.*$prompt $" {
        pass "Echo test"
    }
    -re "$prompt $" {
        fail "Echo test"
    }
    timeout {
        fail "(timeout) Echo test"
    }
}

除非您的需求非常简单,否则使用这样一个完善的框架从长远来看可能会比您自己提出的更好。

答案 1 :(得分:4)

您正在寻找BATS(Bash自动测试系统): https://github.com/bats-core/bats-core

来自文档:

example.bats contains
#!/usr/bin/env bats

@test "addition using bc" {
  result="$(echo 2+2 | bc)"
  [ "$result" -eq 4 ]
}  

@test "addition using dc" {
  result="$(echo 2 2+p | dc)"
  [ "$result" -eq 4 ]
}


$ bats example.bats

 ✓ addition using bc
 ✓ addition using dc

2 tests, 0 failures

答案 2 :(得分:0)

好吧,我认为每种语言都应该有一种执行外部过程的方法。

在C#中,您可以执行以下操作:

var p = new Process();
p.StartInfo = new ProcessStartInfo(@"C:\file-to-execute.exe");
... //You can set parameters here, etc.
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.UseShellExecute = false;
p.Start();

//To read the standard output:
var output = p.StandardOutput.ReadToEnd();

我从来没有写过标准输入,但我相信也可以通过访问p.StandardInput来完成。我们的想法是将两个输入视为Stream个对象,因为它们就是这样。

在Python中有subprocess模块。根据其文件:

  

子进程模块允许您生成新进程,连接到它们的输入/输出/错误管道,并获取它们的返回代码。

在为几个月前编写的编译器的代码生成部分编写单元测试时,我必须这样做:Writing unit tests in my compiler (which generates IL)

答案 3 :(得分:0)

我们编写了should,这是一个用于测试任何CLI工具的单文件Python程序。默认用法是检查输出的一行是否包含某种模式。从文档中:

# A .should file launches any command it encounters.
echo "hello, world"

# Lines containing a `:` are test lines.
# The `test expression` is what is found at the right of the `:`.
# Here 'world' should be found on stdout, at least in one line.
:world

# What is at the left of the `:` are modifiers.
# One can specify the exact number of lines where the test expression has to appear.
# 'moon' should not be found on stdout.
0:moon

应该可以检查出现次数,查找正则表达式,使用变量,过滤器测试,解析json数据并检查退出代码。

答案 4 :(得分:-3)

当然,已经完成了数千次。但编写一个工具来运行简单的shell脚本或批处理文件就像你提出的那样是一项微不足道的任务,几乎不值得尝试转变为通用工具。