Unit Testing with WatiN and NUnit
It seems that the common theme among SO questions regarding WatiN have to do with actually getting the thing working and I'm no exception.
I've downloaded the latest release of WatiN (2.0.20.1089) and am trying to create the NUnit / WatiN equivalent of Hello, World:
using WatiN.Core;
using NUnit.Framework;
namespace Foo.Browser.Tests
{
[TestFixture]
public class BrowserTests
{
[Test]
[STAThread]
public void ExampleTest()
{
IE ie = new IE("http://www.google.com");
ie.TextField(Find.ByName("q")).TypeText("WatiN");
ie.Button(Find.ByValue("Google Search")).Click();
Link link = ie.Link(Find.ByUrl("http://watin.sourceforge.net/"));
Assert.That(link.Text == "WatiN Home");
}
[Test]
public void FirefoxTest()
{
FireFox ff = new FireFox("http://www.google.com");
ff.TextField(Find.ByName("q")).TypeText("WatiN");
ff.Button(Find.ByValue("Google Search")).Click();
Link link = ff.Link(Find.ByUrl("http://watin.sourceforge.net/"));
Assert.That(link.Text == "WatiN Home");
}
}
This tips IE(8) over after an eventual timeout with the following stack trace:
at WatiN.Core.Utilit开发者_StackOverflowyClasses.TryFuncUntilTimeOut.ThrowTimeOutException(Exception lastException, String message) at WatiN.Core.UtilityClasses.TryFuncUntilTimeOut.HandleTimeOut() at WatiN.Core.UtilityClasses.TryFuncUntilTimeOut.Try[T](DoFunc'1 func) at WatiN.Core.WaitForCompleteBase.WaitUntil(DoFunc'1 waitWhile, BuildTimeOutExceptionMessage exceptionMessage) at WatiN.Core.Native.InternetExplorer.IEWaitForComplete.WaitWhileFrameDocumentNotAvailable(IWebBrowser2 frame) at WatiN.Core.Native.InternetExplorer.IEWaitForComplete.WaitForFramesToComplete(IHTMLDocument2 maindocument) at WatiN.Core.Native.InternetExplorer.IEWaitForComplete.WaitForFramesToComplete(IHTMLDocument2 maindocument) at WatiN.Core.Native.InternetExplorer.IEWaitForComplete.WaitForCompleteOrTimeout() at WatiN.Core.WaitForCompleteBase.DoWait() at WatiN.Core.DomContainer.WaitForComplete(IWait waitForComplete) at WatiN.Core.IE.WaitForComplete(Int32 waitForCompleteTimeOut) at WatiN.Core.DomContainer.WaitForComplete() at WatiN.Core.Browser.GoTo(Uri url) at WatiN.Core.IE.FinishInitialization(Uri uri) at WatiN.Core.IE.CreateNewIEAndGoToUri(Uri uri, IDialogHandler logonDialogHandler, Boolean createInNewProcess) at WatiN.Core.IE..ctor(String url) at Foo.Browser.Tests.BrowserTests.ExampleTest() in C:\Development\Foo\Foo.Browser.Tests\BrowserTests.cs:line 19
I have the requisite config file in my bin\debug folder (Foo.Browser.Tests.dll.config) as specified on the WatiN documentation page, so what else is it likely to be? Does anyone have any suggestions for what might be causing the problem?
Phil,
Have a look at the InnerException of the thrown TimeoutExcepetion. This will most probably contain more info to solve your issue.
HTH Jeroen van Menen Lead dev WatiN
Looks like Phil may have answered your question, but I found your example to throw exceptions as well. To fix said issue I changed the Link Find to look by attribute (href) as below.
[Test]
public void ExampleTest()
{
IE ie = new IE("http://www.google.com");
ie.TextField(Find.ByName("q")).TypeText("WatiN");
ie.Button(Find.ByValue("Google Search")).Click();
Link link = ie.Link(Find.By("href", "http://watin.sourceforge.net/"));
Assert.That(link.Text == "WatiN Home");
}
Note that I only tested for IE as this box doesn't have FireFox installed.
I had a similar issue with this code
var link1 = WebBrowser.Current.Link(Find.ByText("Log Off"));
var exists = link1.Exists;
which was resolved thus...
var link1 = WebBrowser.Current.Link(Find.ByText("Log Off"));
link1.WaitUntilExists();
var exists = link1.Exists;
Didnt run into big issues WatiN via xUnit.net myself.
Here's a laundry list, which people should feel free to edit into and/or suggest updates to:
- Is the NUnit process admin? Is the IE its spawning admin? have a look in Task Manager. (Not that running as admin is a panacea - you ideally want to avoid this, but as a way of eliminating reasons for it not to work)
- Does running via TestDriven.net, CodeRush or ReSharper help?
- Have you [referenced the relevant dlls as a way to get] the dependent DLLs such as shdocvvw.dll sitting alongside your test assembly] ?
- Have you tried seeing if Fiddler shows anything timing out?
- Have you tried browsing by hand to make sure any security dialogs have been OK'd in the context? e.g., sometimes your test context might be admin whereas your normal browsing profile might not be (depends on browser) - e.g., if you have ignored a cert warning in one context but not the other this might cause an issue.
One big gotcha that bit me wrt WatiN is that after a few thousand invocations on WS08 IE will refuse to cooperate until you log off and on again (see one of my outstanding questions). The route I went down (I needed fail-proof monitoring) was to use the WatiN recorder and then port those to HtmlAgilityPack with LINQ querying with hand-coded GET/POST stuff using WebRequest which works quite well but obviously doesnt handle JavaScript which obviously renders it academic for many scenarios.
I experienced similar problems to Ruben's regarding the logoff/logon situation. The best reasoning I've been able to find so far has to do with the fact that WatiN is running IE using a COM server. There may be issues regarding the disposal, but that's a whole other Oprah...
As far as the timeout situation goes, it happens every now and then, but it typically pops up a message in the NUnit console, and continues on. One big difference that I can see between your implementation and mine is that I'm running the IE instance as a singleton object. That way, I never have to close and reopen IE between tests, and I haven't experienced the logoff/logon issue since. Consequently, my test cycles are shorter, even when IE is visible and not running in the background.
public void ExampleTest()
{
IE ie = new IE("http://www.google.com");
ie.TextField(Find.ByName("q")).TypeText("WatiN");
var btnSearch = ie.Button(Find.ByValue("Google Search"));
btnSearch.ClickNoWait();
ie.WaitforComplete();
Link link = ie.Link(Find.ByUrl("http://watin.sourceforge.net/"));
Assert.That(link.Text == "WatiN Home");
}
精彩评论