Search code examples
c#.netbrowserwatin

Is it possible to run WatiN test code externally against target c# code?


My goal is to automate test in .NET WebBrowser control. Below code works just fine if I put my WatiN test code in the same file.

Code:

namespace WindowsFormsApplication1
{
    public partial class Form1 : System.Windows.Forms.Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }

    private void Form1_Load(object sender, EventArgs e)
        {

            //I have WebBrowser control in the form
            //so the WatiN code below works
            var t = new Thread(() =>
            {
                Settings.AutoStartDialogWatcher = false;
                var ie = new IE(webBrowser1.ActiveXInstance);
                ie.GoTo("http://www.google.com");
                ie.TextField(Find.ByClass("lst")).TypeText("this is awesome!!");
                ie.Button(Find.ByName("btnG")).Click();
            });
            t.SetApartmentState(ApartmentState.STA);
            t.Start();

        }//end form load
   }//end class

}//end namespace

But it's not good to mix test code and target code. So I would like to take WatiN test code part out and put it in separate C# file in separate project. But then if I do so, I lose reference to the Form of course.

I've searched for something called WndProc (http://dotnet.sys-con.com/node/39039) but seems like it is not really what I am looking for.

So my question is:

  1. is it possible to separate the WatiN code from target code?

  2. given the fact, it is even possible to get the Form object that's already running? (I mean getting reference of the Form from other C# console app for instance? )

  3. if so, could someone show me the sample code?

I've tried below in separate project but nothing happens after the Form1 is opened. Because the process stop at Application.Run(myform)

var t = new Thread(() =>
            {
                Form1 myform = new Form1();
                Application.Run(myform);
                myform.textBox1.Text = "really";

                Settings.AutoStartDialogWatcher = false;
                var ie = new IE(myform.webBrowser1.ActiveXInstance);
                ie.GoTo("http://www.google.com");
                ie.TextField(Find.ByClass("lst")).TypeText("this is awesome!!");
                ie.Button(Find.ByName("btnG")).Click();
            });
            t.SetApartmentState(ApartmentState.STA);
            t.Start();

Solution

  • First of all, you are really duplicating your recent question.

    I am using WatiN a lot, but for browser automation, not tests, but I don't really know, why you can't use WatiN in your tests directly. Why can't you have test project with WatiN code? Apart of that, I really have a feeling, that you need to learn C# more. You already said earlier, that you are using C# for couple days.

    As an answer to your question, you cannot really have a reference to objects, that you created in separate processes (.NET speaking - in separate AppDomain). You can't do something, like you wanted to do in your previous question, that is:

    System.Diagnostics.Process Proc = new System.Diagnostics.Process();
    Proc.StartInfo.FileName = "path_to_exe\\winformWithWebBrowserTest.exe";
    Proc.Start();
    
    WindowsFormsApplication1.Form1 form1 = new Form1();
    

    With that code you are in process A:

    1. Starting process B.
    2. Creating object of type Form1 in process A.

    There is no connection, link or whatever between process A and B. You can't simply create object or call method or whatever in process A, that lives in project B. If you need to do that, you have to google for "interprocess communication in C#". In these days you can add "WCF" to your search criteria. For example, see this question: Interprocess communication for Windows in C# (.NET 2.0) or What is the best choice for .NET inter-process communication?. But it is really not that simple, as you want. Basically it's like making process B a server/host, and process A a client.

    EDIT after OP comment

    If you want to automate only web browser control, it can be done with a little effort. You can try something like this:

    var p = Process.Start(@"path_to_exe");
    
    Thread.Sleep(1000); //Need to wait a while for that process to start, 
                        //and web browser control to initialize
    
    //Use IEUtils from WatiN library
    //We need to find a handle to window containing web browser control
    //Maybe you will have to do some other stuff to find that window and I can't
    //guarantee this will work instantly, because internally this method is enumerating
    //controls on form to find web browser control
    var htmlDocument = IEUtils.IEDOMFromhWnd(p.MainWindowHandle); 
    
    //Copy from WatiN class - ShellWindows2
    var SID_SWebBrowserApp = new Guid(0x0002DF05, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
    
    var serviceProvider = htmlDocument as WatiN.Core.Native.Windows.IServiceProvider;
    
    object objIWebBrowser;
    var guidIWebBrowser = typeof(IWebBrowser2).GUID;
    serviceProvider.QueryService(ref SID_SWebBrowserApp, ref guidIWebBrowser, out objIWebBrowser);
    
    //Stopping dialog watcher is essential
    Settings.AutoStartDialogWatcher = false;
    var ie = new IE(objIWebBrowser);
    ie.GoTo(@"http://www.google.com");
    

    If you need to use dialog watcher you could rewrite code from my answer to another question.