it-swarm.com.ru

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

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

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

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

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

Есть ли способ сделать окно консоли доступным для взаимодействия через юнит-тест?

109
pencilCake

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


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

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

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

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

107
Michael Edenfield

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

Мы можем использовать Console.WriteLine в обычном режиме, и вывод отображается, но не в окне «Вывод», а в новом окне после того, как мы щелкнули «Вывод» в подробностях теста.

 enter image description here

133
Tiago Duarte

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

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

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

28
Dmitry Pavlov

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

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

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

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

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

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

Несколько вещей, на которые стоит обратить внимание:

  1. Обратите внимание, что точка останова теперь отображается в виде ромба, а не сферы, указывая точку трассировки 
  2. Вы можете вывести значение переменной, заключив его в {this}. 
  3. Снимите флажок «Продолжить выполнение», чтобы в этой строке был разрыв кода, как в любой обычной точке останова. 
  4. У вас есть возможность запустить макрос. Пожалуйста, будьте осторожны - вы можете вызвать вредные побочные эффекты.

Смотрите документацию для более подробной информации.

26
Wonko the Sane

Есть несколько способов записать вывод из модульного теста Visual Studio в C #:

  • Console.Write - тестовый жгут Visual Studio захватит это и покажет, когда вы выберете тест в Test Explorer и нажмете ссылку Output. не появляется в окне вывода Visual Studio при запуске или отладке модульного теста (возможно, это ошибка).
  • Debug.Write - тестовый жгут Visual Studio захватит это и покажет в результатах теста. Отображается ли в окне вывода Visual Studio при отладке модульного теста, если только параметры отладки Visual Studio не настроены на перенаправление вывода в окно непосредственного доступа. Ничего не появится в окне «Вывод» (или «Немедленно»), если вы просто запустите тест без отладки. По умолчанию доступно только в сборке отладки (то есть, когда определена константа DEBUG).
  • Trace.Write - тестовый жгут Visual Studio захватит это и покажет в результатах теста. Есть появляется в окне вывода (или немедленного) Visual Studio при отладке модульного теста (но не при простом запуске теста без отладки). По умолчанию доступно в сборках Debug и Release (то есть, когда определена константа TRACE).

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

18
yoyo

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

Trace.WriteLine() 

записать в окно вывода при отладке юнит-теста. 

5
Sturla

В Visual Studio 2017 «TestContext» не отображает ссылку «Вывод» в Test Explorer. Однако Trace.Writeline () показывает ссылку Ouput. 

3
naz hassan

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

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

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

2
sinni800

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

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

нам нужны заглушки для разрыва этих зависимостей, такие как запись в 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" );
        }
    }
1
dekdev

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

1
Jackie

Выводное сообщение 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.");

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

0
DevCod

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 в вашем коде при таких обстоятельствах.

0
SwiftArchitect