locked
Extending visual studio to add sub menu to context menu of unit test class RRS feed

  • Question

  • Hi,

    Sorry, if i am posting this question in wrong forum.

    I just started developing the visual studio extension following the MSDN library and so far i have reached only adding the item to the context menu of the code editor window.

    I am using Visual Studio 2013 and installed the  Visual Studio SDK to get the extensibility project templates. I created a small extension to get started and manage the add the item to context menu by adding the below highlighted line to .vsct file.

          <Group guid="guidHelloVSExtensionCmdSet" id="MyMenuGroup" priority="0x0600">

            <!--<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>-->

            <!--<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE"/>-->

            <Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>

          </Group>

    The context menu "MyFirstVSExtension" is shown as below

    I want to restrict my custom context menu item only to a test class (it can be a unit test class or a coded ui class). So how can i recognize the type of class that i am right clicking to bring the context menu. Also, i would like to know if i am bring the context menu from a test method or from outside the test method. Thanks in advance!!!


    Thanks, Pratap

    • Moved by lake Xiao Tuesday, November 1, 2016 1:22 AM
    Monday, October 31, 2016 5:44 AM

All replies

  • Hi Pratap15,

    Since your issue is more related to the developing Visual Studio extension. I moved your thread to the corresponding forum for better support.

    Thanks for your understanding.

    Best Regards,

    Lake Xiao

    Tuesday, November 1, 2016 1:22 AM
  • Thanks Lake

    I made some progress on the problem. I took help of the post http://www.diaryofaninja.com/blog/2014/02/18/who-said-building-visual-studio-extensions-was-hard.

    I subscribed to the event of menu command using below code (the bold line is subscribing to the event which will be called when we right click inside the code editor window)

            protected override void Initialize()
            {
                Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
                base.Initialize();
    
                dte = GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
                // Add our command handlers for menu (commands must exist in the .vsct file)
                OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (null != mcs)
                {
                    // Create the command for the menu item.
                    CommandID menuCommandID = new CommandID(GuidList.guidHelloVSExtensionCmdSet, (int)PkgCmdIDList.cmdidMyFirstVSExtension);
                    OleMenuCommand menuItem = new OleMenuCommand(MenuItemCallback, menuCommandID);
                    menuItem.BeforeQueryStatus += menuItem_BeforeQueryStatus;
                    mcs.AddCommand(menuItem);
                }
            }

    To check whether the active document\window is a test class i wrote below method

            private bool IsTestClass()
            {
                if (dte == null)
                    return false;
    
                Document activeDoc = dte.ActiveDocument;
                TextDocument textDoc = activeDoc.Object() as TextDocument;
                if (textDoc.Language.ToLowerInvariant() != "csharp")
                    return false;
                TextSelection sel = (TextSelection)activeDoc.Selection;
                TextPoint pnt = (TextPoint)sel.ActivePoint;
                CodeElement classElement = pnt.get_CodeElement(vsCMElement.vsCMElementClass);
                if (classElement == null)
                    return false;
                CodeElements classAttributes = ((EnvDTE80.CodeClass2)classElement).Attributes;
                foreach (CodeElement currAttribute in classAttributes)
                {
                    if (currAttribute.Name == "TestClass" || currAttribute.Name == "CodedUITest")
                        return true;
                }
                return false;
            }

    To know whether user has right clicked on or inside the test method i wrote below method

            private bool IsTestMethod(CodeElement codeElement)
            {
                if (codeElement == null)
                    return false;
                bool isValidTestMethod = false;
                try
                {
                    CodeElements methodAttributes = ((EnvDTE80.CodeFunction2)codeElement).Attributes;
                    foreach (CodeElement currAttribute in methodAttributes)
                    {
                        if (currAttribute.Name == "TestMethod") // Applicable for unit test and coded ui test
                        {
                            isValidTestMethod = true;
                            break;
                        }
                    }
                }
                catch
                {
                    isValidTestMethod = false;
                }
                return isValidTestMethod;
            }

    The CodeElement represents the member of a class or the class itself. To method IsTestMethod we need to pass a function member from the window where we right clicked. We can get the CodeElement using below code

    EnvDTE.DTE dte = GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; // GetService function is from base class Package
    Document activeDoc = dte.ActiveDocument;
    TextSelection sel = (TextSelection)activeDoc.Selection;
    TextPoint pnt = (TextPoint)sel.ActivePoint;
    CodeElement methodElement = pnt.get_CodeElement(vsCMElement.vsCMElementFunction);

    If you find this as a solution then mark it as an answer else please post a better solution, if any.


    Thanks, Pratap

    Tuesday, November 1, 2016 2:31 PM