Click here to Skip to main content
15,883,870 members
Articles / Programming Languages / C#

Automated Test System: Part I

Rate me:
Please Sign up or sign in to vote.
3.13/5 (5 votes)
17 Mar 2009GPL32 min read 30.5K   473   18   6
The article attempts to demonstrate a way of testing in the .NET framework. This is just a demonstration of how we can do automated testing in C# .NET.

Introduction

This article presents just a demonstration of how we can start an automated test system development. It's open to all to contribute and make it more worthy. Also, kindly note that you will require both the ATS.zip and Testapp.zip.

Background

I had been looking for an automated test system tool for quite some time, but could not find something which was reliable. So I thought why not try and develop something myself.

main.png

Using the code

The code can be used by anyone who has a basic understanding of the Reflection namespace in the .NET framework. The sole idea is based on any other reflector available in the market, for example Reflector, or the ILDASM that ships with the installation of the .NET framework.

I have tried to use the same idea here. Most of the usable code resides in ATSMainForm.cs. Once we are inside the application:

C#
/// ********************************************************************
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main ()
{
    Application.Run (new ATSMainForm ());
}

We will need to select the target assembly/executable and hit on Launch. What we do in launch is shown here:

C#
///**********************************************************************
/// <summary>
/// Click event handler for the launch button.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="ea">An <see cref="EventArgs"/> object
/// that contains the event data.</param>
/// <remarks>
/// Launches the target application selected via browse button.
/// </remarks> 
private void launchBtn_Click (object sender, System.EventArgs ea)
{
    // Enable/Disable controls
    this.m_mainTv.Nodes.Clear ();
    this.m_mainPnl.Enabled = true;
    this.m_invokeMethodBtn.Enabled = false;
    this.m_methodNameTxtBox.Enabled = false;

    try
    {
        this.m_testAssembly = Assembly.LoadFrom (this.m_appPathTxtBox.Text);
        // Get the available types (controls)
        Type[] types = m_testAssembly.GetTypes ();

        // Try resolving the types and add relevent ones to the treeview
        ResolveTypes (types);

        // Find the entry method and launch the application.
        // TODO: If the default constructor is private, we need to find out
        // how the application can still be launched.
        MethodInfo entryMethod = m_testAssembly.EntryPoint;

        this.m_testForm = m_testAssembly.CreateInstance (
            entryMethod.DeclaringType.FullName,
            true,
            this.m_bindingFlags,
            null,
            null,
            System.Globalization.CultureInfo.InvariantCulture,
            null);
        // Constructor created, try launching??
        ThreadPool.QueueUserWorkItem (new WaitCallback (RunApp), m_testForm);
    }
    catch (Exception ex)
    {
        {
            Form errForm = new ATSError (ex);
            errForm.ShowDialog ();
        }
    }
} // end launchBtn_Click

The good thing about Reflection can be observed here. .NET Reflection allows you to list down all methods/properties/events/classes .. in fact, every thing that is related to this application.

Here is how:

C#
//**********************************************************************
/// <summary>
/// Tries resolving the methods and adds relevent ones to the treeview.
/// <param name="types"> An array of types defined in the loaded assembly
/// </param>
/// <param name="nodeRank"> The index of current <see cref="TreeNode"/>
/// </param>
///</summary>
private void AddMethods (int nodeRank, Type[] types)
{
    MethodInfo[] methods = types[nodeRank].GetMethods (m_bindingFlags);
    this.m_mainTv.Nodes[nodeRank].Nodes.Add ("Methods");

    this.m_mainTv.Nodes[nodeRank].Nodes[1].ImageIndex = 2;
    this.m_mainTv.Nodes[nodeRank].Nodes[1].SelectedImageIndex = 2;

    this.m_tsStatus.Text = "Analysing Methods...";
    this.m_tsProgressBar.ProgressBar.Maximum = methods.Length;

    int nodeCount = 0;

    for (int iMethodCount =0; iMethodCount < methods.Length; iMethodCount++)
    {
        this.m_tsProgressBar.ProgressBar.Value = (int) (iMethodCount/methods.Length * 100);
        this.m_tsStatus.Invalidate ();
        MethodInfo method = (MethodInfo) methods.GetValue (iMethodCount);
        MethodAttributes methodAttrib = method.Attributes;
        if ((method.DeclaringType.FullName == types[nodeRank].FullName.ToString ()) && 
                !(methodAttrib.ToString ().Contains ("SpecialName")))
        {
            this.m_mainTv.Nodes[nodeRank].Nodes[1].Nodes.Add (method.ToString ());
            this.m_mainTv.Nodes[nodeRank].Nodes[1].Nodes[nodeCount].ImageIndex = 2;
            this.m_mainTv.Nodes[nodeRank].Nodes[1].Nodes[nodeCount].SelectedImageIndex = 2;
            this.m_mainTv.Nodes[nodeRank].Nodes[1].Nodes[nodeCount].Tag = method;
            nodeCount++;

        }
    }

    this.m_tsProgressBar.ProgressBar.Value = 0;

} // end AddMethods

Similarly, the events and properties/fields can also be listed. This is one of the approaches that can be followed to write your own reflector or ILDASM :)

testapp.png

Next, the user can start clicking on the method names by which the invoke method textbox is enabled/disabled and then we can invoke any method (say button1_click) as demonstrated in testapp.zip.

Points of interest

pass.png

An interesting point is the way the test is run. Right now, the method names are hard-coded, but later we might like to have these read from some Excel file or something and then use those method names instead.

History

  1. Modified the code a bit to have the start-up form input from the user. The name of the form will be its fully qualified name, i.e., NameSpaceName.FormName.
  2. Check out the latest binaries. I'll upload the updated code and documentation very soon.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
United States United States
"Gameplanner" is an independent software developer. He has been doing software development for many years and has worked with international clients to deliver high quality products.

Comments and Discussions

 
GeneralMy iders Pin
AlphaXu20-Apr-09 16:56
AlphaXu20-Apr-09 16:56 
Excellent article!!!

And also I want to share you with my idea for the tool though it is just a demo.

1. we can add function for setting properites

2. change run test function to dynamic complieCool | :cool:

Then seems more cool~
GeneralRe: My iders Pin
AlphaXu20-Apr-09 17:13
AlphaXu20-Apr-09 17:13 
General[My vote of 2] what unique item were you trying to test Pin
Donsw16-Apr-09 7:41
Donsw16-Apr-09 7:41 
Questionwhy not nunit? Pin
rkeron24-Mar-09 6:21
rkeron24-Mar-09 6:21 
GeneralGood One... Pin
Bhagaban122-Mar-09 22:37
Bhagaban122-Mar-09 22:37 
GeneralYou can test some issue but not all Pin
wegenerb17-Mar-09 8:42
wegenerb17-Mar-09 8:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.