2010-01-07 4 views
0

dans la version actuelle de NUnit, je peux paramétrer TestFixture et l'instancier plusieurs fois. E.g .:Convertir la chaîne en code C#

[TestFixture("var1")] 
[TestFixture("var2")] 
[TestFixture("var3")] 
public class MyTestFixture 
{ 
    private string var; 

    public MyTestFixture(string var) 
    { 
     this.var = var; 
    } 

    ... 

} 

Cela va instancier le MyTestFixture 3 fois avec le paramètre argument. Mon problème est le NUnit actuel n'a pas de fonction de source de données pour l'attribut TextFixture (seulement TestCaseSource). J'ai besoin d'instancier le TestFixture basé sur l'entrée de données, et chaque TestFixture a un ensemble différent d'entrées de données de test. Aucun problème avec les données du test, grâce à TestCaseSource. Mais comment puis-je faire cela pour l'attribut TestFixture?

Mon idée est de générer l'attribut TestFixture à la volée puis remplacez-la chaîne de code et l'insérer dans le code de test, par exemple .: quelque chose comme ceci:

ConvertToCode(GenerateTestFixture()); 
public class MyTestFixture 
{ 
    ... 
} 

Comment puis-je faire cela? Ou y a-t-il un meilleur moyen?

Merci beaucoup pour votre aide.

Meilleures salutations,
Edward

Répondre

3

Création d'attributs pour votre méthode à la volée est possible mais difficile. Tu ferais mieux de trouver une autre approche.

Des attributs (par exemple [TestFixture]) du type que vous avez sont lus par le compilateur lorsque votre code est compilé et inséré automatiquement dans votre code.

Pour générer vos propres attributs pour les classes, vous devez utiliser quelque chose comme Reflection.Emit pour modifier les assemblys générés en tant qu'étape de post-construction pour le projet. C'est comme écrire le langage d'assemblage directement (vous créez MSIL) ce qui peut être amusant mais n'est pas facile et rendrait votre code très difficile à maintenir!

Une autre approche pourrait être d'avoir un ENUM contrôler les cas de test, et une méthode qui vérifie l'ENUM et renvoie les données appropriées:

public enum TestController 
{ 
    Value1, 
    Value2, 
    Value3 
} 

[TestFixture(TestController.Value1)] 
[TestFixture(TestController.Value2)] 
[TestFixture(TestController.Value3)] 
public class MyTestFixture 
{ 
    public MyTestFixture(TestController testController) 
    { 
     var dataForTest = GetDataForTest(testController); 
    } 

    ... 

} 

La méthode GetDataForTest() faudrait alors une sorte d'instruction switch pour générer les données. Une autre approche pourrait consister à utiliser un type plutôt qu'une énumération, puis instancier le type dans la méthode GetDataForTest() et appeler une méthode usine - mais je pense que cela pourrait être un peu trop compliqué.

+0

Merci beaucoup Jeremy. Le truc TestFixture est piloté par les données, donc je ne saurais pas à l'avance combien de valeur il y aura. L'autre approche fonctionnerait-elle pour TestFixture piloté par les données? Si oui, pouvez-vous me donner un court échantillon? Encore merci beaucoup pour votre aide. Cordialement, Edward –

+0

Si vous ne savez pas combien il y aura alors je ne pense pas qu'il sera possible d'avoir des tests séparés pour chaque élément de données. Au lieu de cela, vous devrez avoir un test qui teste tous les éléments de données. –

+0

En fait, le test existe déjà avec un cas de test test tous les éléments de données, nous avons également un résultat de test personnalisé pour générer des résultats pour chaque élément de données. Mais comme NUnit 2.5 prend en charge les données, j'ai été chargé de convertir le test existant en données UNit pilotées. Cela a quelques avantages sur le test existant, comme regarder mieux dans l'interface utilisateur, peut exécuter un test, etc.Je peux simplement utiliser le TestCaseSource, le problème est que le nom du test devient très long avec beaucoup de doublons comme cas de test hiérarchique. Je pense que je vais essayer l'approche de Reflection.Emit. Merci beaucoup pour votre aide. Cordialement, Edward –

0

Ceci est maintenant possible 3.x NUnit en utilisant l'attribut TestFixtureSource. Créer une classe qui implémente IEnumerable avec vos valeurs puis utilisez-le comme suit:

[TestFixtureSource(typeof(Foo), Category = "Quux")] 
public class BarTest 
{  
    public BarTest(object baz) 
    { 
     _baz = baz; 
    { 
} 

Une chose qui a changé avec TestCaseSource et applique à TestFixtureSource est que vous devez soit donner un type qui implémente IEnumerable ou lui donner un méthode statique.Si vous utilisiez des propriétés ou des méthodes qui génèrent des données à partir du constructeur, vous devez refactoriser de manière statique ou simplement implémenter la classe IEnumerable elle-même et la transmettre comme type source.