jWebTest : An IE6 based web tester

Download jwebtest.zip

Synopsis:

Test1.cs
RunFiles.cs
Test1.txt
Test2.txt
Test3.txt
Browser.cs
EnumReportApp.cs
Explorer.cs
Globals.cs
IEProcesses.cs
jwebtest.cs
Logger.cs
MsgBoxHandler.cs
Options.cs
TestRunner.cs
WebTest.cs


Test1.cs

Synopsis
using System;
using System.IO;
using System.Collections;

class Test1 : WebTest
{
  public override void Run()
  {
    //    myBrowser.GotoHomePage();
    //    myBrowser.GotoURL("www.intuit.com");
    //
    //    myBrowser.AssertTitleContains("some bad text here");
    //
    //    myBrowser.AssertTitleContains("intuit home");
    //    myBrowser.ClickLink("Careers");
    //    myBrowser.AssertTitleContains("careers@intuit");
    //	
    //    myBrowser.ClickLink("How to Apply");
    //    myBrowser.AssertTitleContains("how to apply");
    //    myBrowser.AssertBodyContains("What happens once I submit");
    //    
    //    myBrowser.ClickLink("Apply for a Specific Opening");
    //    myBrowser.AssertTitleContains("careers job search");
  }
}

RunFiles.cs

Synopsis
using System;
using System.IO;
using System.Collections;

class RunFiles: WebTest
{
  public override void Run()
  {
    string[] files = Directory.GetFiles(Directory.GetCurrentDirectory(), "test*.txt");
    foreach (string file in files)
      RunFile(file);
  }

  class TestCase
  {
    string mCmd = null;
    string mParm1 = null;
    string mParm2 = null;
    string mParm3 = null;
    public TestCase(string cmd)
    {
      mCmd = cmd;
    }
    public TestCase(string cmd, string parm1)
    {
      mCmd = cmd;
      mParm1 = parm1;
    }
    public TestCase(string cmd, string parm1, string parm2)
    {
      mCmd = cmd;
      mParm1 = parm1;
      mParm2 = parm2;
    }
    public TestCase(string cmd, string parm1, string parm2, string parm3)
    {
      mCmd = cmd;
      mParm1 = parm1;
      mParm2 = parm2;
      mParm3 = parm3;
    }
    public string Cmd { get { return mCmd; } }
    public string Parm1 { get { return mParm1; } }
    public string Parm2 { get { return mParm2; } }
    public string Parm3 { get { return mParm3; } }
  }

  public void Runit(ArrayList testcases)
  {
    foreach (TestCase tc in testcases)
    {
      switch(tc.Cmd)
      {
        case "homepage": myBrowser.GotoHomePage(); break;
        case "goto" : myBrowser.GotoURL(tc.Parm1); break;
        case "back" : myBrowser.GoBack(); break;
        case "link" : myBrowser.ClickLink(tc.Parm1); break;
        case "textarea" : myBrowser.SetTextArea(tc.Parm1, tc.Parm2, tc.Parm3); break;
        case "input" : myBrowser.SetInputTextBox(tc.Parm1, tc.Parm2, tc.Parm3); break;
        case "button" : myBrowser.ClickButton(tc.Parm1, tc.Parm2, tc.Parm3); break;
        case "assert" :
        {
          switch(tc.Parm1)
          {
            case "title": myBrowser.AssertTitleContains(tc.Parm2); break;
            case "body" : myBrowser.AssertBodyContains(tc.Parm2); break;
            default: 
              throw new TestException("Unknown assert type: '" + tc.Parm1 + "'");
              //todo: write file and lineno
          }
        }
          break;
        default: 
          //todo: write file and lineno
          throw new TestException("Unknown command: '" + tc.Cmd + "'");
      }
    }
  }

  private void GetToken(string line, ref int posn, ref string parm)
  {
    char delim = ' ';
    if (line[posn] == '"')
    {
      delim = '"';
      posn++;
    }
    for( ; posn < line.Length && line[posn] != delim; ++posn)
      parm += line[posn];

    if (delim == '"')
      posn++;

    for( ; posn < line.Length && line[posn] == ' '; ++posn)
      ; //skip blanks

    parm = parm.Replace("\\n", "\n");
  }

  private TestCase parse(string line)
  {
    line = line.Trim();
    if (line == "") return null; //empty line
    if (line[0] == '#') return null; //comment

    string cmd = "";
    string parm1 = "";
    string parm2 = "";
    string parm3 = "";

    int posn = 0;

    GetToken(line, ref posn, ref cmd);
    if (posn >= line.Length)
      return new TestCase(cmd);

    GetToken(line, ref posn, ref parm1);
    if (posn >= line.Length)
      return new TestCase(cmd, parm1);

    GetToken(line, ref posn, ref parm2);
    if (posn >= line.Length)
      return new TestCase(cmd, parm1, parm2);

    GetToken(line, ref posn, ref parm3);
    if (posn >= line.Length)
      return new TestCase(cmd, parm1, parm2, parm3);

    throw new TestException("Could not parse line: '" + line + "'");
  }

  public void RunFile(string filename)
  {
    Globals.logger.Info("Reading file: '" + filename + "'");
    ArrayList teststeps = new ArrayList();
    StreamReader reader = new StreamReader(filename);
    for(string line = reader.ReadLine(); line != null; line = reader.ReadLine())
    {
      TestCase tc = parse(line);
      if (tc == null) continue;
      teststeps.Add(parse(line));
    }
    reader.Close();
    Runit(teststeps);
  }
}

Test1.txt

Synopsis
homepage
goto localhost/jqwiki/rpc.cgi?clean
goto localhost/jqwiki/jqwiki.cgi
assert title "Front Page"
assert body "Describe FrontPage here"
link Edit
assert title "Edit FrontPage"
textarea "" PageText "This is the new text"
button "" FormSave Save
assert title "Front Page"
assert body "This is the new text"
link RecentChanges
assert body "FrontPage (new)"


Test2.txt

Synopsis
homepage
goto localhost/jqwiki/rpc.cgi?clean
goto localhost/jqwiki/jqwiki.cgi
assert title "Front Page"
assert body "Describe FrontPage here"
link "Edit"
assert title "Edit FrontPage"
textarea "" PageText "abc def ghi jkl"
button "" FormSave Save
assert title "Front Page"
link Search
input "" "FulltextSearch" "xxx"
button "" FormSubmit Search
assert body "None of the search terms were found in the database"
        
