Shouldly断言库如何知道断言所应用于的表达式? [英] How does the Shouldly assertion library know the expression the assertion was applied to?

查看:57
本文介绍了Shouldly断言库如何知道断言所应用于的表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

针对.NET的断言库应该以某种方式知道调用断言方法的表达式,因此它能够将其显示在消息中.我试图找出它是如何工作的,但在源代码中迷路了.我怀疑它会查看已编译的代码,但我真的很想看看这是如何发生的.从文档中

The Shouldly assertion library for .NET somehow knows what expression the assertion method was called on so it is able to display it into the message. I tried to find out how it works but got lost in the source code. I suspect it looks into the compiled code but I would really like to see how this happens. From the documentation

map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1

以某种方式应该知道表达式map.IndexOfValue("boo")并能够在测试失败消息中显示它.有谁知道这是怎么发生的?

Somehow Shouldly knows the expression map.IndexOfValue("boo") and was able to display it in the test failure message. Does anyone know how this happens?

推荐答案

看看代码,这很聪明.

魔术发生在 ActualCodeTextGetter 类中.首先,它使用StackTrace检索源代码文件的行:

The magic is happening in the ActualCodeTextGetter class. First, it retrieves the line of the source code file by using the StackTrace:

  StackTrace stackTrace = trace ?? new StackTrace(true);

  // Cut for brevity

  StackFrame stackFrame = frame;
  this.ShouldlyFrameIndex = index - 1;
  string fileName = stackFrame.GetFileName();
  this._determinedOriginatingFrame = fileName != null && File.Exists(fileName);
  this._shouldMethod = this.ShouldlyFrame.GetMethod().Name;
  this.FileName = fileName;
  this.LineNumber = stackFrame.GetFileLineNumber() - 1;

一旦有了源代码文件的名称,以及语句的行和偏移量,就可以直接读取文件:

Once it has the name of the source code file, along with the line and offset of the statement, it's just a matter of reading directly the file:

private string GetCodePart()
{
  string str = "Shouldly uses your source code to generate its great error messages, build your test project with full debug information to get better error messages\nThe provided expression";
  if (this._determinedOriginatingFrame)
  {
    string codeLines = string.Join("\n", ((IEnumerable<string>) File.ReadAllLines(this.FileName)).Skip<string>(this.LineNumber).ToArray<string>());
    int indexOfMethod = codeLines.IndexOf(this._shouldMethod);
    if (indexOfMethod > 0)
      str = codeLines.Substring(0, indexOfMethod - 1).Trim();
    str = !str.EndsWith("Should") ? str.RemoveVariableAssignment().RemoveBlock() : this.GetCodePartFromParameter(indexOfMethod, codeLines, str);
  }
  return str;
}

还有很多逻辑可以精确地隔离该语句,但总而言之,诀窍是:

There's a lot more logic going on to isolate precisely the statement, but in short the trick is:

  • 使用StackTrace检索源代码的位置和语句的行
  • 解析源代码以获取确切的语句

当然,只有在用于编译代码的同一台计算机上运行它时,它才可以工作.

Of course, it can work only if you're running it on the same machine you used to compile the code.

这篇关于Shouldly断言库如何知道断言所应用于的表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