2012-11-03 33 views
4

这是我第一次尝试破解NUnit接口,并且遇到一些问题。NUnit API和以编程方式运行测试

这就是我想实现:

  • 取一组字符串输入,代码文件和编译成汇编
  • 走在内存组合,并传递给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引用也会被识别。

但是,当我调试TestAssembly只显示测试计数为零。所以不是显示测试成功或失败,而是显示没有结果,基本上什么都不做。

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

+0

任何你不能正确地将你的程序集正确放入磁盘并将它们传递给nunit的原因? –

+0

除了我不应该这样做的事实?!我不想依赖文件系统的存在。 –

+0

好的,谢谢,只是在通读代码之前试图理解上下文 –

回答

2

NUnit在运行时执行一些AppDomain创建,我想知道是否动态地做了所有这些动作,并且由于缺少依赖关系而无法看到您的测试?

+2

我将此标记为答案以给予应有的抵免 - 这非常接近主要问题,这是InstallBuiltins()的缺失调用。不过,请参阅我的答案,以获取可用的完整代码。 –

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代码库中是私有的!