2011-08-21 10 views
22

Ho appena iniziato a testare xUnit.net, ma non sembra che sia in grado di acquisire alcun output (Console, Debug, Trace), come mi sarei aspettato.xUnit.net non acquisisce l'output della console

È possibile? Sto usando un esempio di libreria di classi .NET 4.0 con xUnit.net 1.8.

risposta

3

In generale, è una brutta strada da percorrere per fare affidamento sulla registrazione dei test e. Il pass/fail dovrebbe essere il risultato dei test. E semplicemente non dovrebbero arrivare al punto in cui ci sono abbastanza cose in corso che sarà necessario guardare una traccia.

Il xunit.gui.exe mostra l'output di console e traccia, xunit.console.exe no. Se è importante, puoi collegare un TraceListener che reindirizza a un file facendo le appropriate voci di configurazione .NET standard (c 'è un FileWriterTraceListener che dovresti riuscire ad agganciare se lo fai su Google).


UPDATE: Come discusso in his blog post, Damian Hickey ha un buon esempio di un possibile sostituto - registrazione cablaggio al xUnit 2 ITestOutputHelper come dimostrato in https://github.com/damianh/CapturingLogOutputWithXunit2AndParallelTests/blob/master/src/Lib.Tests/Tests.cs

UPDATE 2: In alcuni casi, si può aggiungere registrazione e mangimi per l'ITestOutputHelper senza coinvolgere LogContext utilizzando un semplice adattatore come segue (ho solo in F #, sorry):

// 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 differenza w con questo approccio contro l'uso del contesto di log è che il logging al Serilog Logger globale non viene prelevato.

+1

Grazie per la vostra risposta. Stavo usando xunit.console.exe. Sono consapevole che non è una buona soluzione, e non era proprio l'uso previsto. Il motivo per cui avevo bisogno era di eseguire il debug di alcune operazioni sulle stringhe durante la creazione di una nuova classe usando TDD. – kfuglsang

+0

Personalmente, in questo caso, dovrei semplicemente impostare xunit.console.exe come progetto di avvio nel debugger. BTW TeamCity e altri ambienti di esecuzione simili raccolgono il risultato del test mentre stai cercando –

+0

@downvoter Perché? (A proposito di V2, c'è un lavoro programmato per fermare i dati in deglutizione ...) –

2

C'è una soluzione come si trova qui: https://xunit.codeplex.com/discussions/211566

Basta aggiungere questo al vostro costruttore o il metodo in cui si desidera eseguire il debug di uscita:

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

Per coloro che effettuano il tuning in seguito, questa non è più una pratica consigliata. Vedi http://xunit.github.io/docs/capturing-output.html. –

+4

Oh uomo quei ragazzi xunit, se non è abbastanza complicato non è xunit -.- Ofc non c'è IMessageSink su .Net Core .... MsTestV2 in soccorso! – MushyPeas

24

La situazione è cambiata un po 'con xUnit.net 2. So che la domanda riguarda una versione precedente, ma poiché le persone arriveranno qui dopo aver eseguito l'aggiornamento, ho pensato che valesse la pena indicarlo.

Per vedere un qualche tipo di uscita in uscita di test nella versione 2 è necessario prendere una dipendenza nella classe di test (tramite un argomento del costruttore) su un'istanza di ITestOutputHelper, quindi utilizzare il metodo WriteLine su questa interfaccia . Es .:

public class MyTestSpec 
{ 
    private readonly ITestOutputHelper _testOutputHelper; 

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

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

Si può scegliere per collegare il quadro di registrazione a questa interfaccia, forse iniettando un ILog implementazione che ha inoltrato tutte le chiamate a ITestOutpuHelper.

Riconosco che non vorrai farlo di default, ma a scopi diagnostici di tanto in tanto può essere molto utile. Questo è particolarmente vero dove i test falliscono solo su alcuni server di test basati su cloud &!

+1

A proposito, ITestOutputHelper si trova nello spazio dei nomi Xunit.Abstractions. – Syndog

+0

[codice di esempio ufficiale] (https://github.com/xunit/samples.xunit/blob/master/TestOutputExample/Example.cs). Funziona ancora su progetti core .NET. – zwcloud

+0

E se avessi già un'istanza dell'oggetto personalizzata (ad esempio 'MyDatabaseFixture') passata in questo costruttore MyTestSpec invece di' ITestOutputHelper'? –

1

Questo può aiutare se il Console.Write è incorporato in fondo in fondo un po 'di gerarchia di classi che non si desidera di refactoring:

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); 
     } 
    } 
Problemi correlati