Estendi xUnit.NET per utilizzare il codice personalizzato durante l'elaborazione di una classe e l'individuazione dei metodi di prova

StackOverflow https://stackoverflow.com/questions/488121

  •  20-08-2019
  •  | 
  •  

Domanda

Sono un grande fan del framework xUnit.NET; Lo trovo leggero, semplice, pulito ed estensibile.

Ora diciamo che ho una lezione del genere:

public class AdditionSpecification
{
  static int result;

  public void Because()
  {
    result = 2 + 2;
  }

  public void Result_is_non_zero()
  {
    Assert.True(result <> 0);
  }

  public void Result_is_correct()
  {
    Assert.Equal(4, result);
  }
}

Con la classe di test sopra voglio che xUnit.NET veda 2 casi di test ed esegua il metodo because () prima di ognuno di essi.

Lasciando da parte eventuali problemi che potresti avere con i miei nomi di classe o metodo, la struttura di questo test / specifica, il framework xUnit.NET o BDD, ecco la mia domanda:

Come posso dire a xUnit.NET che desidero personalizzare il modo in cui identifica ed esegue i metodi di test fuori da questa classe senza usando un attributo personalizzato simile a [Fact] su ogni test target metodo?

So che posso derivare da BeforeAfterAttribute per decorare ogni metodo di test con personalizzazione prima e dopo l'esecuzione. Come posso farlo a livello di classe? Devo scrivere un corridore personalizzato?

È stato utile?

Soluzione 2

Quindi risulta che stavo cercando il metodo ITestClassCommand.EnumerateTestMethods ().

  1. Il runner di prova xUnit.NET predefinito itererà su tutte le classi in il tuo gruppo di prova.
  2. Per ognuno controllerà un RunWithAttribute; questa è la tua occasione per scavalcare il Implementazione ITestClassCommand che viene utilizzato per identificare i metodi test contenenti. (RunWithNUnit è un buon esempio)
  3. ITestClassCommand.EnumerateTestMethods () viene chiamato per elaborare la classe di test e restituire un IEnumerable di metodi di test.
  4. ogni test IMethodInfo viene quindi passato a ITestClassCommand.EnumerateTestCommands (IMethodInfo testMethod) per ottenere l'IEnumerable di ITestCommands
  5. ciascun ITestCommand viene quindi eseguito e viene data la possibilità di restituire un risultato.

Nel caso del mio esempio sopra, avrei bisogno di qualcosa del tipo:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RunWithMyTestClassCommandAttribute : RunWithAttribute
{
   public RunWithMyTestClassCommandAttribute()
               : base(typeof(MyTestClassCommand)) {}
}

Quindi potrei decorare il mio esempio sopra con:

[RunWithMyTestClassCommand]
public class AdditionSpecification
{
  static int result;

  public void Because()
  {
    result = 2 + 2;
  }

  public void Result_is_non_zero()
  {
    Assert.True(result <> 0);
  }

  public void Result_is_correct()
  {
    Assert.Equal(4, result);
  }
}

Infine, in MyTestClassCommand, ho l'opportunità tra EnumerateTestMethods () e EnumerateTestCommands (IMethodInfo testMethod) di utilizzare la logica che voglio individuare e costruire istanze ITestCommand che vengono eseguite come test individuali.

A proposito, nel processo di ricerca di questo problema, ho riscontrato un piccolo bug nel framework xUnit.NET in cui un IMethodInfo personalizzato generato da EnumerateTestMethods () non è mai apparso in EnumerateTestCommands (..) perché veniva scartato e riavvolto dal test runner o da una delle sue fabbriche.

Ho inviato questo problema al progetto xUnit su codeplex e è stato corretto il 30 maggio , 2009 per xUnit.NET 1.5 CTP 2

Altri suggerimenti

IUseFixture di xUnit.net ti permette di fare per configurazione del dispositivo. È quindi possibile definire la propria classe di dispositivi:

public class AdditionFixture : IDisposable
{
  public int Because() 
  {
    return 2 + 2;
  }

  public void Dispose()
  {
   //test tear down code
  }      
}

La tua classe di test può quindi implementarlo (con setFixture che richiede l'implementazione):

public class AdditionSpecification : IUseFixture<AdditionFixture>
{
  int result;

  public void SetFixture(AdditionFixture Fixture)
  {
   result = Fixture.Because();
  }

  [Fact]
  public void Result_is_non_zero()
  {
   Assert.True(result <> 0);
  }

  [Fact]
  public void Result_is_correct()
  {
   Assert.Equal(4, result);
  }
}

Il corridore xUnit creerà una singola istanza del dispositivo e lo passerà a SetFixture prima di eseguire ciascun test. Dopo aver eseguito tutti i test, il corridore eliminerà l'apparecchiatura se implementa IDisposable. Spero che ti aiuti!

La wiki di xUnit su codeplex contiene ulteriori informazioni, incluso un bell'esempio di come implementare IUseFixture per gestire una connessione al database per i tuoi dispositivi di prova.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top