C# – Convert string to C# code

cnunitnunit-2.5

in the current NUnit version, I can parameterized TestFixture and instantiated it multiple times. E.g.:

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

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

    ...  

}  

This will instantiate the MyTestFixture 3 times with the argument parameter. My problem is the current NUnit doesn't have datasource feature for TextFixture attribute (only TestCaseSource). I need to instantiate the TestFixture based on the data input, and each TestFixture has a different sets of test case data input. No problem with the Test case data driven, thanks to the TestCaseSource. But how can I do this for the TestFixture attribute?

My idea is to generate the TestFixture attribute on the fly then change it to code string and insert into the test code, e.g.: something like this:

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

How can I do this? Or are there a better way?

Thank you very much for your help.

Best regards,
Edward

Best Answer

Creating attributes for your method on the fly is possible but hard. You're better off finding another approach.

Attributes (e.g. [TestFixture]) of the kind you have are read by the compiler when your code is compiled and inserted in to your code automatically.

To generate your own attributes for classes you'll need to use something like Reflection.Emit to modify generated assemblies as a post-build step for the project. This is like writing assembly language directly (you'd be creating MSIL) which might be fun but is not easy and would make your code very hard to maintain!

An alternative approach might be to have an enum control the test cases, and have a method that checks the enum and returns the appropriate data:

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

    ...   

}   

The method GetDataForTest() would then have some kind of switch statement to generate the data.

An alternative approach might be to use a type rather than an enum, then instantiate the type in the GetDataForTest() method and call a factory method - but I think that might be a bit overcomplicated.