如何检查程序集是否包含单元测试而不加载它?

时间:2013-04-19 18:57:11

标签: c# unit-testing .net-assembly

我目前正在使用以下方法检查测试程序集:

private bool IsTestAssembly(string path)
{
    var assembly = Assembly.LoadFrom(path);
    foreach (var type in assembly.GetTypes())
    {
        var a = type.GetCustomAttributes(true).Select(x => x.ToString());
        if (a.Contains("Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute"))
            return true;
    }
    return false;
}

但是我想在没有将程序集加载到内存中的情况下检查这个,因为我需要能够在验证失败后删除它。

我希望我可以简单地卸载装配,但我很快就发现了,根据MSDN

  

如果不卸载包含它的所有应用程序域,就无法卸载单个程序集。

提前致谢!

2 个答案:

答案 0 :(得分:2)

我按照TheGreatCO的建议制定了一个简短的解决方案,即将程序集加载到新的AppDomain中:

1)用法:

// assemblies are unloaded on disposal
using (var analyser = new AssemblyAnalyser())
{
    var path = "my.unit.tests.dll";
    var b = analyser.IsTestAssembly(path);
    Assert.IsTrue(b);
}

2)实施:

public class AssemblyAnalyser : MarshalByRefObject, IDisposable
{
    public AssemblyAnalyser()
    {
        var evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
        var appSetup = new AppDomainSetup()
        {
            ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
        };
        appDomain = AppDomain.CreateDomain(otherDomainFriendlyName, evidence, appSetup); 
    }

    public bool IsTestAssembly(string assemblyPath)
    {
        if (AppDomain.CurrentDomain.FriendlyName != otherDomainFriendlyName)
        {
            var analyser = appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, GetType().FullName);
            return ((AssemblyAnalyser)analyser).IsTestAssembly(assemblyPath);
        }
        else
        {
            var assembly = Assembly.LoadFrom(assemblyPath);
            return ContainsTestClasses(assembly);
        }
    }

    public void Dispose()
    {
        if (AppDomain.CurrentDomain.FriendlyName != otherDomainFriendlyName)
        {
            AppDomain.Unload(appDomain);
            GC.SuppressFinalize(this);
        }
    }

    ~AssemblyAnalyser()
    {
        Dispose();
    }

    private bool ContainsTestClasses(Assembly assembly)
    {
        foreach (var type in assembly.GetTypes())
        {
            var attr = type.GetCustomAttributes(true).Select(x => x.ToString());
            if (attr.Contains("Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute"))
                return true;
        }
        return false;
    }

    private const string otherDomainFriendlyName = "AssemblyAnalyser";

    private AppDomain appDomain;
}

答案 1 :(得分:1)

使用Mono.Cecil检查装配体。塞西尔不需要加载组件来检查它。