Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

UITestBench, a lightweight UI testing library

, 3 Apr 2008 CPOL
This article describes how to build a lightweight test bench for testing user interfaces which are written entirely in C#/.NET, using NUnit or any other unit test framework.
UITestBench.zip
UITestBench
UITestBench
bin
Debug
UITestFramework.dll
Framework
Properties
UITestDemoApp
bin
Debug
UITestDemoApp.exe
UITestDemoApp.vshost.exe
Properties
Settings.settings
UITestDemoApp_UITest
bin
Debug
nunit.framework.dll
UITestDemoApp.exe
UITestDemoApp_UITest.dll
UITestFramework.dll
Import
nunit.framework.dll
Properties
Settings.settings
/*
 * This file is licensed under the Code Project CPOL License
 * http://www.codeproject.com/info/cpol10.aspx
 * 
 * © Steffen Schütte 2008
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace de.steffenschuette.UITest.Framework
{
    internal class UIScanner
    {

        /// <summary>
        /// Dictionary with UIFormInfo objects for a formID
        /// </summary>
        private IDictionary<string, UIFormInfo> uiForms;


        public UIScanner()
        {
            uiForms = new Dictionary<string, UIFormInfo>();
        }

        /// <summary>
        /// Gets the UI element with the given id from a specific form.
        /// </summary>
        /// <param name="formId">The form id.</param>
        /// <param name="elementId">The element id.</param>
        /// <returns></returns>
        public UIElementInfo GetUIElement(string formId, string elementId)
        {
            //Scan the forms if formId was not found
            if (!uiForms.ContainsKey(formId))
            {
                ScanUIElements();
            }

            //Now return the UIElement if the form has been scanned
            if (uiForms.ContainsKey(formId))
            {

                return uiForms[formId].GetUIElementInfo(elementId);

            }
            else
            {
                throw new Exception("No form with id '" + formId + "' found!");
            }

            
        }


        /// <summary>
        /// Scans the UI elements of all available forms.
        /// </summary>
        public void ScanUIElements()
        {
            List<string> formIds = new List<string>();
            foreach (Form openForm in Application.OpenForms)
            {

                //Let the name be the form id
                //TODO: This could be improved to support multiple forms with the same type name
                string formId = openForm.GetType().Name;
                
                ScanUIElementsOfForm(openForm, formId);

                formIds.Add(formId);
            }

            //Remove forms that no longer exist
            foreach(string formId in uiForms.Keys)
            {
                if(!formIds.Contains(formId))
                {
                    uiForms.Remove(formId);
                }
            }
        }

        private void ScanUIElementsOfForm(Form formToScan, string formId)
        {
            IDictionary<string, UIElementInfo> newlyScannedElements = new Dictionary<string, UIElementInfo>();

            //Get all supported UI elements of the form
            ScanUIElementsOfControl(formToScan, newlyScannedElements, formToScan.GetType().Name, formToScan.GetType().Name);

            //Set the owner of the elements to the scanned form
            foreach (string key in newlyScannedElements.Keys)
            {
                newlyScannedElements[key].OwningForm = formToScan;
                Console.WriteLine(key);
            }

            //Remove existing form info 
            if (uiForms.ContainsKey(formId))
            {
                uiForms.Remove(formId);
            }

            //And replace with new form info about the newly scanned elements
            uiForms.Add(formId, new UIFormInfo(formToScan.Text, newlyScannedElements));
        }


        /// <summary>
        /// Scans the child elements of the given control.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="uiElements">The ui elements.</param>
        /// <param name="path">The path.</param>
        /// <param name="parent">The parent.</param>
        private void ScanUIElementsOfControl(Control control, IDictionary<string, UIElementInfo> uiElements, string path, string parent)
        {
            int itemIdx = 0;
            foreach (Control childControl in control.Controls)
            {
                string myPath = path + "/" + childControl.GetType().Name + "[" + itemIdx + "]";
                string key = myPath;
                //Use the parent name + accessible name as key if possible
                if (childControl.AccessibleName != null && childControl.AccessibleName.Length > 0)
                {
                    key = parent + "/" + childControl.AccessibleName;
                }
                else if (childControl.Text != null && childControl.Text.Length > 0)
                {
                    //Else use the parent name and the controls text as key
                    key = parent + "/" + childControl.Text;
                }

                //Use the shorter key if not yet used
                if (!uiElements.ContainsKey(key))
                {
                    uiElements.Add(key, new UIElementInfo(childControl, key));
                }
                else
                {
                    //Else use the unique path to the element
                    uiElements.Add(myPath, new UIElementInfo(childControl, myPath));
                }

                ScanUIElementsOfControl(childControl, uiElements, myPath, childControl.GetType().Name);
                itemIdx++;
            }

            //It might be a ToolStrip
            ToolStrip strip = control as ToolStrip;
            if (strip != null)
            {
                ScanToolStripItems(strip.Items, uiElements, path, strip.Text);
            }
        }

        /// <summary>
        /// Scans the tool strip items.
        /// </summary>
        /// <param name="toolStripItemCollection">The tool strip item collection.</param>
        /// <param name="uiElements">The ui elements.</param>
        /// <param name="path">The path.</param>
        /// <param name="parent">The parent.</param>
        private void ScanToolStripItems(ToolStripItemCollection toolStripItemCollection, IDictionary<string, UIElementInfo> uiElements, string path, string parent)
        {
            int itemIdx = 0;
            foreach (ToolStripItem item in toolStripItemCollection)
            {
                string myPath = path + "/" + item.Text + "[" + itemIdx + "]";
                string key = parent + "/" + item.Text;
                if (!uiElements.ContainsKey(key))
                {
                    uiElements.Add(key, new UIElementInfo(item, key));
                    myPath = key;
                }
                else
                {
                    uiElements.Add(myPath, new UIElementInfo(item, myPath));
                }
                itemIdx++;

                ToolStripMenuItem menuItem = item as ToolStripMenuItem;
                if (menuItem != null)
                {
                    ScanToolStripItems(menuItem.DropDownItems, uiElements, path, item.Text);
                }
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

slkr171
Software Developer
Germany Germany
I currently hold the following qualifications
 
- PhD in Computer Science
- M.Sc. in Software Technology
- Diplom (FH) in Computer Science

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150301.1 | Last Updated 3 Apr 2008
Article Copyright 2008 by slkr171
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid