it-swarm.com.de

Kann ich bei einem Komponententest in die Konsole schreiben? Wenn ja, warum wird das Konsolenfenster nicht geöffnet?

Ich habe ein Testprojekt in Visual Studio. Ich verwende Microsoft.VisualStudio.TestTools.UnitTesting.

Ich füge diese Zeile in einem Unit-Test hinzu:

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

Wenn ich den Test starte, wird der Test bestanden, aber das Konsolenfenster wird überhaupt nicht geöffnet.

Gibt es eine Möglichkeit, das Konsolenfenster für die Interaktion über einen Komponententest verfügbar zu machen?

109
pencilCake

HINWEIS: Die ursprüngliche Antwort unten sollte für alle Versionen von VS bis VS2012 funktionieren. VS2013 scheint kein Fenster mit Testergebnissen mehr zu haben. Wenn Sie eine testspezifische Ausgabe benötigen, können Sie stattdessen den @ Stretch-Vorschlag von Trace.Write() verwenden, um die Ausgabe in das Ausgabefenster zu schreiben.


Die Console.Write -Methode schreibt nicht in die "Konsole" - sie schreibt in alles, was mit dem Standardausgabe-Handle für den laufenden Prozess verbunden ist. In ähnlicher Weise liest Console.Read die Eingabe von allem, was mit der Standardeingabe verbunden ist.

Wenn Sie einen Komponententest über VS2010 ausführen, wird die Standardausgabe vom Testkabelbaum umgeleitet und als Teil der Testausgabe gespeichert. Sie können dies anzeigen, indem Sie mit der rechten Maustaste auf das Fenster "Testergebnisse" klicken und der Anzeige die Spalte "Ausgabe (StdOut)" hinzufügen. Dies zeigt alles an, was an stdout geschrieben wurde.

Sie könnten manuell ein Konsolenfenster mit P/Invoke öffnen, wie @ sinni800 sagt. Aus der AllocConsole Dokumentation geht hervor, dass die Funktion die Handles stdin und stdout zurücksetzt, um auf das neue Konsolenfenster zu verweisen. (Da bin ich mir nicht hundertprozentig sicher. Es scheint mir falsch, wenn ich bereits stdout umgeleitet habe, damit Windows es mir stiehlt, aber ich habe es nicht versucht.)

Im Allgemeinen halte ich es jedoch für eine schlechte Idee; Wenn Sie die Konsole nur verwenden möchten, um weitere Informationen zu Ihrem Komponententest zu erhalten, ist die Ausgabe für Sie da. Verwenden Sie Console.WriteLine so wie Sie sind, und überprüfen Sie die Ausgabeergebnisse im Fenster Testergebnisse, wenn Sie fertig sind.

115

Jemand kommentierte diese offenbar neue Funktionalität in VS2013. Ich war mir nicht sicher, was er zuerst meinte, aber jetzt, wo ich das tue, denke ich, dass es seine eigene Antwort verdient.

Wir können Console.WriteLine normal verwenden und die Ausgabe wird angezeigt, nicht im Ausgabefenster, sondern in einem neuen Fenster, nachdem wir in den Testdetails auf "Ausgabe" geklickt haben.

 enter image description here

133
Tiago Duarte

Sie können diese Zeile verwenden, um in Output Window des Visual Studio zu schreiben:

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

Hoffentlich hilft das

28
Dmitry Pavlov

Wie bereits erwähnt, sind Unit-Tests so konzipiert, dass sie ohne Interaktion laufen.

Sie können Unit-Tests jedoch genauso wie jeden anderen Code debuggen. Am einfachsten ist es, die Schaltfläche Debuggen auf der Registerkarte Testergebnisse zu verwenden.

Debugging heißt, Breakpoints verwenden zu können. Breakpoints verwenden zu können bedeutet, Tracepoints verwenden zu können, was ich im täglichen Debugging sehr nützlich finde.

Im Wesentlichen können Sie mit Tracepoints in das Ausgabefenster schreiben (oder genauer in die Standardausgabe). Optional können Sie weiterlaufen oder wie ein normaler Haltepunkt anhalten. Dadurch erhalten Sie die "Funktionalität", nach der Sie fragen, ohne dass Sie den Code neu erstellen oder mit Debug-Informationen füllen müssen.

Fügen Sie einfach einen Haltepunkt hinzu und klicken Sie dann mit der rechten Maustaste auf diesen Haltepunkt. Wählen Sie die Option "When Hit ...": When Hit option

Welcher Dialog erscheint: When Breakpoint Is Hit

Ein paar Dinge zu beachten:

  1. Beachten Sie, dass der Haltepunkt jetzt als Raute angezeigt wird, anstelle einer Kugel, die einen Trace-Punkt anzeigt 
  2. Sie können den Wert einer Variablen ausgeben, indem Sie sie wie folgt einfügen: {this}. 
  3. Deaktivieren Sie das Kontrollkästchen "Continue Execution" (Ausführung fortsetzen), damit der Code in dieser Zeile wie ein normaler Haltepunkt unterbrochen wird 
  4. Sie haben die Möglichkeit, ein Makro auszuführen. Bitte seien Sie vorsichtig - Sie können schädliche Nebenwirkungen verursachen.

Weitere Informationen finden Sie in der Dokumentation.

26
Wonko the Sane

Es gibt mehrere Möglichkeiten, die Ausgabe eines Visual Studio-Komponententests in C # zu schreiben:

  • Console.Write - Der Visual Studio-Test-Kabelsatz erfasst dies und zeigt es an, wenn Sie den Test im Test-Explorer auswählen und auf den Link Ausgabe klicken. Wird not im Visual Studio-Ausgabefenster angezeigt, wenn ein Komponententest ausgeführt oder debuggt wird (dies ist wahrscheinlich ein Fehler).
  • Debug.Write - Der Visual Studio-Test-Kabelsatz erfasst dies und zeigt es in der Testausgabe. Wird beim Debuggen eines Komponententests im Visual Studio-Ausgabefenster angezeigt, es sei denn, die Debugging-Optionen von Visual Studio sind so konfiguriert, dass die Ausgabe in das Direktfenster umgeleitet wird. Wenn Sie den Test einfach ohne Debugging ausführen, wird im Ausgabefenster (oder im Direktfenster) nichts angezeigt. Standardmäßig nur in einem Debug-Build verfügbar (dh, wenn die DEBUG-Konstante definiert ist).
  • Trace.Write - Das Testpaket von Visual Studio erfasst dies und zeigt es in der Testausgabe. Wird im Debuggen eines Komponententests im Visual Studio-Ausgabefenster (oder im Direktfenster) angezeigt (nicht jedoch beim einfachen Ausführen des Tests ohne Debugging). Standardmäßig in Debug- und Release-Builds verfügbar (dh, wenn die TRACE-Konstante definiert ist).

Bestätigt in Visual Studio 2013 Professional.

18
yoyo

Sie können verwenden

Trace.WriteLine() 

zum Schreiben in das Ausgabefenster beim Debuggen eines Tests. 

5
Sturla

In Visual Studio 2017 zeigt "TestContext" den Ausgabe-Link nicht im Test Explorer an. Trace.Writeline () zeigt jedoch die Ouput-Verknüpfung. 

3
naz hassan

Zunächst sollen Unit-Tests von design vollständig ohne Interaktion ablaufen.

Abgesehen davon glaube ich nicht, dass an eine Möglichkeit gedacht wurde. 

Sie könnten versuchen, mit AllocConsole P/Invoke zu hacken, um eine Konsole zu öffnen, selbst wenn Ihre aktuelle Anwendung eine GUI-Anwendung ist. Die Console-Klasse wird dann an die jetzt geöffnete Konsole gesendet.

2
sinni800

Genau das ist keine Lösung, sondern ein Ansatz aus dem Buch der 

art of Unit Testing von Roy Osherove

wir brauchen Stubs, um diese Abhängigkeiten zu durchbrechen, wie das Schreiben in das Dateisystem oder das Schreiben in das Ereignisprotokoll oder das Schreiben in die Konsole. 

Stub könnte an die Hauptklasse übergeben werden, und wenn Stub nicht null ist, schreiben Sie in Stub. Es kann jedoch die API ändern (wie jetzt hat Konstruktor einen Stub als Parameter). Der andere Ansatz ist das Erben und Erstellen eines Scheinobjekts. was unten beschrieben wird.

    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 () kann ebenfalls verwendet werden.

1
Jackie

Die IMHO-Ausgabenachricht ist in den meisten Fällen nur für den Fall eines fehlgeschlagenen Tests relevant. Ich habe das folgende Format erstellt, Sie können auch Ihr eigenes Format erstellen. Dies wird im VS Test Explorer-Fenster selbst angezeigt. 

Wie wird diese Nachricht im VS Test Explorer-Fenster ausgegeben? Ein Beispielcode wie dieser sollte funktionieren.

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.");

Sie können eine eigene Klasse für Sie einrichten. Ich hoffe es hilft!

0
DevCod

Visual Studio für Mac

Keine der anderen Lösungen funktionierte mit VS für Mac

Wenn Sie NUnit verwenden, können Sie Ihrer Lösung einen kleinen .NETKonsolenprojekt hinzufügen. Verweisen Sie dann auf das Projekt, das Sie testen möchten, in Referenzen dieses neuen Objekts Konsolenprojekt.

Was auch immer Sie in Ihren [Test()]-Methoden getan haben, können Sie in der Main der Konsolen-App auf folgende Weise ausführen:

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}");
    }
}

Unter diesen Umständen können Sie Console.Write und Console.WriteLine in Ihrem Code verwenden.

0
SwiftArchitect