input "" FulltextSearch abc
button "" FormSubmit Search
assert body "One or more search terms found on the following pages:"
assert body "1FrontPage"

input "" FulltextSearch "def ghi"
button "" FormSubmit Search
assert body "One or more search terms found on the following pages:"
assert body "2FrontPage"

Test3.txt

Synopsis
homepage
goto localhost/jqwiki/rpc.cgi?clean
goto localhost/jqwiki/jqwiki.cgi
assert title "Front Page"
assert body "Describe FrontPage here"
link Edit
assert title "Edit FrontPage"
textarea "" PageText PageAbc
button "" FormSave Save

#clicking on '?' causes it to go directly to Edit on that page
link ?
assert title "Edit PageAbc"
textarea "" PageText abc
button "" FormSave Save

link FrontPage 
assert title "Front Page"
link Edit
assert title "Edit FrontPage"
textarea "" PageText PageDef
button "" FormSave Save

#clicking on '?' causes it to go directly to Edit on that page
link ?
assert title "Edit PageDef"
textarea "" PageText def
button "" FormSave Save

link FrontPage 
assert title "Front Page"
link Edit
assert title "Edit FrontPage"
textarea "" PageText PageGhi
button "" FormSave Save

#clicking on '?' causes it to go directly to Edit on that page
link ?
assert title "Edit PageGhi"
textarea "" PageText ghi
button "" FormSave Save

link FrontPage 
assert title "Front Page"

link Search
input "" FulltextSearch abc
button "" FormSubmit Search
assert body "One or more search terms found on the following pages:"
assert body 1PageAbc

input "" FulltextSearch "def ghi"
button "" FormSubmit Search
assert body "One or more search terms found on the following pages:"
assert body 1PageDef
assert body 1PageGhi

Browser.cs

Synopsis
using System;
using System.Reflection;
using System.Threading;
using SHDocVw;
using mshtml;

class Browser
{
  static private AutoResetEvent mydocloaded = new AutoResetEvent(false);
  static private bool mydocloading = false;
  static private AutoResetEvent myfinished = new AutoResetEvent(false);
  static private SHDocVw.InternetExplorer myIExplorer = null;
  static private IWebBrowserApp myWebBrowser = null;

  private MsgBoxHandler myMsgBoxHandler = new MsgBoxHandler();

  public Browser()
  {
    myMsgBoxHandler.Start();      
    CreateExplorer();
    SetAllEvents();
    myWebBrowser = (IWebBrowserApp) myIExplorer;
    myWebBrowser.Visible = true;         
  }
  public bool IsAlive()
  {
    return myWebBrowser != null && myIExplorer != null;
  }
  public void Quit()
  {
    Globals.logger.Action("Waiting to quit...");
    myfinished.Reset();
    myWebBrowser.Quit();
    myfinished.WaitOne(5000, false);
    Globals.logger.Info("done.");
  }
  public void Close()
  {
    myMsgBoxHandler.Close();
  }
  
  //-- direct navigation ---------------------------------------
  public void GotoHomePage()
  {
    Globals.logger.Action("goto HomePage");
    myWebBrowser.GoHome();
    AssertDocLoaded();
  }
  public void GoBack()
  {
    Globals.logger.Action("go Back");
    myWebBrowser.GoBack();
    AssertDocLoaded();
  }
  public void GotoURL(string thePage)
  {
    Globals.logger.Action("goto Page: {0}", thePage);
    Object o = null;
    myWebBrowser.Navigate(thePage, ref o, ref o, ref o, ref o);
    AssertDocLoaded();
  }
  
  //-- click items ---------------------------------------
  public void SubmitForm(string formName)
  {
    Globals.logger.Action("submit form: {0} ", formName);
    SubmitForm((IHTMLFormElement) GetForm(formName));
  }
  public void ClickLink(string linkName)
  {
    Globals.logger.Action("click link: {0}", linkName);
    ClickLink(FindLink(linkName));
  }
  public void ClickElement(string tagName, string searchFor)
  {
    Globals.logger.Action("click element: {0}, {1}", tagName, searchFor);
    ClickLink(FindElement(tagName, searchFor));
  }
  public void ClickSubmitButton(string formName)
  {
    Globals.logger.Action("click submit button for form: {0}", formName);
    ClickLink(GetNamedButton(formName, "submit"));
  }
  public void ClickButton(string formName, string buttonName, string buttonValue)
  {
    Globals.logger.Action("click button name: '{0}' value: '{1}' in form: {2}", buttonName, buttonValue, formName);
    ClickLink(FindButton(formName, buttonName, buttonValue));
  }

  //-- msgbox items ---------------------------------------
  public void ExpectMsgBoxOk()
  {
    Globals.logger.Action("expecting msgbox OK button");
    myMsgBoxHandler.ExpectOk();
  }
  public void ExpectMsgBoxCancel()
  {
    Globals.logger.Action("expecting msgbox Cancel button");
    myMsgBoxHandler.ExpectCancel();
  }

  //-- text input ---------------------------------------
  public void SetInputTextBox(string formName, string elementName, string newValue)
  {
    Globals.logger.Action("set textbox: {0}", elementName);
    GetNamedInputTextBox(formName, elementName).value = newValue;
  }
  public void SetTextArea(string formName, string elementName, string newValue)
  {
    Globals.logger.Action("set textarea: {0}", elementName);
    GetNamedTextArea(formName, elementName).value = newValue;
  }

  //-- radio/checkbox buttons ---------------------------------------
  public void ClickRadio(string formName, string checkName, int checkIndex)
  {
    Globals.logger.Action("click radio button: {0}, {1}", checkName, checkIndex.ToString());
    GetRadioButton(GetNamedRadioCollection(formName, checkName), checkIndex).click();
  }
  public void ClickCheckBox(string formName, string checkName)
  {
    Globals.logger.Action("click checkbox: {0}", checkName);
    GetNamedCheckBox(formName, checkName).click();
  }
  public void ChooseSelect(string formName, string selectName, string selectValue)
  {
    Globals.logger.Action("choose select: {0}, {1}", selectName, selectValue);
    IHTMLSelectElement selectarea = GetNamedSelectCollection(formName, selectName);
    for(int i = 0; i < selectarea.length; ++i)
    {
      IHTMLElement s = (IHTMLElement) selectarea.item(i,i);
      if (s == null) continue;
      if (s.innerText == null) continue;
      if (Compare(selectValue, s.innerText))
      {
        SelectOption(selectarea, s);
        return;
      }
    }   
    throw new TestException("Could not find value: '" + selectValue + "' in select: " + selectName + " in form: " + formName);
  }

