Как использовать консоль или терминал внутри метода модульного тестирования в C # Visual Studio 2019 для отображения вывода и получения ввода от пользователя? - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь написать код, который будет подсказывать пользователю и спрашивать, какие тестовые файлы они хотят протестировать (мне нужно иметь возможность тестировать различные входящие файлы клиентов, и все файлы начинаются с имени клиента). Затем я хочу переместить файлы, которые соответствуют тому, что пользователь дал, в папку, где созданные мной модульные тесты могут их взять и запустить на них. У меня возникают проблемы с отображением консоли, даже когда вызывается функция Console.writeLine () (что, очевидно, тогда я не могу ничего ввести в консоль в ответ на то, что должно было отображаться на консоли).

Я пытался использовать тег [ClassInitialize] и вызывать методы, которые запрашивают пользователя внутри этого тегового метода. Я попытался также вызвать те же самые методы в верхней части моего метода модульного тестирования ([TestMethod]), который тоже не работал. Я знаю, что вывод будет в разделе «Открыть дополнительный вывод для этого результата» в проводнике тестов, но это мне не поможет.

    [TestMethod]
    public void CompareModels()
    {
        Console.WriteLine("Please enter customer that you want to test: ");
        var userInput = Console.ReadLine();
        var testFiles = Directory.GetFiles("my test file directory");
        foreach(var file in testFiles)
        {
            if(file.Contain(userInput)
                File.Move(file, "my in testing directory");
        }
    }

Я ожидал, что консоль будет отображаться в первой строке кода, но это не так, и программа ждет на консоли бесконечно. ReadLine (), потому что я не могу ввести какой-либо ввод в консолиэто не появитсяЯ также хотел бы добавить, что если пользователь ничего не вводит в течение нескольких секунд, то тесты будут выполняться с файлами, которые находятся в каталоге «in testing». Таким образом, пользователь может изменить тестируемого клиента, не перемещая файлы вручную, или просто запустить тесты, и они сделают за них всю работу.

1 Ответ

1 голос
/ 07 ноября 2019

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

public interface IFileService
{
    string[] GetFiles(string path);
    void Move(string sourceFileName, string destFileName);
}

Реализация логики с внедренной службой:

public class FileMover
{
    private readonly IFileService _fileService;

    public FileMover(IFileService fileService)
    {
        _fileService = fileService;
    }

    public void MoveFiles(string sourceDir, string destinationDir, string filterText)
    {
        string[] testFiles = _fileService.GetFiles(sourceDir);
        foreach (string file in testFiles) {
            if (file.Contains(filterText)) {
                _fileService.Move(file, destinationDir);
            }
        }
    }
}

Выможно использовать фальшивые рамки для создания тестовых манекенов. Они автоматически создают инструментированный класс из интерфейса, который вы можете настроить для работы. Манекен автоматически считает вызовы методов и регистрирует их параметры, возвращает то, что вы настроили и т. Д.

Тест без консоли:

[TestMethod]
public void CompareModels()
{
    // Arrange
    IFileService fileService = Substitute.For<IFileService>();
    //TODO: setup fileService Dummy.

    var sut = new FileMover(fileService); // sut stands for Service Under Test.
    string sourceDir = @"C:\Test\Source";
    string destDir = @"C:\Test\Destination";
    string userInput = "abcd";

    // Act
    sut.MoveFiles(sourceDir, destDir, userInput);

    // Assert
    //TODO: test whether the fileService methods have been called as expected.
}

В реальном приложении консоли:

var fileService = new RealFileService();
var mover = new FileMover(fileService);

Console.WriteLine("Please enter customer that you want to test: ");
string userInput = Console.ReadLine();
mover.MoveFiles("my test file directory", "my in testing directory", userInput);

Если вы сделаете это, следовательно, вы захотите использовать Внедрение зависимости контейнер. Для этого вам нужно определить все ваши сервисы через интерфейс.

public interface IFileMover
{
    void MoveFiles(string sourceDir, string destinationDir, string filterText);
}

public class FileMover : IFileMover
{
    ...
}

Установить контейнер DI:

var diContainer = new SomeDependencyInjectionContainer();
diContainer.Register<IFileService, RealFileService>();
diContainer.Register<IFileMover, FileMover>();

Контейнер DI автоматически распознает и создает сервисы, которые он должен внедрить черезконструкторТаким образом, вы можете просто создать файл-движок с помощью

var mover = diContainer.Resolve<IFileMover>();

A RealFileService, который будет автоматически введен.

...