سؤال

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?

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top