  //-- get values ---------------------------------------
  public string GetSelectValue(string formName, string selectName, string selectOption)
  {
    Globals.logger.Action("choose select: {0}, {1}", selectName, selectOption);
    IHTMLSelectElement selectarea = GetNamedSelectCollection(formName, selectName);
    for(int i = 0; i < selectarea.length; ++i)
    {
      IHTMLElement s = (IHTMLElement) selectarea.item(i,i);
      if (s == null) continue;
      if (s.innerText == null) continue;
      if (Compare(selectOption, s.innerText))
      {            
        return (string)s.getAttribute("Value",0);
      }
    }   
    throw new TestException("Could not find value: '" + selectOption + "' in select: " + selectName + " in form: " + formName);
  }
  public string GetQueryStringValue(string variableName)
  {
    string stringValue = myWebBrowser.LocationURL.ToString().ToLower();
    int startingPoint = stringValue.IndexOf(variableName,0) + variableName.Length + 2;
    return stringValue.Substring(startingPoint,36);
  }

  //-- asserts ---------------------------------------
  public void AssertTitleContains(string expectedTitle)
  {
    Globals.logger.SetLocation();
    AssertContains(GetDoc().title, expectedTitle);
  }
  public void AssertTitleNotContains(string expectedTitle)
  {
    Globals.logger.SetLocation();
    AssertNotContains(GetDoc().title, expectedTitle);
  }
  public void AssertBodyContains(string expected)
  {
    Globals.logger.SetLocation();
    AssertContains(GetDoc().body.innerText, expected);
  }
  public void AssertBodyNotContains(string expected)
  {
    Globals.logger.SetLocation();
    AssertNotContains(GetDoc().body.innerText, expected);
  }
  public void AssertTextAreaContains(string formName, string elementName, string expected)
  {
    Globals.logger.SetLocation();
    AssertContains(GetNamedTextArea(formName, elementName).value, expected);
  }
  public void AssertEqualCaseInsensitive(string expected, string actual)
  {
    if (expected.ToLower().Equals(actual.ToLower()))
      return;
    Globals.logger.SetLocation();
    Globals.logger.Failure("string '{0}'\ndoes not match expected string '{1}'", actual, expected);
  }
  //-------------
  //-- private from here on
  //-------------
  private void ClickLink(IHTMLElement link)
  {
    link.click();
    AssertDocLoaded();
  }
  private IHTMLElement FindLink(string linktext)
  {
    foreach (IHTMLElement link in GetLinks())
    {
      if (link == null) continue;
      if (link.tagName == null) continue;
      if (! Compare(link.tagName, "A")) continue;
      if (link.innerText == null) continue;
      if (Compare(linktext, link.innerText)) return link;
    }
    throw new TestException("Could not find link: '" + linktext + "'");
  }
  private IHTMLElement FindElement(string tag, string searchFor)
  {
    foreach (IHTMLElement link in GetLinks())
    {
      if (link == null) continue;
      if (link.tagName == null) continue;
      if (! Compare(link.tagName, tag)) continue;
      if (link.outerHTML == null) continue;
      if (!Contains(link.outerHTML, "href=")) continue;
      if (Contains(link.outerHTML, searchFor)) return link;
    }
    throw new TestException("Could not find link with tag: '" + tag + "'\nor containing string '" + searchFor + "'");
  }
  private IHTMLElement FindButton(string formName, string buttonName, string buttonValue)
  {
    foreach (IHTMLInputElement e in GetElementsByName(buttonName))
    {
      if (e == null) continue;
      if (formName != "")
      {
        if (e.form == null) continue;
        if (e.form.name == null) continue;
        if (! Compare(formName, e.form.name)) continue;
      }
      if (e.value == null) continue;
      if (Compare(buttonValue, e.value)) return (IHTMLElement) e;
    }   
    throw new TestException("Could not find button with name: '" + buttonName + "' value: '" + buttonValue + "'");
  }
  private void SetChooseOption(IHTMLElement s)
  {
    IHTMLOptionElement opt = (IHTMLOptionElement) s;
    opt.selected = true;
  }
  private void SelectOption(IHTMLSelectElement selectarea, IHTMLElement s)
  {
    SetChooseOption(s);
    FireSelectOnChangeEvent(selectarea);
    Thread.Sleep(500); //give up the cpu
    if (mydocloading)
      AssertDocLoaded();
  }
  private void FireSelectOnChangeEvent(IHTMLSelectElement selectarea)
  {
    if (selectarea.onchange.GetType() == typeof(System.DBNull)) return;

    object n = null;
    object eobj = GetDoc4().CreateEventObject(ref n);
    ((IHTMLElement3) selectarea).FireEvent("onchange", ref eobj);
  }
  private IHTMLElementCollection GetElementsByName(string name)
  {
    return (IHTMLElementCollection) GetDoc3().getElementsByName(name);
  }
  private IHTMLElement GetRadioButton(IHTMLElementCollection radiocoll, int buttonIndex)
  {
    IHTMLElement button = (IHTMLElement) radiocoll.item(buttonIndex, buttonIndex);
    if (button == null) throw new TestException("Could not find radio button with index: " + buttonIndex);
    return button;
  }
  private IHTMLElementCollection GetForms()
  {
    IHTMLElementCollection forms = (IHTMLElementCollection) GetDoc().forms;
    if (forms == null) throw new TestException("Page has no forms.");
    return forms;
  }
  private IHTMLElementCollection GetLinks()
  {
    IHTMLElementCollection links = (IHTMLElementCollection) GetDoc().links;
    if (links == null) throw new TestException("Page has no links.");
    return links;
  }
  private IHTMLFormElement3 GetForm(string formName)
  {
    IHTMLElementCollection forms = GetForms();
    IHTMLFormElement3 form = (IHTMLFormElement3) forms.item(formName, 0);
    if (form == null)
    {
      if (forms.length == 1)
      {
        form = (IHTMLFormElement3) forms.item(0, 0);
      }
    }
    if (form == null) throw new TestException("Could not find form: '" + formName + "'");
    return form;
  }
  private IHTMLDocument2 GetDoc()
  {
    return (IHTMLDocument2) myWebBrowser.Document;
  }
  private IHTMLDocument3 GetDoc3()
  {
    return (IHTMLDocument3) myWebBrowser.Document;
  }
  private IHTMLDocument4 GetDoc4()
  {
    return (IHTMLDocument4) myWebBrowser.Document;
  }
  //NOTE: even though the GetNamedxxx() methods look alike, they are not.
  // The casts cause a QueryInterface() to be done and therefore they cannot be merged into one
  // unless the cast is identical.
  private IHTMLElementCollection GetNamedRadioCollection(string formName, string colName)
  {
    IHTMLElementCollection aColl = (IHTMLElementCollection) GetForm(formName).namedItem(colName);
    if (aColl == null) throw new TestException("Could not find radio groupname: '" + colName + "'");
    return aColl;
  }
  private IHTMLElement GetNamedButton(string formName, string buttonName)
  {
    return GetNamedElement(formName, "Could not find button", buttonName);
  }
  private IHTMLElement GetNamedCheckBox(string formName, string colName)
  {
    return GetNamedElement(formName, "Could not find checkbox", colName);
  }
  private IHTMLElement GetNamedElement(string formName, string warning, string elementName)
  {
    IHTMLElement anElement = (IHTMLElement) GetForm(formName).namedItem(elementName);
    if (anElement == null) throw new TestException(warning + ": '" + elementName + "'");
    return anElement;
  }
  private IHTMLSelectElement GetNamedSelectCollection(string formName, string selectName)
  {
    IHTMLSelectElement selectarea = (IHTMLSelectElement) GetForm(formName).namedItem(selectName);
    if (selectarea == null) throw new TestException("Could not find chooselist: '" + selectName + "'");
    return selectarea;
  }
  private IHTMLInputElement GetNamedInputTextBox(string formName, string elementName)
  {
    IHTMLInputElement inputarea = (IHTMLInputElement) GetForm(formName).namedItem(elementName);
    if (inputarea == null) throw new TestException("Could not find input textbox: '" + elementName + "'");
    return inputarea;
  }
  private IHTMLTextAreaElement GetNamedTextArea(string formName, string elementName)
  {
    IHTMLFormElement3 form = GetForm(formName);
    IHTMLTextAreaElement textarea = null;
    try 
    {
      textarea = (IHTMLTextAreaElement) form.namedItem(elementName);
    } 
    catch(Exception)
    {
    }
    if (textarea == null) throw new TestException("Could not find textarea: '" + elementName + "'");
    return textarea;
  }
  // END: GetNamedxxx()

