Java 如何测试命令行界面(CLI)?

Java 如何测试命令行界面(CLI)?,java,testing,command-line-interface,bats-core,Java,Testing,Command Line Interface,Bats Core,我的Java应用程序由两部分组成: 核心库(类、接口等) 命令行界面(CLI),它使用核心库 1。我使用JUnit进行单元测试,但是你会为2做什么呢 如何为命令行界面创建自动测试?使用Apache commons exec从Java程序执行命令 我遇到了完全相同的问题,在这里着陆,但没有找到好的答案,所以我想我会发布我最终找到的解决方案,作为将来在这里着陆的任何人的起点 我是在CLI之后编写测试的(我知道,这让我感到羞耻),所以首先我要确保CLI是以可测试的方式编写的。它看起来是这样的(我省略了

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

  • 核心库(类、接口等)
  • 命令行界面(CLI),它使用核心库
  • 1。我使用JUnit进行单元测试,但是你会为2做什么呢


    如何为命令行界面创建自动测试?

    使用Apache commons exec从Java程序执行命令


    我遇到了完全相同的问题,在这里着陆,但没有找到好的答案,所以我想我会发布我最终找到的解决方案,作为将来在这里着陆的任何人的起点

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

    继续测试
    CLI
    不是公共图书馆的一部分,因此应保护它不受图书馆用户的影响。如上所述,您可以使用默认的访问修饰符将其设置为包私有。这使您的测试能够完全访问该类(只要它们在同一个包中),同时仍能保护它,所以这就是问题所在

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

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

    @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]);
    }
    
    覆盖某些边缘情况也很容易:

    @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来测试invidual命令方法。我这样做了(我发现):

    换句话说,将JVM的
    out
    替换为您可以在练习前查询的内容,然后将旧控制台设置回测试的拆卸中

    当然,CLI应用程序通常不仅仅是打印到控制台。假设您的程序将信息保存到文件中,您可以对其进行测试(从JUnit 4.7开始):


    JUnit将负责创建有效文件并在测试运行结束时将其删除,让您可以自由测试CLI方法是否正确处理了该文件。

    对于CLI,请尝试BATS(Bash自动测试系统):

    从文档中:

    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
    

    是的,Apache Commons Exec确实执行程序。那么如何使用它测试CLI呢?海报上说他们的应用程序是Java的。
    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());
    }
    
    @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);
        }
    }
    
    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