Search code examples
c#bddroslyn

Can I find the source code filename and line number range of a particular C# function?


I'm working on a BDD-style automated testing library, and it would be great if I could include the source code of a failing test in the exception message.

Assuming I can climb the stack trace to find the function which best represents the test, can I use a tool like Roslyn to find the source code for that function?

By way of further explanation, I have tests which look like this:

        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")
        );
    }

If the test fails, I want to provide as much context in the exception message as possible, since I regard the exception as the UI for the test. I'm currently including things like links to screenshots and links to videos of the whole test, and it would be nice if I could also include the source code of the test (since it's pretty human-readable). It's a small thing, but there is a lot of mental context switching involved in debugging a test failure, and it would help not to have to go & look up what the test was trying to do.

NOTE: I'm not interested in a discussion of unit tests vs integration tests. These are integration tests, yes we have unit tests too.

You can assume:

  • I have access to the source code, and can provide the path to the solution file
  • I can climb the exception callstack to get a reference to a System.Reflection.MethodBase object which represents the function CannotChangePasswordIfCurrentPasswordIsIncorrect().
  • I could provide pdb's if needed

So I basically need the filename and range of linenumbers where the source code for that function live.


Solution

  • This question has the information I was looking for.

    Basically it's possible to use Roslyn to ask for the source of a particular function:

    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();
    }