c# - visual - xunit




Puis-je écrire dans la console dans un test unitaire? Si oui, pourquoi la fenêtre de la console n'est pas ouverte? (7)

J'ai un projet de test dans Visual Studio. J'utilise Microsoft.VisualStudio.TestTools.UnitTesting.

J'ajoute cette ligne dans un de mes tests unitaires:

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

Quand j'exécute le test, le test passe mais la fenêtre de la console n'est pas ouverte du tout.

Y at-il un moyen de rendre la fenêtre de la console disponible pour interagir via un test unitaire?


Ce n'est pas une solution, mais une approche du livre

l'art des tests unitaires par Roy Osherove

nous avons besoin de stubs pour casser ces dépendances, comme écrire sur FileSystem ou écrire dans le journal des événements ou écrire dans la console -

Stub peut être passé dans la classe principale et si stub n'est pas nul, écrire dans Stub. Cependant, il peut changer l'API (comme maintenant constructeur a un stub comme paramètre). L'autre approche hérite et crée un objet Mock. qui est décrit ci-dessous.

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

Comme indiqué, les tests unitaires sont conçus pour fonctionner sans interaction.

Cependant, vous pouvez déboguer des tests unitaires, comme n'importe quel autre code. La manière la plus simple consiste à utiliser le bouton Déboguer dans l'onglet Résultats du test.

Etre capable de déboguer signifie être capable d'utiliser des points d'arrêt. Etre capable d'utiliser des points d'arrêt, donc, signifie être capable d'utiliser Tracepoints , ce que je trouve extrêmement utile dans le débogage quotidien.

Essentiellement, les points de trace vous permettent d'écrire dans la fenêtre de sortie (ou, plus précisément, dans la sortie standard). En option, vous pouvez continuer à courir, ou vous pouvez vous arrêter comme un point d'arrêt régulier. Cela vous donne la "fonctionnalité" que vous demandez, sans avoir besoin de reconstruire votre code, ou de le remplir avec des informations de débogage.

Ajoutez simplement un point d'arrêt, puis cliquez avec le bouton droit sur ce point d'arrêt. Sélectionnez l'option "When Hit ...":

Ce qui amène le dialogue:

Quelques choses à noter:

  1. Notez que le point d'arrêt est maintenant montré comme un diamant, au lieu d'une sphère, indiquant un point de trace
  2. Vous pouvez afficher la valeur d'une variable en l'entourant comme {this}.
  3. Décochez la case "Continuer l'exécution" pour que le code se casse sur cette ligne, comme n'importe quel point d'arrêt normal
  4. Vous avez la possibilité d'exécuter une macro. S'il vous plaît soyez prudent - vous pouvez provoquer des effets secondaires nocifs.

Voir la documentation pour plus de détails.


Debug.WriteLine () peut également être utilisé.


Il existe plusieurs façons d'écrire une sortie à partir d'un test unitaire Visual Studio en C #:

  • Console.Write - Le harnais de test de Visual Studio capturera ceci et l'affichera lorsque vous sélectionnez le test dans l'Explorateur de test et que vous cliquerez sur le lien Sortie. Ne s'affiche pas dans la fenêtre de sortie de Visual Studio lors de l'exécution ou du débogage d'un test unitaire (il s'agit sans doute d'un bogue).
  • Debug.Write - Le harnais de test Visual Studio capturera ceci et l'affichera dans la sortie du test. Apparaît dans la fenêtre Visual Studio Output lors du débogage d'un test unitaire, à moins que les options Visual Studio Debugging ne soient configurées pour rediriger Output vers la fenêtre Immediate. Rien n'apparaîtra dans la fenêtre Sortie (ou Immédiate) si vous exécutez simplement le test sans débogage. Par défaut uniquement disponible dans une version Debug (c'est-à-dire lorsque la constante DEBUG est définie).
  • Trace.Write - Le harnais de test Visual Studio capturera ceci et l'affichera dans la sortie du test. Apparaît dans la fenêtre Visual Studio Output (ou Immediate) lors du débogage d'un test unitaire (mais pas lors de l'exécution du test sans débogage). Par défaut disponible dans les versions Debug et Release (c'est-à-dire lorsque la constante TRACE est définie).

Confirmé dans Visual Studio 2013 Professional.


Remarque: la réponse d'origine ci-dessous devrait fonctionner pour n'importe quelle version de VS jusqu'à VS2012. VS2013 ne semble plus avoir de fenêtre de résultats de test. Au lieu de cela, si vous avez besoin d'une sortie spécifique au test, vous pouvez utiliser la suggestion de Trace.Write() de @ Stretch pour écrire la sortie à écrire dans la fenêtre de sortie.

La méthode Console.Write n'écrit pas dans la "console" - elle écrit dans tout ce qui est connecté au handle de sortie standard pour le processus en cours d'exécution. De même, Console.Read lit l'entrée de tout ce qui est connecté à l'entrée standard.

Lorsque vous exécutez un test unitaire via VS2010, la sortie standard est redirigée par le faisceau de test et stockée en tant que partie de la sortie de test. Vous pouvez le voir en cliquant avec le bouton droit sur la fenêtre Test Results et en ajoutant la colonne "Output (StdOut)" à l'affichage. Cela montrera tout ce qui a été écrit sur stdout.

Vous pouvez ouvrir manuellement une fenêtre de console en utilisant P / Invoke comme l'indique @ sinni800. À la lecture de la documentation AllocConsole , il apparaît que la fonction réinitialisera les poignées stdin et stdout pour pointer vers la nouvelle fenêtre de la console. (Je ne suis pas sûr à 100% à ce sujet, ça me semble un peu faux si j'ai déjà redirigé stdout pour Windows pour me le voler, mais je n'ai pas essayé.)

En général, cependant, je pense que c'est une mauvaise idée; Si tout ce que vous voulez utiliser pour la console est de vider plus d'informations sur votre test unitaire, la sortie est là pour vous. Continuez à utiliser Console.WriteLine comme vous êtes et vérifiez les résultats de sortie dans la fenêtre Résultats des tests quand c'est fait.


Tout d'abord, les tests unitaires sont, par conception , censés fonctionner complètement sans interaction.

Cela mis à part, je ne pense pas qu'il y ait une possibilité à laquelle on pensait.

Vous pouvez essayer de pirater avec AllocConsole P / Invoke qui ouvrira une console même si votre application actuelle est une application graphique. La classe Console affichera ensuite sur la console maintenant ouverte.


Vous pouvez utiliser cette ligne pour écrire dans la fenêtre de sortie de Visual Studio:

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

J'espère que cela pourra aider





console-application