在我的一个应用程序中,我有一个负责用户输入的类。输入的默认方法是控制台(键盘),我想为它编写一些单元测试以确保它是正确的。
我正在考虑使用google-test框架进行单元测试,这样可以轻松实现所有测试的自动化。但是,我不确定如何自动测试控制台输入。
有没有办法模拟键盘上的用户输入?或者我是否必须手动输入我的测试输入?或者可能重定向stdin
(在运行单元测试时代码或管道)?
编辑:我打算使用GNU readline进行用户输入。目前我看不到任何方法来重定向此库的输入流 - 也许其他人有这方面的经验?
答案 0 :(得分:3)
您可以使用expect。
答案 1 :(得分:3)
基本上,你的类应该能够使用随机输入流,而不仅仅是stdin(你必须重构它,如果它还没有)。
之后,您将能够简单地将模拟流与您的自定义数据放在一起,并模拟任何用户输入。
答案 2 :(得分:1)
模拟输入。
答案 3 :(得分:1)
如果您的平台是.NET,here's one way to do it。
答案 4 :(得分:1)
我打算使用GNU readline 用于用户输入。目前我做不到 看到任何重定向输入的方法 这个图书馆的流
创建一个抽象类,其成员与您要使用的readline功能相匹配。针对此抽象类而不是直接针对readline API进行编程。使用dependency injection将此类的实例获取到需要它的代码。
然后,您可以创建此类的两个实现:一个简单地包装readline库,另一个模拟实现可以在单元测试中使用。模拟实现将有额外的成员,可以很容易地模拟用户。
答案 5 :(得分:0)
对于.NET / C#,您可以使用此问题中的Options类或变体。因为您将所有命令映射到委托,然后您可以在委托结束时对每个方法进行单元测试,并轻松找到未知命令:
MyHandler handler = new MyHandler()
CommandOptions options = new CommandOptions();
// Put this in the test Setup
options.Add("show", handler.Show)
.Add("connect", v => handler.Connect(v))
.Add("dir", handler.Dir);
if (!options.Parse(args))
Assert.Fail(string.Format("{0} was not recognised.",args))
MyHandler类类似于:
public class MyHandler
{
public void Show() { }
public void Connect(string[] args){}
public void Dir() {}
}
答案 6 :(得分:0)
对于控制台,我总是用自己的实现来包装它。
对单元测试中涉及的所有第三方控件使用包装器和接口,使得使用隔离框架(如Rhino Mocks)非常容易。它让我可以控制测试,并在我的代码中明确定义了依赖性。由于我需要控制台的新功能,我可以将它们添加到包装器界面。我还没有接口膨胀的问题......
public interface IConsoleShim
{
void WriteLine(string message);
ConsoleKeyInfo ReadKey();
}
public class ConsoleShim : IConsoleShim
{
public void WriteLine(string message)
{
Console.WriteLine(message);
}
public ConsoleKeyInfo ReadKey()
{
return Console.ReadKey();
}
}
这是一个实际的测试
[NUnit.Framework.Test]
public void Run_writes_to_console_100_times_waits_for_keypress()
{
// arrange
Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();
IConsoleShim consoleMock = mocks.StrictMock<IConsoleShim>();
Program program = new Program(consoleMock);
int expected = 100;
// VerifyAll automatically called
Rhino.Mocks.With.Mocks(mocks).Expecting(() =>
{
Rhino.Mocks.Expect.Call(() => consoleMock.WriteLine("")).IgnoreArguments().Repeat.Times(expected);
Rhino.Mocks.Expect.Call(consoleMock.ReadKey()).Return(new ConsoleKeyInfo());
});
//act
program.Run();
}