4

这是我第一次尝试侵入 NUnit 界面,并且面临一些问题。

这就是我想要实现的目标:

  • 将一组字符串输入作为代码文件并将它们编译成程序集
  • 获取内存中的程序集并将其传递给 NUnit 以识别和运行此代码中的测试

这是我到目前为止所拥有的

/// <summary> Validates whether the code files are valid </summary>
public string Validate(string[] codefiles)
{
    // To avoid NullReferenceException within NUnit
    // don't know why this is needed!
    TestExecutionContext.CurrentContext.TestPackage
        = new TestPackage("PersonTest");

    var assembly = BuildAssembly(codefiles);
    TestSuite suite = new TestAssembly(assembly, "PersonTest");
    var result = suite.Run(new NullListener(), TestFilter.Empty);
    return result.IsSuccess ? string.Empty : result.Message;
}

/// <summary> Builds an assembly </summary>
private static Assembly BuildAssembly(string[] code)
{
    var compilerparams = new CompilerParameters(new[] {"nunit.framework.dll"})
    {
        GenerateExecutable = false,
        GenerateInMemory = true
    };
    var results = new CSharpCodeProvider()
        .CompileAssemblyFromSource(compilerparams, code);

    if (!results.Errors.HasErrors) return results.CompiledAssembly;

    throw new Exception(GetErrors(results));
}

这些是我要编译的两个字符串(通过将带有两个元素的字符串数组发送到上面的验证方法中)

private const string File1 = @"
    public class Person 
    {
        public string Name {get;set;}

        public Person(string name)
        {
            Name = name;
        }
    }";

private const string ProperInput = @"
    using NUnit.Framework;

    [TestFixture]
    public class PersonTest
    {
        [Test]
        public void CheckConstructor()
        {
            var me = new Person(""Roopesh Shenoy"");
            Assert.AreEqual(""Roopesh Shenoy"", me.Name);
        }
    }";

问题:

编译进行得很好——生成的程序集甚至有这两种类型。也不将 nunit.framework.dll 传递到引用的程序集中会产生编译异常(动态编译时),因此这意味着 TestFixture/Test addributes 也被识别。

但是,当我调试 TestAssembly 时,测试计数仅显示为零。因此,它没有显示测试成功或失败,而是显示不确定,基本上什么都不做。

我尝试浏览 NUnit 代码库,但还没有得出任何好的结论 - 他们的大多数便捷方法都希望程序集位于文件系统上,所以我试图弄清楚如何做到这一点。有任何想法吗?

4

2 回答 2

2

NUnit 在运行时会创建一些 AppDomain,我想知道是否以某种方式动态地破坏了它并且由于缺少依赖项而看不到您的测试?

于 2012-11-03T17:29:55.773 回答
1

啊,它有效!

我错过了几个步骤(其中固定装置被单独识别并添加到程序集中)+最初是对“InstallBuiltIns”方法的调用。它现在可以工作了,这就是它的外观:

//this is needed only once
CoreExtensions.Host.InstallBuiltins();

var assembly = BuildAssembly(codefiles.ToArray());

// to avoid NullReferenceException - don't know why this is needed!
TestExecutionContext.CurrentContext.TestPackage
    = new TestPackage(assembly.GetName().FullName);

var suite = GetTestSuiteFromAssembly(assembly);
return suite.Run(new NullListener(), TestFilter.Empty);

在哪里:

/// <summary>
/// Converts a given assembly containing tests to a runnable TestSuite
/// </summary>
protected static TestSuite GetTestSuiteFromAssembly(Assembly assembly)
{
    var treeBuilder = new NamespaceTreeBuilder(
        new TestAssembly(assembly, assembly.GetName().FullName));
    treeBuilder.Add(GetFixtures(assembly));
    return treeBuilder.RootSuite;
}

/// <summary>
/// Creates a tree of fixtures and containing TestCases from the given assembly
/// </summary>
protected static IList GetFixtures(Assembly assembly)
{
    return assembly.GetTypes()
        .Where(TestFixtureBuilder.CanBuildFrom)
        .Select(TestFixtureBuilder.BuildFrom).ToList();
}

BuildAssembly 和以前一样。我不得不重复 NUnit 中的一些逻辑的唯一原因是,由于某种原因,这些在 NUnit 代码库中是私有的!

于 2012-11-03T15:33:23.267 回答