首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何测试命令行接口(CLI)?

如何测试命令行接口(CLI)?
EN

Stack Overflow用户
提问于 2014-12-14 17:59:53
回答 2查看 7.9K关注 0票数 7

我的Java应用程序由两部分组成:

  1. 核心库(类、接口等)
  2. 命令行接口(CLI),它使用核心库

对于1.我使用JUnit进行单元测试,但是对于2您会做什么呢?

如何为命令行接口创建自动化测试?

EN

回答 2

Stack Overflow用户

发布于 2015-07-24 11:00:04

我有同样的问题,降落在这里,没有找到一个好的答案,所以我想我会张贴我最终找到的解决方案,作为一个起点,任何人谁在这里降落在未来。

我在CLI之后编写了我的测试(我知道这是我的耻辱),所以我首先确保CLI是以可测试的方式编写的。它看起来像这样(我省略了异常处理,并简化了很多,以使它更易读):

代码语言:javascript
复制
public class CLI {

    public static void main(String... args) {
        new CLI(args).startInterface();
    }

    CLI(String... args) {
        System.out.println("Welcome to the CLI!");
        // parse args, load resources, etc
    }

    void startInterface() {
        BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String[] input = sanitiseInput(consoleReader.readLine());

            if (input[0].equalsIgnoreCase("help") {
                help();
            } else if (input[0].equalsIgnoreCase("exit") {
                break;
            } else if (input[0].equalsIgnoreCase("save") {
                save(input);
            } else {
                System.out.println("Unkown command.");
            }
        }
    }

    String[] sanitiseInput(String rawInput) {
        // process the input and return each part of it in order in an array, something like:
        return rawInput.trim().split("[ \t]+");
    }

    void help() {
        // print help information
        System.out.println("Helpful help.");
    }

    void save(String[] args) {
        // save something based on the argument(s)
    }
}

继续测试。CLI不是公共图书馆的一部分,因此应该保护它不受图书馆用户的影响。正如前面提到的这里,您可以使用默认的访问修饰符使它成为私有包。这使您的测试能够在仍然保护类的同时对类进行完全访问(只要它们在同一个包中),所以这就是所处理的。

为CLI接受的每个命令编写一个方法,可以让JUnit测试几乎完美地模拟用户输入。由于对象在调用startInterface()之前不会从stdin读取,所以只需实例化它并测试各个方法。

首先,测试原始输入是否被正确清理是很好的,您可以通过为JUnit编写sanitiseInput()测试来实现这一点。我写了这样的测试:

代码语言:javascript
复制
@Test
public void commandAndArgumentsSeparatedBySpaces() throws Exception {
    String[] processedInput = uut.sanitiseInput("command argument1 argument2");

    assertEquals("Wrong array length.", 3, processedInput.length);
    assertEquals("command", processedInput[0]);
    assertEquals("argument1", processedInput[1]);
    assertEquals("argument2", processedInput[2]);
}

也很容易涵盖一些边缘情况:

代码语言:javascript
复制
@Test
public void leadingTrailingAndIntermediaryWhiteSpace() throws Exception {
    String[] processedInput = uut.sanitiseInput("  \t  this   \twas \t  \t  a triumph  \t\t    ");

    assertEquals("Wrong array length.", 4, processedInput.length);
    assertEquals("this", processedInput[0]);
    assertEquals("was", processedInput[1]);
    assertEquals("a", processedInput[2]);
    assertEquals("triumph", processedInput[3]);
}

接下来,我们可以通过监视stdout来测试invididual命令方法。我做了这个(我找到了这里):

代码语言:javascript
复制
private CLI uut;
private ByteArrayOutputStream testOutput;
private PrintStream console = System.out;
private static final String EOL = System.getProperty("line.separator");

@Before
public void setUp() throws Exception {
    uut = new CLI();
    testOutput = new ByteArrayOutputStream();
}

@Test
public void helpIsPrintedToStdout() throws Exception {
    try {
        System.setOut(new PrintStream(testOutput));
        uut.help();
    } finally {
        System.setOut(console);
    }
    assertEquals("Helpful help." + EOL, testOutput.toString());
}

换句话说,用您可以在练习之前查询的内容替换JVM的out,然后在测试的解压中设置旧的控制台。

当然,CLI应用程序通常所做的不仅仅是打印到控制台。如果您的程序将信息保存到一个文件中,您可以这样测试它(从JUnit 4.7开始):

代码语言:javascript
复制
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();

@Test
public void informationIsSavedToFile() throws Exception {
    File testFile = tempFolder.newFile();
    String expectedContent = "This should be written to the file.";

    uut.save(testFile.getAbsolutePath(), expectedContent);

    try (Scanner scanner = new Scanner(testFile)) { 
        String actualContent = scanner.useDelimiter("\\Z").next();
        assertEquals(actualContent, expectedContent);
    }
}

JUnit将负责创建一个有效的文件并在测试结束时删除它,让您可以自由地测试它是否被CLI方法正确处理。

票数 11
EN

Stack Overflow用户

发布于 2015-12-29 01:55:08

对于任何CLI,您都可以使用(自动测试系统)

文档中的测试规范是一个类似于example.bats的脚本文件。

代码语言:javascript
复制
#!/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命令执行和输出时,如下所示:

代码语言:javascript
复制
$ bats example.bats

 ✓ addition using bc
 ✓ addition using dc

2 tests, 0 failures

有关更多问题,请参见相关标记:蝙蝠核

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27472270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档