我可以找到特定C#函数的源代码文件名和行号范围吗?

时间:2013-12-16 20:17:47

标签: c# bdd roslyn

我正在开发一个BDD风格的自动化测试库,如果我能在异常消息中包含失败测试的源代码,那就太棒了。

假设我可以爬上堆栈跟踪以找到最能代表测试的函数,我可以使用像Roslyn这样的工具来查找该函数的源代码吗?

作为进一步的解释,我的测试看起来像这样:

        public void CannotChangePasswordIfCurrentPasswordIsIncorrect() {
        Given(
            App.ChangePasswordDialog.IsVisible,
            App.ChangePasswordDialog.CurrentPassword.Is("InvalidPassword"),
            App.ChangePasswordDialog.NewPassword.Is("ValidNewPassword"),
            App.ChangePasswordDialog.ConfirmPassword.Is("ValidNewPassword")
        );

        When(
            I.Click(App.ChangePasswordDialog.ChangePasswordButton)
        );

        Then(
            App.ChangePasswordDialog.Alert.IsVisible,
            App.ChangePasswordDialog.Alert.HasKeywords("current", "not correct")
        );
    }

如果测试失败,我想在异常消息中提供尽可能多的上下文,因为我将异常视为测试的UI。我目前正在包括屏幕截图链接和整个测试视频链接等内容,如果我还可以包含测试的源代码(因为它非常易读),那就太好了。这是一件小事,但是在调试测试失败时涉及很多心理上下文切换,这将有助于不必去&查看测试试图做的事情。

注意:我对单元测试与集成测试的讨论不感兴趣。这些是集成测试,是的,我们也有单元测试。

你可以假设:

  • 我可以访问源代码,并可以提供解决方案文件的路径
  • 我可以爬上异常callstack来获取对System.Reflection.MethodBase的引用  表示函数的对象CannotChangePasswordIfCurrentPasswordIsIncorrect()。
  • 如果需要,我可以提供pdb

所以我基本上需要知识库的文件名和范围,其中包含该函数的源代码。

4 个答案:

答案 0 :(得分:2)

我无法想象这是一个好主意。我也认为不可能。除非您正在使用尚未编译的表达式树,否则在运行时几乎不可能对msil进行反编译。即使你可以,由于优化,一些代码可能会完全不同。

答案 1 :(得分:1)

以简单的方式执行 - 请求库的用户指向源代码。这样你就可以查看堆栈跟踪,转到正确的文件并从那里显示源代码行。

答案 2 :(得分:0)

您可以使用

轻松地通过堆栈跟踪访问源代码
 var  stackTrace = Environment.StackTrace;

修改

堆栈跟踪包含执行堆栈的代码成员和代码行。 所以你有源代码名称。

如果您使用* resharper ,则可以执行ctrl-c将此字符串复制到剪贴板。 * 然后在visual studio和resharper中的ctrl-E T将显示一个形式化的堆栈跟踪 然后,您可以按下源代码错误,它会打开问题的编辑器。

Edit2:因为您需要“源代码提取”和堆栈跟踪。我的回答可能无济于事 但要考虑哪些更有用。我将堆栈跟踪存储在系统日志(db表)中。它比我关心更有帮助;-)
取决于您的代码封装的方式。抛出异常的实际代码可能没那么有用。无论如何只是我的观点。

答案 3 :(得分:0)

This question有我正在寻找的信息。

基本上可以使用Roslyn来询问特定功能的来源:

string GetMethod(string filename, string methodName)
{
    var syntaxTree = SyntaxTree.ParseFile(filename);
    var root = syntaxTree.GetRoot();
    var method = root.DescendantNodes()
                     .OfType<MethodDeclarationSyntax>()
                     .Where(md => md.Identifier.ValueText.Equals(methodName))
                     .FirstOrDefault();
    return method.ToString();
}