【问题标题】:How to run NUnit programmatically如何以编程方式运行 NUnit
【发布时间】:2008-10-12 03:35:38
【问题描述】:

我有一些引用 NUnit 的程序集并使用单个测试方法创建单个测试类。我能够获得该程序集的文件系统路径(例如“C:...\test.dll”)。我想以编程方式使用 NUnit 来运行这个程序集。

到目前为止,我有:

var runner = new SimpleTestRunner();
runner.Load(path);
var result = runner.Run(NullListener.NULL);

但是,调用 runner.Load(path) 会引发 FileNotFound 异常。我可以通过堆栈跟踪看到问题在于 NUnit 在堆栈中调用 Assembly.Load(path) 。如果我将路径更改为“Test,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”,那么我仍然会收到相同的错误。

我已向 AppDomain.Current.AssemblyResolve 添加了一个事件处理程序,以查看是否可以手动解析此类型,但我的处理程序永远不会被调用。

让 Assembly.Load(...) 工作的秘诀是什么?

【问题讨论】:

  • 最后我的解决方案是只使用 XUnit。 NUnit 有点笨拙。

标签: c# .net nunit assembly.load


【解决方案1】:

如果要以控制台模式打开,添加nunit-console-runner.dll引用并使用:

NUnit.ConsoleRunner.Runner.Main(new string[]
   {
      System.Reflection.Assembly.GetExecutingAssembly().Location, 
   });

如果你想以 gui 模式打开,添加 nunit-gui-runner.dll 参考并使用:

NUnit.Gui.AppEntry.Main(new string[]
   {
      System.Reflection.Assembly.GetExecutingAssembly().Location, 
      "/run"
   });

这是最好的方法,因为您不必指定任何路径。

另一种选择是将 NUnit 运行器集成到 Visual Studio 调试器输出中:

public static void Main()
{
    var assembly = Assembly.GetExecutingAssembly().FullName;
    new TextUI (new DebugTextWriter()).Execute(new[] { assembly, "-wait" });
}

public class DebugTextWriter : StreamWriter
{
    public DebugTextWriter()
        : base(new DebugOutStream(), Encoding.Unicode, 1024)
    {
        this.AutoFlush = true;
    }

    class DebugOutStream : Stream
    {
        public override void Write(byte[] buffer, int offset, int count)
        {
            Debug.Write(Encoding.Unicode.GetString(buffer, offset, count));
        }

        public override bool CanRead { get { return false; } }
        public override bool CanSeek { get { return false; } }
        public override bool CanWrite { get { return true; } }
        public override void Flush() { Debug.Flush(); }
        public override long Length { get { throw new InvalidOperationException(); } }
        public override int Read(byte[] buffer, int offset, int count) { throw new InvalidOperationException(); }
        public override long Seek(long offset, SeekOrigin origin) { throw new InvalidOperationException(); }
        public override void SetLength(long value) { throw new InvalidOperationException(); }
        public override long Position
        {
            get { throw new InvalidOperationException(); }
            set { throw new InvalidOperationException(); }
        }
    };
}

【讨论】:

  • 我尝试了这种方法,它给出了“未设置对象实例的对象引用”。调用 Main 时。也许现在需要不同的参数?
  • 如果你使用的是gui模式和nunit-gui-runner.dll,别忘了把你的main函数标记为[STAThread]。
  • 我刚刚做了第二个例子,GUI。我不得不将"/run" 更改为"-run"。我在 Debian Gnu/Linux 上运行。
  • @Was 添加[STAThread] 停止调试局部变量。删除它解决了这个问题。
  • 您好,当我尝试打开 gui 模式并使用您示例中的代码时,我遇到以下问题:第一次运行正常,第二次运行我收到错误:“对象未设置为实例一个物体”。分析堆栈跟踪我发现这个错误是在 nunit 代码中引发的。在展示 gui runner 之后我应该清理一些东西吗?
【解决方案2】:

“让 Assembly.Load 工作的秘诀是什么?”

System.Reflection.Assembly.Load 接受一个包含程序集名称的字符串,而不是文件路径。

如果您想从文件中加载程序集,请使用:

Assembly a = System.Reflection.Assembly.LoadFrom(pathToFileOnDisk);

(LoadFrom实际上在内部使用了Assembly.Load)

顺便说一句,你有什么理由不能使用NUnit-Console command line tool,而只是将路径传递给你的测试程序集?然后,您可以只使用 System.Diagnostics.Process 从您的客户端应用程序中运行它,可能更简单?

【讨论】:

  • 好吧,我希望我可以使用 LoadFrom,但不幸的是,Assembly.Load 是从 NUnit 中调用的,而不是我的代码,所以我无法控制它。
  • 我可能只需要像你建议的那样通过一个过程来调用它......我宁愿有对象用于我自己的显示目的,但现在只使用一个过程就足够了。
  • 编程没有“秘密”!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 2023-03-24
  • 2011-05-04
  • 1970-01-01
  • 2011-04-05
  • 1970-01-01
  • 2015-02-12
相关资源
最近更新 更多