  private void SubmitForm(IHTMLFormElement form)
  {
    form.submit();
    AssertDocLoaded();
  }
  private void AssertContains(string actual, string expected)
  {
    if (actual == null && expected == null) return;
    if (actual == null) actual = "";
    if (Contains(actual.Replace("\r\n", "\n"), expected)) return;
    Globals.logger.Failure("string '{0}'\ndoes not contain expected string '{1}'", actual, expected);
  }
  private void AssertNotContains(string actual, string expected)
  {
    if (actual == null && expected == null) return;
    if (actual == null) actual = "";
    if (!Contains(actual.Replace("\r\n", "\n"), expected)) return;
    Globals.logger.Failure("string '{0}'\n contains string '{1}'", actual, expected);
  }
  private void AssertDocLoaded()
  {
    if (mydocloaded.WaitOne(60000, false)) return;
    Globals.logger.Failure("page failed to load!");
  }
  private bool Compare(string s1, string s2)
  {
    return s1.Trim().ToLower().Equals(s2.Trim().ToLower());
  }
  private bool Contains(string s1, string s2)
  {
    return s1.Trim().ToLower().IndexOf(s2.Trim().ToLower()) != -1;
  }
  private void CreateExplorer()
  {
    try
    {
      myIExplorer = new SHDocVw.InternetExplorer();
    }
    catch(Exception e)
    {
      Globals.logger.Failure("Exception when creating IE object {0}",  e);
      throw e;
    }
  }
  private void SetAllEvents()
  {
    myIExplorer.TitleChange += new DWebBrowserEvents2_TitleChangeEventHandler(OnTitleChange);
    myIExplorer.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(OnDocumentComplete);
    myIExplorer.OnQuit += new DWebBrowserEvents2_OnQuitEventHandler(OnQuit);
    myIExplorer.BeforeNavigate2 += new DWebBrowserEvents2_BeforeNavigate2EventHandler(OnBeforeNavigate2);
    myIExplorer.DownloadBegin += new DWebBrowserEvents2_DownloadBeginEventHandler(OnDownloadBegin);
    myIExplorer.DownloadComplete += new DWebBrowserEvents2_DownloadCompleteEventHandler(OnDownloadComplete);
  }

  //-------------
  //-- statics from here on
  //-------------
  static private void OnTitleChange(string Text)
  {
    Globals.logger.Event("Title changed to: {0}", Text);
  }
  static private void OnDocumentComplete(Object ob1, ref Object URL)
  {
    Globals.logger.Event("Document complete: {0}", (string) URL);
    mydocloaded.Set();
    mydocloading = false;
  }
  static private void OnQuit()
  {
    Globals.logger.Event("IE Quitting...");
    myfinished.Set();
  }
  static private void OnDownloadBegin()
  {
    mydocloading = true;
    mydocloaded.Reset();
    //Globals.logger.Event("Download begin...");
  }
  static private void OnDownloadComplete()
  {
    //Globals.logger.Event("Download complete...");
  }
  static private void OnBeforeNavigate2(Object ob1, ref Object URL, ref Object Flags, ref Object Name, ref Object da, ref Object Head, ref bool Cancel)
  {
    Globals.logger.Event("IE Before Navigate2...");
    Cancel = false;
  }
}

EnumReportApp.cs

Synopsis
using System;
using System.Runtime.InteropServices;

namespace atweb
{
	/// <summary>
	/// Summary description for EnumReportApp.
	/// </summary>
      public delegate bool CallBack(int hwnd, int lParam);
   
      public class EnumReportApp 
      {
   
         [DllImport("user32")]
         public static extern int EnumWindows(CallBack x, int y); 
   
         public static void RenameMethod() 
         {
            CallBack myCallBack = new CallBack(EnumReportApp.Report);
            EnumWindows(myCallBack, 0);
         }
   
         public static bool Report(int hwnd, int lParam) 
         { 
            Console.Write("Window handle is ");
            Console.WriteLine(hwnd);
            return true;
         }
      }
}

Explorer.cs

Synopsis
using System;

public class Explorer 
{
  public void Run()
  {
    try
    {  
      TestRunner.Run();
    }
    catch(Exception sE)
    {
      Globals.logger.Failure("unhandled exception occurred", sE);
    }
  }
}

Globals.cs

Synopsis
using System;

public class Globals
{
  public static Logger logger = new TextLogger(Console.Out);
  public static Options options = new Options();

  public static void SetLogger(System.Windows.Forms.ListBox lb)
  {
    logger = new ListBoxLogger(lb);
  }

}

IEProcesses.cs

Synopsis
using System;
using System.Collections;
using System.Windows.Forms;
using SHDocVw;
using mshtml;

public class IEProcesses
{
  private ListBox mOutBox;
  public IEProcesses(ListBox lb)
  {
    mOutBox = lb;
  }

  public void Display()
  {
    foreach (SHDocVw.InternetExplorer ie in new SHDocVw.ShellWindowsClass())
    {
      if (ie.FullName.ToLower().IndexOf("iexplore.exe") == -1 ) continue;
      DisplayIEComponents(ie);
    }
  }
  private void  DisplayIEComponents(SHDocVw.InternetExplorer ie)
  {
    IHTMLDocument2 doc2 = (IHTMLDocument2) ie.Document;
    mOutBox.Items.Add("Explorer Instance: url= " + ie.LocationURL);
    mOutBox.Items.Add("\tmyBrowser.VerifyTitleContains(\"" + doc2.title +  "\");");
    DisplayFormComponents((IHTMLElementCollection) doc2.forms);
    DisplayNonFormComponents((IHTMLElementCollection) doc2.links);
  }
  private void DisplayNonFormComponents(IHTMLElementCollection links)
  {
    foreach (IHTMLElement link in links)
      DisplayLinksWithNoForm(link);
  }
  private void DisplayLinksWithNoForm(IHTMLElement link)
  {
    if (link.innerText == null) return;
    if (link.innerText.ToLower().Trim() == "") return;
    mOutBox.Items.Add("\tmyBrowser.ClickLink(\"" + link.innerText.Trim() + "\");");
  }
  private void DisplayFormComponents(IHTMLElementCollection forms)
  {
    Hashtable radiogroups = new Hashtable();
    foreach (IHTMLFormElement form in forms)
      DisplayFormComponents(form, radiogroups);
  }
  private void DisplayFormComponents(IHTMLFormElement form, Hashtable radiogroups)
  {
    bool submitfound = false;
    string formname = form.name;
    string formid = GetFormId(form);

    for(int i = 0; i < form.length; ++i)
    {
      IHTMLElement item = (IHTMLElement) form.item(i, i);
      if (item.tagName.Equals("INPUT"))
        DisplayInputElement(item, formid, formname, radiogroups, ref submitfound);
      else if (item.tagName.Equals("SELECT"))
        DisplaySelectElement(item, formid, formname);
      else if (item.tagName.Equals("TEXTAREA"))
        DisplayTextAreaElement(item, formid, formname);
      else
        mOutBox.Items.Add("\t-->Form: '" + formname + "'\tItem: tag='" + item.tagName + "' innertext='" + item.innerText + "'");
    }
    if (!submitfound)
    {
      if (formid == null)
        mOutBox.Items.Add("\tmyBrowser.SubmitForm(\"" + formname + "\");");
      else
        mOutBox.Items.Add("\tmyBrowser.SubmitForm(\"" + formid + "\");");
    }
  }
  private string GetFormId(IHTMLFormElement form)
  {
    IHTMLElement eform = (IHTMLElement) form;
    if (eform != null && eform.id != null) return eform.id;
    return null;
  }
  private void DisplayInputElement(IHTMLElement item, string formid, string formname, Hashtable radiogroups, ref bool submitfound)
  {
    IHTMLInputElement initem = (IHTMLInputElement) item;
    if (initem.type.Equals("hidden")) return;
         
    if (initem.type.Equals("password") || initem.type.Equals("text"))
      mOutBox.Items.Add("\tmyBrowser.SetInputTextBox(\"" + formname + "\", \""+initem.name+"\", \"...\");");
    else if (initem.type.Equals("submit"))
    {
      submitfound = true;
      if (formid == null)
        mOutBox.Items.Add("\tmyBrowser.ClickSubmitButton(\"" + formname + "\")");
      else
        mOutBox.Items.Add("\tmyBrowser.SubmitForm(\"" + formid + "\");");
    }
    else if (initem.type.Equals("radio"))
    {
      int index = 0;
      if (radiogroups.ContainsKey(initem.name))
      {
        index = (int) radiogroups[initem.name] + 1;
        radiogroups[initem.name] = index;
      }
      else
        radiogroups.Add(initem.name, index); 
      mOutBox.Items.Add("\tmyBrowser.ClickRadio(\"" + formname + "\", \""+initem.name+"\", "+ index +");   //value->'"+initem.value+"'");
    }
    else if (initem.type.Equals("checkbox"))
      mOutBox.Items.Add("\tmyBrowser.ClickCheckBox(\"" + formname + "\", \""+initem.name+"\");");
    else if (initem.type.Equals("button"))
      mOutBox.Items.Add("\tmyBrowser.ClickButton(\"" + formname + "\", \""+initem.name+"\", \""+initem.value+"\");");
    else
      mOutBox.Items.Add("\t-->Form: '" + formname + "'\tItem: tag='" + item.tagName + "' name='" +initem.name+ "' value='" + initem.value + "' type='" + initem.type + "'");
  }
  private void DisplayTextAreaElement(IHTMLElement item, string formid, string formname)
  {
    IHTMLTextAreaElement taitem = (IHTMLTextAreaElement) item;
    mOutBox.Items.Add("\tmyBrowser.SetTextArea(\"" + formname + "\", \""+taitem.name+"\", \"...\");");
  }
  private void DisplaySelectElement(IHTMLElement item, string formid, string formname)
  {
    IHTMLSelectElement sitem = (IHTMLSelectElement) item;
    for(int j = 0; j < sitem.length; ++j)
    {
      IHTMLElement e = (IHTMLElement) sitem.item(j, j);
      if (e == null) continue;

      string name = sitem.name;
      if (item.id != null && item.id != "") name = item.id;
      mOutBox.Items.Add("\tmyBrowser.ChooseSelect(\"" + formname + "\", \""+name+"\", \""+e.innerText+"\");");
    }
  }
}

jwebtest.cs

Synopsis
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

