我的Java应用程序由两部分组成:
- 核心库(类,接口等)
- 命令行界面(CLI),它使用核心库
对于第一部分,我使用JUnit进行单元测试,但是对于第二部分,你会怎么做呢?
如何为命令行界面创建自动化测试?
我的Java应用程序由两部分组成:
对于第一部分,我使用JUnit进行单元测试,但是对于第二部分,你会怎么做呢?
如何为命令行界面创建自动化测试?
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 中读取数据,因此您可以简单地实例化它并测试各个方法。
首先,测试正确清理原始输入是否正确,您可以通过编写 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]);
}
接下来,我们可以通过监控标准输出来测试单个命令方法。我在这里找到了一个方法(链接):
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());
}
out
,然后在测试结束时将旧控制台设置回去。@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
:#!/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
命令执行时,输出结果如下:$ bats example.bats
✓ addition using bc
✓ addition using dc
2 tests, 0 failures
查看相关标签以获取更多问题: bats-core