Question xUnit.net ne capture pas la sortie de la console


Je viens de commencer à tester xUnit.net, mais il ne semble pas capturer de sortie (Console, Debug, Trace), comme je l’aurais prévu.

Est-ce possible? J'utilise un exemple de bibliothèque de classes .NET 4.0 avec xUnit.net 1.8.


24
2017-08-21 14:42


origine


Réponses:


En général, il est difficile de se fier à l’abattage et tests. Le succès / échec devrait être le résultat des tests. Et ils ne devraient tout simplement pas arriver au stade où il se passe suffisamment de choses pour examiner une trace.

le xunit.gui.exe affiche la sortie console et trace, xunit.console.exe ne fait pas. Si c'est important, vous pouvez connecter un TraceListener qui redirige vers un fichier en créant des entrées de configuration .NET standard appropriées (Theres 'a FileWriterTraceListener que vous devriez pouvoir connecter si vous le google).


MISE À JOUR: Comme discuté dans son blog, Damian Hickey a un bon exemple de substitut possible - la connexion de câblage à la xUnit 2 ITestOutputHelper comme démontré dans https://github.com/damianh/CapturingLogOutputWithXunit2AndParallelTests/blob/master/src/Lib.Tests/Tests.cs

MISE À JOUR 2: Dans certains cas, on peut ajouter une journalisation et l’alimenter ITestOutputHelper sans impliquer LogContext en utilisant un adaptateur simple comme suit (je l'ai seulement dans F #, désolé):

// Requirement: Make SUT depend on Serilog NuGet
// Requirement: Make Tests depend on Serilog.Sinks.Observable

type TestOutputAdapter(testOutput : Xunit.Abstractions.ITestOutputHelper) =
    let formatter = Serilog.Formatting.Display.MessageTemplateTextFormatter(
        "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}", null);
    let write logEvent =
        use writer = new System.IO.StringWriter()
        formatter.Format(logEvent, writer);
        writer |> string |> testOutput.WriteLine
    member __.Subscribe(source: IObservable<Serilog.Events.LogEvent>) =
        source.Subscribe write

let createLogger hookObservers =
    LoggerConfiguration()
        .WriteTo.Observers(Action<_> hookObservers)
        .CreateLogger()
let createTestOutputLogger (output: ITestOutputHelper) =
    let adapter = TestOutputAdapter testOutputHelper
    createLogger (adapter.Subscribe >> ignore)

type Tests(testOutputHelper) =
    let log = createTestOutputLogger testOutputHelper

    [<Fact>] let feedToSut () =
        // TODO pass log to System Under Test either as a ctor arg or a method arg

La différence avec cette approche par rapport au contexte du journal est que la connexion au Serilog global [contextualisé] Logger ne sera pas ramassé.


3
2017-08-23 10:13



La situation a un peu changé avec xUnit.net 2. Je sais que la question concerne une version antérieure, mais comme les gens vont atterrir ici après avoir effectué la mise à niveau, j'ai pensé que cela valait la peine de le signaler.

Pour voir une sorte de sortie dans la sortie de test de la version 2, vous devrez prendre une dépendance dans votre classe de test (via un argument constructeur) sur une instance de ITestOutputHelper, puis utilisez le WriteLine méthode sur cette interface. Par exemple.:

public class MyTestSpec
{
  private readonly ITestOutputHelper _testOutputHelper;

  public MyTestSpec(ITestOutputHelper testOutputHelper)
  {
    _testOutputHelper = testOutputHelper;
  }

  [Fact]
  public void MyFact()
  {
    _testOutputHelper.WriteLine("Hello world");
  }
}

Vous pouvez choisir de connecter votre framework de journalisation à cette interface, peut-être en injectant une ILog mise en œuvre qui transfère tous les appels à ITestOutpuHelper.

Je reconnais que vous ne voudrez pas faire cela par défaut, mais à des fins de diagnostic de temps en temps, cela peut être très utile. Cela est particulièrement vrai lorsque vos tests échouent uniquement sur un serveur de génération et de test basé sur le cloud!


30
2018-06-25 16:06



Cela peut être utile si votre Console.Write est intégré dans une hiérarchie de classes que vous ne souhaitez pas modifier:

    public MyTestClass(ITestOutputHelper output)
    {
        var converter = new Converter(output);
        Console.SetOut(converter);
    }

    private class Converter : TextWriter
    {
        ITestOutputHelper _output;
        public Converter(ITestOutputHelper output)
        {
            _output = output;
        }
        public override Encoding Encoding
        {
            get { return Encoding.Whatever; }
        }
        public override void WriteLine(string message)
        {
            _output.WriteLine(message);
        }
        public override void WriteLine(string format, params object[] args)
        {
            _output.WriteLine(format, args);
        }
    }

3
2017-11-28 10:34



Il existe une solution telle que trouvée ici: https://xunit.codeplex.com/discussions/211566

Ajoutez simplement ceci à votre constructeur ou à votre méthode où vous voulez déboguer la sortie:

Debug.Listeners.Add(new DefaultTraceListener());

2
2018-04-18 22:38



Il peut être utile de partager mon expérience ici:

Dans un nouveau projet (avec les anciennes bibliothèques), j'ai essayé xUnit. Il est célèbre et même l'équipe de langage C # l'utilise, alors ça doit être cool. Et je frappe le problème de sortie de la console très rapidement. Au début, j'étais très confus pourquoi je n'ai pas obtenu les sorties de la console. Ils ont bien fonctionné dans NUnit ou MSTest.

J'ai lu les documents de xUnit, et j'ai trouvé que ses auteurs avaient une forte opinion: la sortie de la console dans les tests est mauvaise. D'ACCORD. Je vois leur point de vue, mais je ne suis pas tout à fait d’accord, en particulier dans de nombreux projets du monde réel, qui mêlent souvent héritage et piratage. Heureusement, ils ont fourni le ITestOutputHelpersolution ou solution de contournement? C'est un passe-temps d'écrire, mais bon, je les ai écrites.

J'ai alors obtenu des résultats, hein ... Et les autres? Oh oui, le code d'installation unique, qui était maintenant dans class fixtures. Donc j'ai aussi injecté ITestOutputHelper là et courir. Et j'ai une erreur, il ne peut pas instancier la classe de fixture. Alors, ITestOutputHelper n'est pas supporté là.

Hmm ... Je peux mettre en cache la sortie de la phase d'installation et les écrire à l'intérieur des tests plus tard, mais ils seront ensuite produits une fois par test. Je peux écrire une fonction pour utiliser un indicateur de variable statique, de manière à n'écrire qu'une seule fois, mais cela apparaît comme la sortie du premier test, au lieu du niveau d'assemblage. Donc, un peu aléatoire, difficile à trouver. Et le pire problème est la sortie console de une fois déchirer n'a nulle part où sortir.

O ... K ... Laisse-moi le laisser pour l'instant. Et j'ai continué mon voyage. Ensuite, j'ai dû faire face à quelques cas de tests nécessitant un ordre d'exécution dédié. Oui, je sais que ce n'est pas cool. Mais il y a des cas, en particulier dans certains tests d'intégration, c'est le moyen le plus simple et le plus naturel de le faire. Cela peut être aussi simple que d'ajouter un [Order()] attribut dans NUnit ou création d'un test ordonné dans MSTest. Mais je suis allé à docs xUnit, seulement pour le trouver non pris en charge, même si les documents fournissent un exemple de code de projet pour étendre et ajouter cette fonctionnalité.

Donc, contrairement à NUnit / MSTest, xUnit est un outil de choix. Il est difficile de faire du mal (selon ses auteurs). Si vous avez besoin des fonctionnalités que xUnit ne fournit pas, comme moi, ce n’est pas le bon outil pour vous.


0
2018-06-03 14:27