//todo:
// - add a "Close IE" button (only visible if RunTests was pressed)
// - add menu
//     - options (verbosity, etc.)
// - new option (switch /c) means "close IE when done"
// - new option (switch /out:filename) means redirect output to given file
//   It finds all tests (via reflection) in any dll's it finds in the dir tree
// - add help
// - get it to run test from cmd line (if any args) and from windows (if 0 args).

public class MainWindow : Form
{
  private IEProcesses mProcesses;
  private ListBox mPageDumpOutputListBox;
  private System.Windows.Forms.MainMenu mainMenu1;
  private System.Windows.Forms.Button mRefresh;
  private System.Windows.Forms.Button mRunTests;
  private System.Windows.Forms.TabControl mTabSelector;
  private System.Windows.Forms.TabPage mTestOutputTab;
  private System.Windows.Forms.TabPage mPageDumpOutputTab;
  private System.Windows.Forms.ListBox mTestOutputTabListBox;
  private System.ComponentModel.Container components = null;

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main() 
  {
    //    Globals.options.ProcessCommandLine(args);
    //Globals.options.verbose = false;
    Globals.options.verbose = true;
    Application.Run(new MainWindow());
  }
  public MainWindow()
  {
    // Required for Windows Form Designer support
    InitializeComponent();
    mProcesses = new IEProcesses(mPageDumpOutputListBox);
    AttachToIE();
  }

  /// <summary>
  /// Clean up any resources being used.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
    if( disposing )
    {
      if (components != null) 
        components.Dispose();
    }
    base.Dispose( disposing );
  }

  //-------------------------------------------------
  //-- private from here on
  //-------------------------------------------------
		#region Windows Form Designer generated code
  /// <summary>
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
    this.mPageDumpOutputListBox = new System.Windows.Forms.ListBox();
    this.mainMenu1 = new System.Windows.Forms.MainMenu();
    this.mRefresh = new System.Windows.Forms.Button();
    this.mRunTests = new System.Windows.Forms.Button();
    this.mTabSelector = new System.Windows.Forms.TabControl();
    this.mPageDumpOutputTab = new System.Windows.Forms.TabPage();
    this.mTestOutputTab = new System.Windows.Forms.TabPage();
    this.mTestOutputTabListBox = new System.Windows.Forms.ListBox();
    this.mTabSelector.SuspendLayout();
    this.mPageDumpOutputTab.SuspendLayout();
    this.mTestOutputTab.SuspendLayout();
    this.SuspendLayout();
    // 
    // mPageDumpOutputListBox
    // 
    this.mPageDumpOutputListBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
    this.mPageDumpOutputListBox.ItemHeight = 15;
    this.mPageDumpOutputListBox.Name = "mPageDumpOutputListBox";
    this.mPageDumpOutputListBox.ScrollAlwaysVisible = true;
    this.mPageDumpOutputListBox.Size = new System.Drawing.Size(536, 259);
    this.mPageDumpOutputListBox.TabIndex = 0;
    this.mPageDumpOutputListBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mPageDumpOutputListBox_MouseDown);
    // 
    // mRefresh
    // 
    this.mRefresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
    this.mRefresh.Location = new System.Drawing.Point(8, 0);
    this.mRefresh.Name = "mRefresh";
    this.mRefresh.Size = new System.Drawing.Size(56, 24);
    this.mRefresh.TabIndex = 1;
    this.mRefresh.Text = "Refresh";
    this.mRefresh.Click += new System.EventHandler(this.mRefresh_Click);
    // 
    // mRunTests
    // 
    this.mRunTests.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
    this.mRunTests.Location = new System.Drawing.Point(72, 0);
    this.mRunTests.Name = "mRunTests";
    this.mRunTests.TabIndex = 2;
    this.mRunTests.Text = "RunTests";
    this.mRunTests.Click += new System.EventHandler(this.mRunTests_Click);
    // 
    // mTabSelector
    // 
    this.mTabSelector.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                             this.mPageDumpOutputTab,
                                                                             this.mTestOutputTab});
    this.mTabSelector.Location = new System.Drawing.Point(8, 24);
    this.mTabSelector.Name = "mTabSelector";
    this.mTabSelector.SelectedIndex = 0;
    this.mTabSelector.Size = new System.Drawing.Size(672, 384);
    this.mTabSelector.TabIndex = 3;
    // 
    // mPageDumpOutputTab
    // 
    this.mPageDumpOutputTab.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                   this.mPageDumpOutputListBox});
    this.mPageDumpOutputTab.Location = new System.Drawing.Point(4, 22);
    this.mPageDumpOutputTab.Name = "mPageDumpOutputTab";
    this.mPageDumpOutputTab.Size = new System.Drawing.Size(664, 358);
    this.mPageDumpOutputTab.TabIndex = 1;
    this.mPageDumpOutputTab.Text = "PageDump";
    // 
    // mTestOutputTab
    // 
    this.mTestOutputTab.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                               this.mTestOutputTabListBox});
    this.mTestOutputTab.Location = new System.Drawing.Point(4, 22);
    this.mTestOutputTab.Name = "mTestOutputTab";
    this.mTestOutputTab.Size = new System.Drawing.Size(664, 358);
    this.mTestOutputTab.TabIndex = 0;
    this.mTestOutputTab.Text = "Test Output";
    // 
    // mTestOutputTabListBox
    // 
    this.mTestOutputTabListBox.Name = "mTestOutputTabListBox";
    this.mTestOutputTabListBox.Size = new System.Drawing.Size(712, 316);
    this.mTestOutputTabListBox.TabIndex = 0;
    this.mTestOutputTabListBox.SelectedIndexChanged += new System.EventHandler(this.mTestOutputTabListBox_SelectedIndexChanged);
    // 
    // MainWindow
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    this.ClientSize = new System.Drawing.Size(1008, 338);
    this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                this.mTabSelector,
                                                                this.mRunTests,
                                                                this.mRefresh});
    this.KeyPreview = true;
    this.Menu = this.mainMenu1;
    this.Name = "MainWindow";
    this.Text = "jWebTest";
    this.Layout += new System.Windows.Forms.LayoutEventHandler(this.MainWindow_Layout);
    this.mTabSelector.ResumeLayout(false);
    this.mPageDumpOutputTab.ResumeLayout(false);
    this.mTestOutputTab.ResumeLayout(false);
    this.ResumeLayout(false);

  }
		#endregion
  private void MainWindow_Layout(object sender, LayoutEventArgs e)
  {
    ResizeTabSelectorToForm();
    Invalidate();
  }
  private void ResizeTabSelectorToForm()
  {
    const int gap = 3;
    mTabSelector.SetBounds(0, mRefresh.Height + gap, this.ClientSize.Width, this.ClientSize.Height - mRefresh.Height - gap);
    mPageDumpOutputListBox.SetBounds(0, 0, mPageDumpOutputTab.ClientSize.Width, mPageDumpOutputTab.ClientSize.Height); 
    mTestOutputTabListBox.SetBounds(0, 0, mTestOutputTab.ClientSize.Width, mTestOutputTab.ClientSize.Height); 
  }
  private void mRefresh_Click(object sender, System.EventArgs e)
  {
    AttachToIE();      
  }
  private void AttachToIE()
  {
    mTabSelector.SelectedTab = mPageDumpOutputTab;
    mPageDumpOutputListBox.BeginUpdate();
    mPageDumpOutputListBox.Items.Clear();
    mProcesses.Display();
    mPageDumpOutputListBox.EndUpdate();
    mPageDumpOutputListBox.Update();
  }
  protected override bool ProcessKeyPreview(ref Message m)
  {
    if (m.WParam.ToInt32() == 0x74) //==F5
    {
      AttachToIE();
      return true;
    }
    return base.ProcessKeyPreview(ref m);
  }
  private void mPageDumpOutputListBox_MouseDown(object sender, MouseEventArgs e)
  {
    int index = mPageDumpOutputListBox.IndexFromPoint(new Point(e.X,e.Y));
    if(index >= 0) mPageDumpOutputListBox.DoDragDrop(mPageDumpOutputListBox.Items[index].ToString()+ "\n", DragDropEffects.Copy);
  }
  private void mRunTests_Click(object sender, System.EventArgs e)
  {
    Globals.SetLogger(mTestOutputTabListBox);
    mTabSelector.SelectedTab = mTestOutputTab;
    mTestOutputTabListBox.Items.Clear();
    new Explorer().Run();
    mTestOutputTabListBox.Update();
  }

  private void mTestOutputTabListBox_SelectedIndexChanged(object sender, System.EventArgs e)
  {
    string line = (string) mTestOutputTabListBox.SelectedItem;
    int endoffilename = line.IndexOf(":", line.IndexOf(":") + 1);
    
    string filelineno = line.Substring(0, endoffilename);
    string[] tokens = filelineno.Split('(');
    string filename = tokens[0];
    if (tokens.Length != 2)
      return;
    tokens = tokens[1].Split(",()".ToCharArray());
    if (tokens.Length != 3)
      return;
    int lineno = Int32.Parse(tokens[0]);
    int colno = Int32.Parse(tokens[1]);
    lineno--;
    if (lineno < 0)
      lineno = 0;

    EnvDTE.DTE dte;
    try 
    {
      object o =  System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE");
      dte = (EnvDTE.DTE) o;
    }
    catch(System.Runtime.InteropServices.COMException ex)
    {
      Console.WriteLine("devenv not running...");
      Console.WriteLine("ex: " + ex.Message);
      dte = new EnvDTE.DTEClass();

    }
    dte.MainWindow.Visible = true;
    dte.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMaximize;
    dte.MainWindow.SetFocus();

    EnvDTE.Window w = dte.ItemOperations.OpenFile(filename, "{7651A701-06E5-11D1-8EBD-00A0C90F26EA}");
    w.Activate();
    string title = w.Caption;
    System.Console.WriteLine("Title: " + title);

    EnvDTE.TextDocument td = (EnvDTE.TextDocument) dte.ActiveDocument.Object("TextDocument");
    td.Selection.MoveToLineAndOffset(lineno, colno, false);
    td.Selection.ActivePoint.TryToShow(EnvDTE.vsPaneShowHow.vsPaneShowAsIs, 0);

  }
}

Logger.cs

Synopsis
using System;
using System.IO;
using System.Diagnostics;

/// <summary>
/// Summary description for Logger.
/// </summary>
public abstract class Logger
{
  public void Info(string s)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(INFO_MSG + s);
  }
  public void Info(string s, string parm1)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(String.Format(INFO_MSG + s, parm1));
  }
  public void Action(string s)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(ACTION_MSG + s);
  }
  public void Action(string s, string parm1)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(String.Format(ACTION_MSG + s, FormatString(parm1, DEFAULT_MSG_LENGTH)));
  }
  public void Action(string s, string parm1, string parm2)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(String.Format(ACTION_MSG + s, FormatString(parm1, DEFAULT_MSG_LENGTH), FormatString(parm2, DEFAULT_MSG_LENGTH)));
  }
  public void Action(string s, string parm1, string parm2, string parm3)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(String.Format(ACTION_MSG + s,
      FormatString(parm1, DEFAULT_MSG_LENGTH),
      FormatString(parm2, DEFAULT_MSG_LENGTH),
      FormatString(parm3, DEFAULT_MSG_LENGTH)));
  }
  public void Failure(string s)
  {
    mOutFunc(FormatLocation() + FAILED_MSG + s);
  }
  public void Failure(string s, string parm1, string parm2)
  {
    mOutFunc(String.Format(FormatLocation() + FAILED_MSG + s, FormatString(parm1, DEFAULT_MSG_LENGTH), FormatString(parm2, DEFAULT_MSG_LENGTH)));
  }
  public void Failure(string s, Exception e)
  {
    mOutFunc(String.Format(FormatLocation() + FAILED_MSG + s + "{0}", e.Message));
  }
  public void Event(string s)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(EVENT_MSG + s);
  }
  public void Event(string s, string parm1)
  {
    if (!Globals.options.verbose) return;
    mOutFunc(String.Format(EVENT_MSG + s, FormatString(parm1, DEFAULT_MSG_LENGTH)));
  }
  public void SetLocation()
  {
    StackTrace st = new StackTrace(true);
    StackFrame sframe = st.GetFrame(2);
    mFilename = sframe.GetFileName();
    mLineno = sframe.GetFileLineNumber() - 1;
    mColno = sframe.GetFileColumnNumber();
  }

  //-------------------------------------------------------
  //-- private/protected from here on
  //-------------------------------------------------------
  static protected readonly int DEFAULT_MSG_LENGTH = 53;
  static protected readonly string INFO_MSG   = "Info  : ";
  static protected readonly string FAILED_MSG = "FAILED: ";
  static protected readonly string ACTION_MSG = "Action: ";
  static protected readonly string EVENT_MSG  = "Event : ";
  protected delegate void WriteLineFunc(string s);
  protected WriteLineFunc mOutFunc;
  
  protected string FormatString(string s, int maxlength)
  {
    if (s.Length <= maxlength) return s;
    return s.Substring(0, maxlength - 3) + "...";
  }
  protected string FormatLocation()
  {
    return mFilename + "(" + mLineno + "," + mColno + "): ";
  }

  string mFilename;
  int mLineno;
  int mColno;
}

public class TextLogger : Logger
{
  private TextWriter mOut;
  public TextLogger(TextWriter tw)
  {
    mOut = tw;
    mOutFunc = new WriteLineFunc(WriteLine);
  }
  private void WriteLine(string s)
  {
    mOut.WriteLine(s);
  }
}

public class ListBoxLogger : Logger
{
  private System.Windows.Forms.ListBox mOut;
  public ListBoxLogger(System.Windows.Forms.ListBox lb)
  {
    mOut = lb;
    mOutFunc = new WriteLineFunc(WriteLine);
  }
  private void WriteLine(string s)
  {
    mOut.Items.Add(s);
    mOut.Update();
  }
}

MsgBoxHandler.cs

Synopsis
using System;
using System.Threading;
using System.Runtime.InteropServices;

class MsgBoxHandler
{
  [DllImport("user32.dll",EntryPoint="SendMessage")]
  private static extern int SendMessage(int _WindowHandler, int _WM_USER, int _data, int _id);
  [DllImport("user32.dll",EntryPoint="FindWindow")]
  private static extern int FindWindow(string _ClassName, string _WindowName);
  private const ushort IDCANCEL   = 0x02;
  private const ushort IDOK   = 0x01;
  private const int WM_COMMAND = 0x111;
  private const ushort BN_CLICKED = 0x00;

  private ushort myMsgBoxAction = 0;
  private Thread myMsgBoxThread;
  private AutoResetEvent myMsgBoxEvent = new AutoResetEvent(false);

  public void Start()
  {
    myMsgBoxThread = new Thread(new ThreadStart(MsgBoxThreadProc));
    myMsgBoxThread.Name = "MsgBoxThread";
    myMsgBoxThread.Start();
  }
  public void Close()
  {
    myMsgBoxThread.Abort();
  }
  public void ExpectOk()
  {
    myMsgBoxAction = IDOK;
    myMsgBoxEvent.Set();
  }
  public void ExpectCancel()
  {
    myMsgBoxAction = IDCANCEL;
    myMsgBoxEvent.Set();
  }
  public void PressMsgBoxButton(ushort buttonid)
  {
    Thread.Sleep(100); //wait for the msgbox to be available
    for(int i = 0; i < 20; ++i, Thread.Sleep(500)) //total of 10 seconds
    {
      int hwnd = FindWindow("#32770", null);
      if (hwnd != 0) 
      {
        SendMessage(hwnd, WM_COMMAND, (BN_CLICKED << 16) | buttonid, 0);
        break;
      }
    }
  }
  private void MsgBoxThreadProc()
  {
    try
    {
      for(;;)
      {
        myMsgBoxEvent.WaitOne();
        PressMsgBoxButton(myMsgBoxAction);
      }
    } 
    catch (ThreadAbortException /*ex*/)
    {
      Globals.logger.Info("MsgBoxThreadProc: exiting...");
    }
  }
}

Options.cs

Synopsis
using System;
using System.Collections;

public class Options
{
  public ArrayList tests = new ArrayList();
  public bool verbose = false;

  public void ProcessCommandLine(string[] args)
  {
    foreach (string arg in args)
    {
      if (arg.ToLower().Equals("/v") || arg.ToLower().Equals("-v"))
        verbose = true;
      else
        tests.Add(arg);
    }
  }
}

TestRunner.cs

Synopsis
using System;
using System.Collections;
using System.Reflection;

class TestException : Exception
{
  public TestException(string s) : base(s)
  {
  }
}

class TestRunner
{
  public static void Run()
  {
    Browser b = new Browser();
    try 
    {
      RunTest(GetTestInstance(Type.GetType("RunFiles")), b);
      if (Globals.options.tests.Count == 0) 
        RunAllTests(b);
      else 
        RunTests(b);

      System.Threading.Thread.Sleep(2000);
      //         b.Quit();
      b.Close();
    }
    catch (TestException ate)
    {
      Globals.logger.Failure("", ate);
    }
    catch(Exception sE)
    {
      if (b.IsAlive()) throw sE;
      Globals.logger.Failure("IE was closed an unknown agent.");
    }
  }

  private static void RunTests(Browser b)
  {
    foreach (string test in Globals.options.tests)
      RunTest(GetTestInstance(Type.GetType(test)), b);
  }
  private static void RunAllTests(Browser b)
  {
    foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
    {
      if (!IsATest(t)) continue;
      RunTest(GetTestInstance(t), b);
    }
  }
  private static WebTest GetTestInstance(Type clazz)
  {
    return (WebTest) Assembly.GetExecutingAssembly().CreateInstance(clazz.Name);
  }
  private static void RunTest(WebTest s, Browser b)
  {
    Globals.logger.Info("---- Start: {0} --------------------------", s.GetType().Name);
    try 
    {
      s.Initialize(b);
      s.Setup();
      s.Run();
    }
    catch (TestException ate)
    {
      Globals.logger.Failure("{0}", ate);
    }
    catch(Exception sE)
    {
      if (b.IsAlive())
        Globals.logger.Failure("exception thrown:", sE);
      else
        Globals.logger.Failure("IE was closed by an unknown agent.");
    }
    try 
    {
      s.Teardown();
    }
    catch(Exception sE)
    {
      Globals.logger.Failure("Teardown failed for " + s.GetType().Name, sE);
    }
    Globals.logger.Info("---- End: {0} --------------------------", s.GetType().Name);
  }
  private static bool IsATest(Type clazz)
  {
    if (!clazz.BaseType.Name.Equals("WebTest")) return false;
    return clazz.Name.StartsWith("Test");
  }
}

WebTest.cs

Synopsis
abstract class WebTest
{
  protected Browser myBrowser = null;
  public abstract void Run();
  public void Initialize(Browser b)
  {
    myBrowser = b;
  }
  public virtual void Setup()
  {
  }
  public virtual void Teardown()
  {
  }
}






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001-2010