5

Having not written a unit testing framework before, it seems to me that an inheritable Fact attribute would make it easier to write abstract test classes or test interfaces if certain types in an assembly all needed to be tested for similar things.

Is there a design reason that Fact isn't inheritable? I think other test frameworks (NUnit, MSTest, MbUnit, etc) that use attributes to identify test methods are similarly designed. What am I missing?

Here's the start of what the FactAttribute for xunit (version 1.9.1.1600) looks like:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class FactAttribute : Attribute
{

I'm trying to understand why it doesn't look like the following instead:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class FactAttribute : Attribute
{ 
Ruben Bartelink
  • 55,135
  • 22
  • 172
  • 222
Scott Lawrence
  • 6,315
  • 12
  • 43
  • 61
  • Are you referring to a test in a base class not running in derived class contexts? Pretty sure it does. If not, are you referring to Attributes derived from Fact not being honoured? TheoryAttribute is a counterexample. Can you add a small code snippet that makes this unambiguous and illustrates better what it is you cannot do or wish to do? – Ruben Bartelink Jul 23 '12 at 23:17
  • Methods attributed with Fact in base class or interface are not picked up/run in derived classes that implemented them. – Scott Lawrence Jul 31 '12 at 14:50
  • @RubenBartelink Thanks for the edit--that clarifies my question much better. – Scott Lawrence Aug 01 '12 at 18:21
  • You're welcome, and you got a merited +1 too - I want to know the answer too! Would be interesting to know if other .NET test frameworks do it or not. – Ruben Bartelink Aug 01 '12 at 22:53

3 Answers3

2

The FactAttribute is inheritable.

Have a look at this article: http://iridescence.no/post/Extending-xUnit-with-a-Custom-ObservationAttribute-for-BDD-Style-Testing.aspx

I think it is really useful sometimes.

RegiS
  • 21
  • 1
  • 3
    My question wasn't directed at the nature of the class, but the nature of its usage. Of course the class is inheritable (as is any class that is not sealed). The issue at hand is that if I apply the Fact attribute to a method of a base class or interface, derived classes that implement that interface method are not recognized as Fact methods; I still have to apply the Fact attribute to the derived method in order for test runners to pick it up and execute it. – Scott Lawrence Jul 31 '12 at 13:30
2

I often use the template pattern in my tests (which seems to be what you are trying to accomplish), and it works just fine with xUnit.net.

public abstract class TestBase
{
    [Fact]
    public void Verify()
    {
        // Step 1
        // Step 2

        // Overridable step 3
        DoStuff();

        // Assert
    }

    protected abstract void DoStuff();
}

public class Test1 : TestBase
{
    protected override void DoStuff()
    {
        // Test1 variation
    }
}

public class Test2 : TestBase
{
    protected override void DoStuff()
    {
        // Test2 variation
    }
}

Verify is executed twice -- once on an instance Test1 and again on an instance of Test2.

Hope this helps.

Scott Lawrence
  • 6,315
  • 12
  • 43
  • 61
bricelam
  • 23,776
  • 7
  • 82
  • 103
1

I never heard of an Attribute being inheritable, as it is with classes. You should have no problem though writing a base class with the common test methods and applying the [Fact] attribute to methods in the derived class.

Otávio Décio
  • 70,467
  • 17
  • 156
  • 220
  • 1
    I only learned that Attributes are inheritable because of this: http://stackoverflow.com/questions/1240960/attributes-and-inheritance I'm already applying [Fact] to derived methods. What I'm trying to understand is why [Fact] isn't inheritable. If it were, I think [Fact] could be applied to common test methods in the base class so derived test classes could be made much smaller. – Scott Lawrence Jul 18 '12 at 17:27
  • Oh I see, so did you check the source for [Fact]? You might be able to change it for your purposes and give it a try, they may have a reason to make it not inheritable – Otávio Décio Jul 18 '12 at 17:29
  • 2
    I'm sure they have a reason--I'm just hoping to find out what it is. I'm just not keen on the idea of making a change like that to the test framework without having a bit more background on why it was implemented this way. – Scott Lawrence Jul 18 '12 at 17:41