Могу ли я писать на консоль в unit test? Если да, то почему окно консоли не открывается?

У меня есть тестовый проект в Visual Studio. Я использую Microsoft.VisualStudio.TestTools.UnitTesting.

Я добавляю эту строку в один из моих модульных тестов:

Console.WriteLine("Some foo was very angry with boo");
Console.ReadLine();

Когда я запускаю тест, проходит тест, но консольное окно вообще не открывается.

Есть ли способ сделать доступным окно консоли доступным через unit test?

Ответ 1

ПРИМЕЧАНИЕ. Исходный ответ ниже должен работать для любой версии VS до VS2012. VS2013 больше не имеет окна результатов теста. Вместо этого, если вам нужен специфичный для теста вывод, вы можете использовать @Stretch с предложением Trace.Write() чтобы записать вывод в окно вывода.


Метод Console.Write не записывает данные в "консоль" - он записывает все, что подключено к стандартному дескриптору вывода для запущенного процесса. Точно так же Console.Read читает ввод из того, что подключено к стандартному вводу.

Когда вы запускаете модульное тестирование через VS2010, стандартный вывод перенаправляется тестовым жгутом и сохраняется как часть тестового вывода. Это можно увидеть, щелкнув правой кнопкой мыши окно "Результаты теста" и добавив столбец с именем "Выход (StdOut)" на дисплей. Это покажет все, что было написано на стандартный вывод.

Вы можете вручную открыть окно консоли, используя P/Invoke, как говорит @sinni800. Из прочтения документации AllocConsole выясняется, что функция сбросит дескрипторы stdin и stdout чтобы они указывали на новое окно консоли. (Я не уверен на 100% в этом; мне кажется, что это неправильно, если я уже перенаправил стандартный stdout для Windows, чтобы украсть его у меня, но я не пытался.)

В общем, я думаю, что это плохая идея; если все, для чего вы хотите использовать консоль, - это выгрузить больше информации о вашем модульном тесте, вывод для вас. Продолжайте использовать Console.WriteLine как вы, и проверьте результаты вывода в окне Результаты теста, когда это будет сделано.

Ответ 2

Кто-то прокомментировал эту, по-видимому, новую функциональность в VS2013. Я не был уверен, что он имел в виду в первую очередь, но теперь, когда я это делаю, я думаю, что он заслуживает этого собственного ответа.

Мы можем использовать Console.WriteLine нормально, и выводится вывод, просто не в окне "Выход", а в новом окне после того, как мы нажимаем "Выход" в деталях теста.

введите описание изображения здесь

Ответ 3

Вы можете использовать эту строку для записи в Окно вывода в Visual Studio:

System.Diagnostics.Debug.WriteLine("Matrix has you...");

Надеюсь, что поможет

Ответ 4

Как указано, модульные тесты предназначены для работы без взаимодействия.

Тем не менее, вы можете отлаживать модульные тесты, как и любой другой код. Самый простой способ - использовать кнопку "Отладка" на вкладке "Результаты теста".

Возможность отладки означает возможность использования контрольных точек. Таким образом, возможность использовать точки останова означает возможность использовать Tracepoints, который я считаю чрезвычайно полезным при ежедневной отладке.

По существу, Tracepoints позволяют вам записывать в окно Output (или, точнее, стандартный вывод). При желании вы можете продолжить выполнение, или вы можете остановиться, как обычная точка останова. Это дает вам "функциональность", которую вы просите, без необходимости перекомпоновки кода или заполнения его отладочной информацией.

Просто добавьте точку останова, а затем щелкните правой кнопкой мыши на этой точке останова. Выберите опцию "When Hit...": When Hit option

Что вызывает диалог: When Breakpoint Is Hit

Несколько замечаний:

  • Обратите внимание, что точка останова теперь отображается как алмаз вместо сферы, указывающая точку трассировки
  • Вы можете вывести значение переменной, заключая ее как {this}.
  • Снимите флажок "Продолжить выполнение", чтобы перерыв кода в этой строке, как и любая обычная точка останова
  • У вас есть возможность запуска макроса. Будьте осторожны - вы можете вызывать вредные побочные эффекты.

Подробнее см. документацию.

Ответ 5

Существует несколько способов записи вывода из Visual Studio unit test в С#:

  • Console.Write. Жгут проводов Visual Studio захватит это и покажет его, когда вы выберете тест в Проводнике тестирования и нажмите ссылку "Вывод". Не отображается в окне вывода Visual Studio при запуске или отладке unit test (возможно, это ошибка).
  • Debug.Write - тестовая проводка Visual Studio захватит это и покажет его в тестовом выпуске. Появляется в окне вывода Visual Studio при отладке unit test, если параметры Visual Studio Debugging не настроены для перенаправления вывода в окно Immediate. В окне Output (или Immediate) ничего не появится, если вы просто запустите тест без отладки. По умолчанию доступно только в сборке Debug (то есть, когда определена константа DEBUG).
  • Trace.Write - тестовая проводка Visual Studio захватит это и покажет его в тестовом выпуске. Появляется в окне вывода Visual Studio (или Immediate) при отладке unit test (но не при простом тестировании без отладки). По умолчанию доступно как в сборках Debug, так и в Release (т.е. При определении константы TRACE).

