Как мне выполнить модульное тестирование консольного класса ввода? - PullRequest
3 голосов
/ 21 августа 2009

В одном из моих приложений у меня есть класс, который отвечает за ввод данных пользователем. Метод ввода по умолчанию - консоль (клавиатура), и я хочу написать для него несколько модульных тестов, чтобы убедиться, что это правильно.

Я рассматриваю возможность использования google-test фреймворка для моего модульного тестирования, который позволяет легко автоматизировать все тестирование. Однако я не уверен, как мне автоматизировать тестирование ввода с консоли.

Есть ли способ имитировать пользовательский ввод с клавиатуры? Или я должен вручную ввести свой тестовый ввод? Или, возможно, перенаправить stdin (либо в коде, либо по каналу при запуске модульного теста)?

РЕДАКТИРОВАТЬ: я планирую использовать GNU readline для ввода данных пользователем. На данный момент я не вижу способа перенаправить поток ввода этой библиотеки - возможно, кто-то еще имеет опыт с этим?

Ответы [ 7 ]

3 голосов
/ 21 августа 2009

По сути, ваш класс должен иметь возможность использовать произвольный входной поток, а не только стандартный ввод (и вы должны его реорганизовать, если он пока не может).

После этого вы сможете просто создать фиктивный поток со своими пользовательскими данными и смоделировать любой пользовательский ввод.

3 голосов
/ 21 августа 2009

Вы можете использовать ожидать .

1 голос
/ 21 августа 2009

Я планирую использовать GNU readline для ввода пользователя. На данный момент я не могу увидеть любой способ перенаправить ввод поток этой библиотеки

Создайте абстрактный класс с членами, которые соответствуют функциональности readline, которую вы хотите использовать. Программируйте этот абстрактный класс вместо прямого API readline. Используйте внедрение зависимостей , чтобы получить экземпляр этого класса для кода, который нуждается в этом.

Затем вы можете создать две реализации этого класса: одну, которая просто оборачивает библиотеку readline, и другую фиктивную реализацию, которую вы можете использовать в своих тестах модулей. В фиктивной реализации были бы дополнительные члены, облегчающие имитацию пользователя.

1 голос
/ 21 августа 2009

Если ваша платформа .NET, вот один из способов сделать это .

1 голос
/ 21 августа 2009

Макет ввода.

0 голосов
/ 21 августа 2009

Для консоли я всегда просто оборачиваю ее своей собственной реализацией.

Использование оболочки и интерфейса для всех сторонних элементов управления, участвующих в модульных тестах, делает работу с изолированной средой (например, 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();
}
0 голосов
/ 21 августа 2009

Для .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() {}
}
...