最近研究了一下watin代码,watin是开源的基于C#的Web自动化测试框,支持Ajax、firefox。其代码相当庞大,复杂。说研究,其实就是看看其中的一些片段而已。
不过还是相当有收获,在UtilityClass类中有一个FireEvent方法,其源代码如下:
public static void FireEvent(DispHTMLBaseElement element, string eventName, NameValueCollection eventObjectProperties)
{
// Execute the JScript to fire the event inside the Browser.
StringBuilder scriptCode = new StringBuilder();
scriptCode.Append("var newEvt = document.createEventObject();");
for (int index = 0; index < eventObjectProperties.Count; index++)
{
scriptCode.Append("newEvt.");
scriptCode.Append(eventObjectProperties.GetKey(index));
scriptCode.Append(" = ");
scriptCode.Append(eventObjectProperties.GetValues(index)[0]);
scriptCode.Append(";");
}
scriptCode.Append("document.getElementById('" + element.uniqueID + "').fireEvent('" + eventName + "', newEvt);");
try
{
IHTMLWindow2 window = ((IHTMLDocument2) element.document).parentWindow;
RunScript(scriptCode.ToString(), window);
}
catch (RunScriptException)
{
…
}
}
public static void RunScript(string scriptCode, IHTMLWindow2 window)
{
RunScript(scriptCode, "javascript", window);
}
public static void RunScript(string scriptCode, string language, IHTMLWindow2 window)
{
try
{
window.execScript(scriptCode, language);
}
catch (Exception ex)
{
throw new WatiN.Core.Exceptions.RunScriptException(ex);
}
}
FireEvent用来模拟select选择框选择,传入鼠标按键参数,在windows程序种调用web JavaScript函数激发onchange事件,而且支持Ajax测试,不过我没有测试成功,最关键的如何让程序执行时等待几秒,Thread.Sleep()语句肯定不行,应当将测试代码都写到axWebBrowser1_DocumentComplete事件里,而且我发现使用MessageBox.Show语句能等待axWebBrowser1事件在后台执行,而Thread.Sleep()语句则使axWebBrowser1事件,前台程序都处于等待状态。如下代码:
private void axWebBrowser1_DocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
{
//这里需要等待几秒让Ajax加载
if (axWebBrowser1.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
return;//这样代码不行
}
while (axWebBrowser1.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
MessageBox.Show("waiting for document state complete. Last state was '" + axWebBrowser1.ReadyState + "'"); //弹出确认框可以达到要求的效果,后台axWebBrowser1继续执行,而程序暂停
Thread.Sleep(100);//达不到要求的效果,后台axWebBrowser1,主程序全部暂停
}
if (e.uRL.ToString().ToLower().IndexOf("pay.htm") > 0)
{
IHTMLDocument2 doc = (IHTMLDocument2)this.axWebBrowser1.Document;
if (doc != null)
{
mshtml.HTMLSelectElement sellanguage = (mshtml.HTMLSelectElement)doc.all.item("signup_language_preference", null);
sellanguage.value = "你要选的值";
NameValueCollection collection = new NameValueCollection();
collection.Add("button", "1");
FireEvent((DispHTMLBaseElement)sellanguage, "onchange", collection);
}
}
textBox1.Text = e.uRL.ToString();
}
对于如何异步执行程序,真的无法成功,而Ajax测试相信也是一项需求很大的课题,恳请大牛高人援手相助,惠人惠己。
另:
James McCaffrey 博士的 AJAX 测试自动化(http://msdn.microsoft.com/zh-cn/magazine/cc163479.aspx)用JavaScript的
window.setTimeout函数也能完成这一工作,但Watin的用dotnet的方法应该更自然一些(没办发谁让咱是完美主义者呢^-^).