views:

65

answers:

3

I'm getting error C3095: 'Xunit::Extensions::InlineDataAttribute': attribute cannot be repeated in C++/CLI code but not C#.

xUnit.net looks like the answer to my prayers - a modern unit test framework with GUI working with C++/CLI. However, using their approach to parameterised testing gives me the error C3095 as shown below.

Any ideas?

I'm using the latest xUnit.net 1.6 with Visual Studio 2008SP1.

using namespace Xunit;
using namespace Xunit::Extensions;

public ref class ParameterisedTestClass
{
public:

    [Theory]
    [InlineData("Kilroy", 6)]
    // uncomment to cause c3095 [InlineData("Jones", 5)]
    void PropTest(String^ msg, int msgLen)
    {
        Assert::Equal(msg->Length, msgLen);
    }
};

the equivalent in C# is fine

using Xunit;
using Xunit.Extensions;

public  class ParameterisedTestClass
{

    [Theory]
    [InlineData("Kilroy", 6)]
    [InlineData("Jones", 5)]
    public void PropTest(String msg, int msgLen)
    {
        Assert.Equal(msg.Length, msgLen);
    }
};
+4  A: 

My guess is that this is due to inheritance, and one of the compilers getting it wrong.

InlineDataAttribute inherits from DataAttribute. Now DataAttribute is declared to allow multiple instances:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]

but InlineDataAttribute doesn't have any explicit AttributeUsage attribute itself. I suspect the C++ compiler isn't spotting the inherited AllowMultiple... or it's possible that it shouldn't be inherited. I can't find any detailed documentation about the inheritance of AttributeUsageAttribute itself - although it has Inherited=true, so I guess it should be inherited completely by InlineDataAttribute...

Jon Skeet
+4  A: 

Hmmm... I looked at the defs here and here, and reproduced them (cut-down) below; the inheritance of AllowMultiple via DataAttribute works fine in C#:

class Test
{
    [InlineData]
    [InlineData]
    static void Main() { }
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
class DataAttribute : Attribute {}

class InlineDataAttribute : DataAttribute { }

So if it isn't working for C++/CLI, I guess C++/CLI simply isn't processing the implied [AttributeUsage]. You should file a request against Xunit asking them to make the [AttributeUsage] explicit on InlineDataAttribute.

Marc Gravell
+1  A: 

I repro with this C++/CLI snippet:

[AttributeUsage(AttributeTargets::All, AllowMultiple = true, Inherited = true)]
ref class BaseAttribute : Attribute {};

ref class DerivedAttribute : BaseAttribute {};

[Derived]
[Derived]    // Error C3095
ref class Test {};

Clearly this is a bug in the C++/CLI compiler. I don't see it reported at connect.microsoft.com. Doing so yourself probably isn't worth the effort, the language is in maintenance mode.

Possible workarounds are editing the source code of xUnit to assign AllowMultiple again or to create your own InlineDataFixedAttribute that inherits InlineDataAttribute.

Hans Passant
Why do you say "the language is in maintenance mode?" For VS2010, native C++ code was the focus, working toward the next version (or maybe even next service pack) I understand that C++/CLI is the focus for Visual C++ team. Certainly they've promised to make Intellisense work in C++/CLI again, implement C++0x (which means anonymous methods and closures in C++/CLI as well bringing it to parity with C# in these areas), etc.
Ben Voigt
I'm with Ben, whilst C++/CLI has been relegated to being an "interop language" as such it is vital and I don't see any reason for it to go away. To a certain extent, focusing on this role gave me hope for its long-term future. Depends on whether you consider "maintenance mode" means it will never get new features or if it will just reliably be fixed - I'd be fairly happy with the latter ;-)
Andy Dent