是否可以针对目标 C# 代码在外部运行 WatiN 测试代码?

发布于 2024-10-20 23:25:17 字数 2065 浏览 1 评论 0原文

我的目标是在 .NET WebBrowser 控件中实现自动化测试。如果我将 WatiN 测试代码放在同一个文件中,下面的代码就可以正常工作。

代码:

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

但是混合测试代码和目标代码并不好。所以我想取出 WatiN 测试代码部分并将其放入单独项目中的单独 C# 文件中。但是如果我这样做,我当然会失去对表单的引用。

我搜索了名为 WndProc (http://dotnet.sys-con.com/node/39039)的东西,但似乎它并不是我真正想要的东西。

所以我的问题是:

  1. 是否可以将WatiN代码与目标代码分开?

  2. 事实上,甚至有可能获取已经运行的 Form 对象吗? (我的意思是从其他 C# 控制台应用程序获取 Form 的引用?)

    事实上
  3. 如果是这样,有人可以向我展示示例代码吗?

我在下面的单独项目中尝试过,但打开 Form1 后没有任何反应。 因为进程停止在 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();

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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紙鸢 2024-10-27 23:25:17

首先,你确实在重复你最近的问题。

我经常使用 WatiN,但用于浏览器自动化,而不是测试,但我真的不知道为什么不能直接在测试中使用 WatiN。为什么你不能用 WatiN 代码进行测试项目?除此之外,我真的有一种感觉,你需要更多地学习 C#。您之前已经说过,您使用 C# 有几天了。

作为问题的答案,您实际上无法引用在单独的进程中创建的对象(.NET 语言 - 在单独的 AppDomain 中)。你不能做一些事情,就像你想做的那样 上一个问题,即:

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

WindowsFormsApplication1.Form1 form1 = new Form1();

使用该代码,您正在进程 A 中:

  1. 启动进程 B。
  2. 在进程 A 中创建 Form1 类型的对象。

没有进程 A 和 B 之间的连接、链接或其他任何内容。您不能简单地在项目 B 中的进程 A 中创建对象或调用方法或其他任何内容。如果您需要这样做,则必须在 google 中搜索“C# 中的进程间通信” ”。现在,您可以将“WCF”添加到您的搜索条件中。例如,请参阅以下问题: C# 中的 Windows 进程间通信 ( .NET 2.0)什么是.NET 进程间通信的最佳选择?。但事情确实没有你想的那么简单。基本上就像让进程 B 成为服务器/主机,进程 A 成为客户端。

在OP评论后进行编辑

如果您只想自动化网络浏览器控制,则可以轻松完成。您可以尝试这样的操作:

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");

如果您需要使用对话框观察程序,您可以重写代码 我对另一个问题的回答

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文