我正在努力使bash中的交互式命令行Java程序自动化,以验证该程序为输入产生了正确的输出(基本上是bash中的穷人单元测试)。
例如,如果我有一个Java程序要求用户输入其全名,然后仅输出其名字,则它应如下所示:
Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)
用户输入“ John Doe”的位置。
运行此命令的简单bash命令如下所示:
OUTPUT=`echo "John Doe" | java NameReader`
Run Code Online (Sandbox Code Playgroud)
要么
OUTPUT=`java NameReader <<< "John Doe"`
Run Code Online (Sandbox Code Playgroud)
两者的麻烦在于$ OUTPUT现在包含以下内容:
Enter your name: John
Run Code Online (Sandbox Code Playgroud)
因为发送到stdin的文本(及其伴随的换行符)不会像我们在控制台中看到的那样在程序的输出中复制。
理想情况下,$ OUTPUT将包含以下内容:
Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)
但是我可以忍受这个:
Enter your name:
John
Run Code Online (Sandbox Code Playgroud)
(输入被完全省略,但是输出如预期的那样在新行中)
bash中是否有一种方法(不更改底层的Java程序)来获取被输送到stdin的文本,也可以在Java程序读取的“时间”将其输送到stdout,因此捕获了完整的交互式会话?
(另一个注意事项:一些搜索表明spawn / expect命令可能会有所帮助,但是将在其上运行的系统似乎没有可用的命令)
您可以使用以下script
命令
script -q -c "java NameReader" log.txt
Run Code Online (Sandbox Code Playgroud)
这将java NameReader
在log.txt
文件中记录命令的输入和输出。
如果你的java程序是这样的:
import java.util.Scanner;
class A {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(sc.next());
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以构建一个 bash 脚本来解析表单的输入
Enter your name: John
John Doe
Run Code Online (Sandbox Code Playgroud)
将其转变为
Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)
这是一种可能的 bash 脚本:
#!/bin/bash
arg1Outpt=`eval "$1"`
javaOut=`echo "$arg1Outpt" | eval "$2"`
#prints Enter your name: John\nJohn Doe
echo "${javaOut}"$'\n'"${arg1Outpt}" |
sed 'N; s/\(Enter your name: \)\(.*\)\(\n\)\(.*\)/\1\4\3\2/'
#and this is a multiline sed(man sed) that transforms your
#input into what you want :)
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
bash pipeCheat.bash 'echo "john doe"' 'java A'
Run Code Online (Sandbox Code Playgroud)
其中,pipeCheat.bash 是保存上述脚本的文件的名称。
如果您有疑问,请随时提问。