Question

I want to check if selected project (I have source code) is a TestProject for one of the following framework: NUnit, MSTest, xUnit.

For MSTest it is simple. I can check .csproj and tag. If I have there {3AC096D0-A1C2-E12C-1390-A8335801FDAB} than it means it is Test project.

The problem are NUnit and xUnit. I can check for this cases references in .csproj. If I have nunit.framework or xunit it will be obvious. But I wondering if is possible to check this in diffrent way.

Do you know different way to recognize test projects?

Était-ce utile?

La solution

One of the way is to check if assembly contains test methods. Attributes for test methods are as following:

  • NUnit: [Test]
  • MSTest: [TestMethod]
  • xUnit.net: [Fact]

Iterate over assemblies and check if assembly contains class with test methods. Example code:

bool IsAssemblyWithTests(Assembly assembly)
{
    var testMethodTypes = new[]
    {
        typeof(Xunit.FactAttribute),
        typeof(NUnit.Framework.TestAttribute),
        typeof(Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute)
    };

    foreach (var type in assembly.GetTypes())
    {
        if (HasAttribute(type, testMethodTypes)) return true;
    }
    return false;
}

bool HasAttribute(Type type, IEnumerable<Type> testMethodTypes)
{
    foreach (Type testMethodType in testMethodTypes)
    {
        if (type.GetMethods().Any(x => x.GetCustomAttributes(testMethodType, true).Any())) return true;
    }

    return false;
}

You can also add more assumptions:

  • check if classes contains TestFixture method,
  • check if classes / test methods are public.

EDIT:

If you need to use C# Parser, here is a sample of NRefactory code for checking if a .cs file contains classes with tests:

string[] testAttributes = new[]
    {
        "TestMethod", "TestMethodAttribute", // MSTest
        "Fact", "FactAttribute", // Xunit
        "Test", "TestAttribute", // NUnit
    };

bool ContainsTests(IEnumerable<TypeDeclaration> typeDeclarations)
{
    foreach (TypeDeclaration typeDeclaration in typeDeclarations)
    {
        foreach (EntityDeclaration method in typeDeclaration.Members.Where(x => x.EntityType == EntityType.Method))
        {
            foreach (AttributeSection attributeSection in method.Attributes)
            {
                foreach (Attribute atrribute in attributeSection.Attributes)
                {
                    var typeStr = atrribute.Type.ToString();
                    if (testAttributes.Contains(typeStr)) return true;
                }
            }
        }
    }

    return false;
}

Example of NRefactory .cs file parsing:

var stream = new StreamReader("Class1.cs").ReadToEnd();
var syntaxTree = new CSharpParser().Parse(stream);
IEnumerable<TypeDeclaration> classes = syntaxTree.DescendantsAndSelf.OfType<TypeDeclaration>();

Autres conseils

I would look for usage of the attributes representing each framework to see which is which.

Use reflection to find classes/methods with the appropriate attribute types (e.g. Test/TestFixture)

This answer has an example that you can modify to meet your needs:

get all types in assembly with custom attribute

Check NuGet references in *.csproj for specific nuggets used for testing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top