Подтверждено в Visual Studio 2013 Professional.

Ответ 6

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

Trace.WriteLine() 

для записи в окно вывода при отладке unittest.

Ответ 7

В Visual Studio 2017 "TestContext" не показывает выходную ссылку в Test Explorer. Тем не менее, Trace.Writeline() показывает ссылку Ouput.

Ответ 8

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

С этим в стороне, я не думаю, что есть такая возможность, о которой думали.

Вы можете попробовать взломать AllocConsole P/Invoke, который откроет консоль, даже если ваше текущее приложение является графическим приложением. Затем класс Console отправляется в открытую консоль.

Ответ 9

Также можно использовать Debug.WriteLine().

Ответ 10

Это точно не решение, а подход из книги

искусство юнит-тестирования Роя Ошерова

нам нужны заглушки для разрыва этих зависимостей, такие как запись в FileSystem или запись в журнал событий или запись в консоль -

Заглушка может быть передана в основной класс, и если заглушка не равна нулю, тогда пишите заглушку. Однако это может изменить API (как сейчас конструктор имеет заглушку в качестве параметра). Другой подход заключается в наследовании и создании фиктивного объекта. который описан ниже.

    namespace ClassLibrary1
    {
       // TO BE TESTED
        public class MyBusinessClass
        {
            ConsoleStub myConsoleForTest;
            public MyBusinessClass()
            {
                // Constructor
            }

            // This is test stub approach - 2
            public MyBusinessClass(ConsoleStub console)
            {
                this.myConsoleForTest = console;
            }

            public virtual void MyBusinessMethod(string s)
            {
                // this needs to be unit tested
                Console.WriteLine(s);

                // Just an example - you need to be creative here
                // there are many ways 
                if (myConsoleForTest !=null){
                    myConsoleForTest.WriteLine(s);
                }
            }
        }

        public class ConsoleStub
        {
            private string textToBeWrittenInConsole;

            public string GetLastTextWrittenInConsole
            {
                get
                {
                    return this.textToBeWrittenInConsole;
                }
            }

            public void WriteLine(string text)
            {
                this.textToBeWrittenInConsole = text;
            }
        } 


        public class MyBusinessClassMock :MyBusinessClass
        {
            private ConsoleStub consoleStub;
            public MyBusinessClassMock()
            {
                // Constructor
            }

            public MyBusinessClassMock(ConsoleStub stub)
            {
                this.consoleStub = stub;
            }

            public override void MyBusinessMethod(string s)
            {
                // if MOCK is not an option then pass this stub 
                // as property or parameter in constructor 
                // if you do not want to change the api  still want
                // to pass in main class then , make it protected and 
                // then inherit it and make just a property for consoleStub

                base.MyBusinessMethod(s);
                this.consoleStub.WriteLine(s);
            }
        }

        [TestClass]
        public class ConsoleTest
        {
            private ConsoleStub consoleStub;
            private MyBusinessClassMock  mybusinessObj

            [TestInitialize]
            public void Initialize()
            {
               consoleStub = new ConsoleStub();
               mybusinessObj = new MyBusinessClassMock(consoleStub);
            }
            [TestMethod]
            public void TestMyBusinessMethod()
            {
                mybusinessObj.MyBusinessMethod("hello world");
                Assert.AreEqual(this.consoleStub.GetLastTextWrittenInConsole,"hello world" );
            }
        }

    }

// Approach - 2 
[TestClass]
    public class ConsoleTest
    {
        private ConsoleStub consoleStub;
        private MyBusinessClass  mybusinessObj

        [TestInitialize]
        public void Initialize()
        {
           consoleStub = new ConsoleStub();
           mybusinessObj = new MyBusinessClass(consoleStub);
        }
        [TestMethod]
        public void TestMyBusinessMethod()
        {
            mybusinessObj.MyBusinessMethod("hello world");
            Assert.AreEqual(this.consoleStub.GetLastTextWrittenInConsole,"hello world" );
        }
    }

Ответ 11

Visual Studio для Mac

Ни одно из других решений не работало на VS для Mac

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

Все, что вы делали в своих методах [Test()] можно сделать в Main приложении консоли следующим образом:

class MainClass
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Console");

        // Reproduce the Unit Test
        var classToTest = new ClassToTest();
        var expected = 42;
        var actual = classToTest.MeaningOfLife();
        Console.WriteLine($"Pass: {expected.Equals(actual)}, expected={expected}, actual={actual}");
    }
}

Вы можете использовать Console.Write и Console.WriteLine в своем коде при таких обстоятельствах.

Ответ 12

Выводное сообщение IMHO в большинстве случаев относится только к неудачному тесту. Я составил следующий формат, вы можете сделать свой собственный тоже. Это отображается в самом окне VS Test Explorer.

Как скинуть это сообщение в VS Test Explorer Window? Пример кода, как это должно работать.

if(test_condition_fails)
    Assert.Fail(@"Test Type: Positive/Negative.
                Mock Properties: someclass.propertyOne: True
                someclass.propertyTwo: True
                Test Properties: someclass.testPropertyOne: True
                someclass.testPropertyOne: False
                Reason for Failure: The Mail was not sent on Success Task completion.");

Вы можете иметь отдельный класс, посвященный этому для вас. Надеюсь, поможет!