tag:blogger.com,1999:blog-82668720106777203352024-03-13T22:53:21.331+01:00WatiN and moreJeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.comBlogger43125tag:blogger.com,1999:blog-8266872010677720335.post-63179644880317975672011-03-14T22:50:00.001+01:002011-03-14T22:51:52.258+01:00WatiN has a new home<p>After some work in the last month, WatiN has a new home: <a href="http://watin.org/">http://watin.org/</a></p> <p>Most of the layout has stayed the same but all the content on the pages have been updated to the recent state of affairs. </p> <p>The website is now running on WordPress. This makes it much easier to update the site but also to give others rights to add/edit content on the site. If you find anything not working (links for instance) or are interested in helping out maintaining the site, let me know!</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-41691049432366281462011-02-16T16:40:00.001+01:002011-02-16T16:40:36.618+01:00Released WatiN 2.0 Final<p>Last week I have release WatiN 2.0 Final (2.0.50.1179). You can download the zip file from Sourceforge:</p> <p><a href="http://sourceforge.net/projects/watin/files/WatiN%202.x/2.0%20Final/WatiN-2.0.50.1179.zip/download">http://sourceforge.net/projects/watin/files/WatiN%202.x/2.0%20Final/WatiN-2.0.50.1179.zip/download</a></p> <p>or install it using NuGet (need to have the Package Manager console for Visual Studio 2010 installed, get it at <a href="http://nuget.org/">nuget.org</a>). To add it to your project is as simple as:</p> <p>PM> Install-Package WatiN</p> <p>The release notes can be found on the new website <a href="http://watin.org/">http://watin.org</a> (which is still in flux but getting there)</p> <p><a href="http://watin.org/documentation/release-2-0-50-11579/">http://watin.org/documentation/release-2-0-50-11579/</a></p> <p>Enjoy Testing with WatiN!</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-1952172214562710812010-04-02T17:53:00.001+02:002010-04-02T17:53:52.118+02:00jQTouch detail style<p>I’m working on a mobile application for the iPhone and I am using <a href="http://jqtouch.com" target="_blank">jQTouch</a> to make the UI look like an iPhone app. jQTouch seriously helps you to quickly create a nice looking UI  but sometimes you need to write your own css to create the layout you want.</p> <p>I needed a detail page with data shown like the contact details do on the iPhone. Since none of the jQTouch themes had some class that I could use, I sat down and finally came up with this little piece of css:</p> <script src="http://gist.github.com/353253.js?file=jQTouch.detail.css"></script> <p>Now all you need to do is apply the detail class to your li element and place the name and the value inside two divs like so</p> <script src="http://gist.github.com/353253.js?file=DetailExampleUsage.html"></script> <p>And the result will look like</p> <p><img src="http://content.screencast.com/users/JvMenen/folders/Jing/media/aa5d595f-18fd-436d-bf88-c7ac4c199c2a/00000001.png" /></p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:23c1a684-dd59-4414-8300-e7f3eb55e4cd" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/jQTouch" rel="tag">jQTouch</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-35026022553260779772010-03-29T17:38:00.001+02:002010-03-29T17:38:46.085+02:00TDD Workshop<p>#shamelessplug</p> <p>Last month I gave a very successful TDD workshop. If you are interested in a TDD workshop, know about C# or Java and happen to be in the Netherlands, have a look at our schedule <a href="http://bit.ly/TDDWorkshop" target="_blank">here</a> (in Dutch) and read the <a href="http://bit.ly/bjDja4" target="_blank">blog about our workshop</a> (also in Dutch).</p> <p>I’m also in the process of creating a 2 day WatiN training. I’ll blog about this as soon as more info is available.</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-12411314142542245112010-01-15T17:44:00.001+01:002010-01-15T17:44:30.856+01:00Browser.AttachTo<T> and IAttachTo<p>In WatiN RC1 the functionality to attach to a browser instance has had a complete redo. This had two reasons:</p> <ol> <li>Being able to attach to a browser in a browser agnostic way.</li> <li>Being able to return your custom browser type.</li> </ol> <p>Download the example code <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/Adding%20an%20AttachToHelper.zip" target="_blank">here</a></p> <h4>From the old way to a browser agnostic way</h4> <p>If you don’t intend to run your tests with different browsers, you still need to make a small change in your code when upgrading to WatiN RC1.</p> <p><a href="http://lh3.ggpht.com/_LPItL_MawEI/S1CbVYQVLKI/AAAAAAAAAHs/TuERTHh-r2E/s1600-h/image%5B3%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="31" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/S1CbVml_3OI/AAAAAAAAAHw/K6fKmpQqCug/image_thumb%5B1%5D.png?imgmax=800" width="383" border="0" /></a> </p> <p>needs to be changed into</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/S1CbV1_wogI/AAAAAAAAAH0/_VSxK7R4BoE/s1600-h/image%5B8%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="30" alt="image" src="http://lh5.ggpht.com/_LPItL_MawEI/S1CbWcOLumI/AAAAAAAAAH4/1VSKs7aU2ak/image_thumb%5B4%5D.png?imgmax=800" width="396" border="0" /></a> </p> <p>which is the same as</p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/S1CbWkz_QyI/AAAAAAAAAH8/jHJnB9RaUfg/s1600-h/image%5B14%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="32" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/S1CbWyIyiYI/AAAAAAAAAIA/XnxH8Qf-54A/image_thumb%5B8%5D.png?imgmax=800" width="425" border="0" /></a> </p> <p>and the same as</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/S1CbXTkOkxI/AAAAAAAAAIE/s2QjR-afLwY/s1600-h/image%5B19%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="32" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/S1CbXvWQusI/AAAAAAAAAII/tJNUL87oRgA/image_thumb%5B11%5D.png?imgmax=800" width="522" border="0" /></a> </p> <p>As you can see in the last example, you can pass in a type which should inherit WatiN.Core.Browser. The following example shows you how to utilize this method in situations where you get a browser instance injected into your test code. In the example the link that is clicked on will open up a new browser instance and we want to verify the text in this newly opened browser instance.</p> <p><a href="http://lh3.ggpht.com/_LPItL_MawEI/S1CbYJfmtCI/AAAAAAAAAIM/i0Cr3a5cOFY/s1600-h/image%5B24%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="320" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/S1CbYTyABkI/AAAAAAAAAIQ/37LiT315DwA/image_thumb%5B14%5D.png?imgmax=800" width="600" border="0" /></a> </p> <p>Thanks to this new AttachTo(type, findBy) method there is no knowledge at all of the used browser type inside my test code.</p> <h4>Returning a custom Browser type from AttachTo()</h4> <p>Many of us who use WatiN will probably use their own custom super duper version of WatiN.Core.IE. Providing new or different behavior then the default IE implementation does. See <a href="http://www.lostechies.com/blogs/dahlbyk/archive/2010/01/12/http-error-codes-in-watin-1-3.aspx" target="_blank">here</a> for example  (and yes this part of the post was also a little bit sparked by their need to write their own AttachTo methods).</p> <p>Here is my great MyIE class which overrides the ToString method and returns the Title and Url of the shown page (it’ll surf just as an example).</p> <p><a href="http://lh3.ggpht.com/_LPItL_MawEI/S1CbY2SzSiI/AAAAAAAAAIU/hXgAbrN4Vtc/s1600-h/image%5B30%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="186" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/S1CbZO9ZKeI/AAAAAAAAAIY/yYCbZxqiOnU/image_thumb%5B18%5D.png?imgmax=800" width="416" border="0" /></a> </p> <p>And now I want to be able write</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/S1CbZmadknI/AAAAAAAAAIc/XfwQsNkakgE/s1600-h/image%5B35%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="33" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/S1CbaFU2MXI/AAAAAAAAAIg/Zw3Tmhw3e-w/image_thumb%5B21%5D.png?imgmax=800" width="497" border="0" /></a> </p> <p>When I run this piece of code, WatiN will throw this exception:</p> <p><strong>WatiN.Core.Exceptions.WatiNException:  <br /></strong><strong>No AttachToHelper registered for type WatiN.Examples.Tests.MyIE.</strong></p> <p><font color="#808080">That does sound like Ican register an AttachToHelper for a browser Type, doesn’t it. The Browser class provides a method RegisterAttachToHelper doing just that.</font></p> <p><font color="#808080">So we need to create our own AttachToMyIEHelper class. Since MyIE is inheriting IE, AttachToMyIEHelper will inherit AttachToIEHelper. And then it is just a matter of overriding the CreateBrowserInstance method, return a new instance of MyIE and we are done. Here is the implementation:</font></p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/S1CbaXekZ9I/AAAAAAAAAIk/S91OcvN511c/s1600-h/image%5B40%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="125" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/S1Cba7_uAVI/AAAAAAAAAIo/t3I_v2WhYTE/image_thumb%5B24%5D.png?imgmax=800" width="540" border="0" /></a> </p> <p>And this code shows you how to register the new AttachToMyIEHelper and use it in your tests.</p> <p><a href="http://lh5.ggpht.com/_LPItL_MawEI/S1CbbBvMr3I/AAAAAAAAAIs/mVhKGZRB_ok/s1600-h/image%5B45%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="407" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/S1CbbnzdqNI/AAAAAAAAAIw/alIhRKIbEDI/image_thumb%5B27%5D.png?imgmax=800" width="594" border="0" /></a> </p> <p>Enjoy testing with WatiN.</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e7ca0053-e73b-4e97-85db-32d97901b3b5" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com5tag:blogger.com,1999:blog-8266872010677720335.post-10018002902144572152010-01-15T16:24:00.001+01:002010-01-15T16:24:35.032+01:00Combine WatiN and White to test Silverlight<p>Googling the web for stuff written about WatiN, I came across this very interesting article to combine forces between WatiN and White. </p> <p><a href="http://leobartnik.net/blog/2010/01/silverlight-uiautomation-testing-using.html">http://leobartnik.net/blog/2010/01/silverlight-uiautomation-testing-using.html</a></p> <p>It also sparked this idea:</p> <p>var  silverlightControl = browser.Control<SilverlightControl>(Find.ByFirst());</p> <p>silverlightControl.Button(Find.ById(“someButton”)).Click;</p> <p>Interesting.</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a0550051-d49d-49f4-8b31-c17c245286a2" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-16334549356258658562009-12-22T14:12:00.001+01:002009-12-22T14:13:33.190+01:00Released WatiN 2.0 RC 1<p>A short shout out to announce the release of WatiN 2.0 Release Candidate 1.</p> <p>Many fixes and new features since the last beta 1 release way back in March. I’m still compiling the list of changes so check back on <a href="http://watin.sourceforge.net/releasenotes-2-0-20-1089.html" target="_blank">this</a> page later this week. But if you follow my blog you are well informed already. If you haven’t been using beta 1, start reading the release note of that release <a href="http://watin.sourceforge.net/releasenotes-2-0-10-x.html" target="_blank">here</a>.</p> <p>And of course  you want to <a href="http://sourceforge.net/projects/watin/files/WatiN%202.x/2.0%20Release%20candidates/WatiN-2.0.20.1089-net-2.0.zip/download" target="_blank">download the new release</a>.</p> <p>Enjoy testing with WatiN!</p> <p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e1a30529-5f0d-4cd8-9778-f68d3250782b" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div></p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-87385885988783008152009-12-11T17:45:00.001+01:002009-12-18T23:27:04.323+01:00Wrapping complex logic in a Control<p><strong>Update 18 December 2009</strong>: Added missing file to code download</p> <p>WatiN is all about simplifying the way you can interact with a web browser and the elements on a page. Simple elements are just wrapped (like divs, links and alike) but for more complex elements WatiN offers you functionality which hides complex interactions with the browser. For instance TextField.TypeText will not only set the value of an input field but will also fire all the appropriate events, basically simulating a real user typing in text.</p> <p>But what if you want to automate/model some action that involves complex logic and/or multiple elements. Yes indeed I am referring to all those ASP and third party controls out there. In this post I will show you how to create your own control which you can use as if it is an element on the page and natively supported by WatiN. </p> <p>You can download the code for this post <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/Creating%20a%20DatePicker%20control.zip" target="_blank">here</a> (which also contains a build of WatiN 2.0 RC1)</p> <h4>The control to automate: JQuery-UI Datepicker</h4> <table cellspacing="5" cellpadding="2" width="600" border="0"><tbody> <tr> <td valign="top" width="332"> <p>I’m going to show you how to create a basic control for the <a href="http://jqueryui.com/demos/datepicker/" target="_blank">jQuery UI Datepicker</a>. But that’s simple you might think, just use TypeText of the TextField class, the WatiN wrapper for input elements of type text. True, but then I need to think about formating the date correctly every time I automate a datepicker. And there might be other things I would like to check on the datepicker (see  <a href="http://jqueryui.com/demos/datepicker/" target="_blank">jQuery-UI Datepicker</a> for all the options that can be set and read on this widget). So I’m going to use the javascript API of the datepicker to automate the control.</p> </td> <td valign="top" width="251"><a href="http://lh5.ggpht.com/_LPItL_MawEI/SyJ3BajpMpI/AAAAAAAAAG0/M5dTh0nYY6s/s1600-h/image%5B7%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="23" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/SyJ3Bpr6toI/AAAAAAAAAG4/bWktoo56RNg/image_thumb%5B3%5D.png?imgmax=800" width="244" border="0" /></a><a href="http://lh4.ggpht.com/_LPItL_MawEI/SyJ3BwcarkI/AAAAAAAAAG8/ROm7q20-U9c/s1600-h/image%5B10%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="203" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/SyJ3CQEnzgI/AAAAAAAAAHA/pvpynAPrYYI/image_thumb%5B4%5D.png?imgmax=800" width="244" border="0" /></a></td> </tr> </tbody></table> <p>Wondering how to use this control in your test code?</p> <p><a href="http://lh5.ggpht.com/_LPItL_MawEI/SyJ3Cr8whPI/AAAAAAAAAHE/LExF0DfKHEs/s1600-h/image%5B18%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="49" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SyJ3C5eknkI/AAAAAAAAAHI/vZL1HEVlFIs/image_thumb%5B8%5D.png?imgmax=800" width="517" border="0" /></a> </p> <p>Looks familiar (and simple) doesn’t it.</p> <h4>The implementation of DatePicker</h4> <p>To create the control I need a root WatiN.Core.Element subtype which will be the base/root Element for my DatePicker control. Since a html input of type text serves as the root element for the jQuery UI datepicker widget, it makes sense that DatePicker will use TextField as its root Element.</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SyJ3DFPxq1I/AAAAAAAAAHM/7lSEYelEUX4/s1600-h/image%5B19%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="84" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SyJ3DTow6KI/AAAAAAAAAHQ/T0sXpJgdIGE/image_thumb%5B9%5D.png?imgmax=800" width="419" border="0" /></a></p> <p>Since I decided I’m going to use the datepicker’s javascript API, the control needs to execute scripts inside the browser. Fortunately WatiN offers this functionality through the RunScript() and Eval() methods, both exposed by the DomContainer class. Control<T>, the base class for every control, exposes the property Element which returns the root Element of the control, in this case TextField. From there we can get to the DomContainer to execute javascript using Eval().</p> <p><a href="http://lh5.ggpht.com/_LPItL_MawEI/SyJ3D-2X2WI/AAAAAAAAAHU/jpoX6fQ5lFU/s1600-h/image%5B24%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="82" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SyJ3EKaZvRI/AAAAAAAAAHY/1brHp5uTmDw/image_thumb%5B12%5D.png?imgmax=800" width="429" border="0" /></a> </p> <p>Next thing to do is to create the javascript to set the date using the API of the jQuery datepicker. This is what the script needs to look like to set the date to 10 December 2009 (indeed the month is 11, a javascript thingy):</p> <p>window.jQuery(<em>element</em>).datepicker(‘setDate’, new Date(<em>2009, 11, 10</em>));</p> <p>To make sure that the javascript references the correct html element in the DOM, I will make use of the new method  GetJavascriptElementReference(), available on every (subtype of) Element (in WatiN 2.0 RC1). And of course the Date should be created  correctly.</p> <p>I’m also using window.jQuery() instead of window.$() to make sure this script will also work when $() is not a shortcut for the jQuery() function (but instead is used by some other javascript library like Prototype).</p> <p>I will combine all this in the setter part of the Date property of the DatePicker control:</p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/SyLPIM3rjvI/AAAAAAAAAHc/c42G57yxzZ0/s1600-h/image%5B3%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="171" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SyLPIZlWiLI/AAAAAAAAAHg/oXMsiFCptWI/image_thumb%5B1%5D.png?imgmax=800" width="613" border="0" /></a> </p> <p>For the getter part there is one catch, transforming the returned javascript date in to a DateTime instance. Fortunately DateTime.Parse parses a UTC date format without any problem, so I let the javascript return the date in such a format.</p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/SyLPI93YvEI/AAAAAAAAAHk/GWD1knfvQlQ/s1600-h/image%5B7%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SyLPJEUVDqI/AAAAAAAAAHo/KAP0RCi9BPY/image_thumb%5B3%5D.png?imgmax=800" width="614" border="0" /></a> </p> <p>Now that we can set and get the date of the jQuery UI Datepicker widget we can start using it in our tests. And it offers a create place to add more functionality. </p> <h4>To conclude</h4> <p>I hope this post will help you start creating controls for your own or third party controls. There is much more that you can do so check out the <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/Creating%20a%20DatePicker%20control.zip" target="_blank">download</a> with this post to see:</p> <ul> <li>How to restrict the use of this control to input elements which are a datepicker. </li> <li>How to handle Date = null and reading a null date. </li> <li>How to read options set on a datepicker widget instance. </li> </ul> <p>There is also a <a href="http://code.google.com/p/watin-contrib/" target="_blank">WatiN-Contrib</a> project started on Google code. So if you like to share your third party WatiN control library, let us know.</p> <p>Enjoy testing with WatiN!</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:5d5a4e41-7bf6-4a1a-bbf5-e93a7d04be84" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com1tag:blogger.com,1999:blog-8266872010677720335.post-12668468759086717692009-12-06T20:57:00.001+01:002009-12-06T21:12:22.589+01:00Using WatiN to parse and scrape HTML<p>Of course you can scrape web pages with WatiN so why this blog post you might ask. Well, with the out-of-the-box WatiN browser support you need to instantiate a browser to get the HTML for a page and scrape it. If you don’t need to interact with the page, like clicking on links, type in some text or rely on cookies for session state, you don’t need all the overhead (memory, start up time) of the browser. </p> <p>This article will show you how you can use WatiN browserless by implementing a new browser: MsHtmlBrowser, using techniques described in <a href="http://radio.javaranch.com/balajidl/2006/01/18/1137606354980.html" target="_blank">this article</a>. </p> <p>For this code I use the current development code which will soon be released as WatiN 2.0 RC. You can download the code for this post <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/MsHtmlBrowser.zip" target="_blank">here</a>.</p> <h4>Load a url with HTMLDocumentClass</h4> <p>The trick to make this work is to make use of IPersistStreamInit and HTMLDocumentClass. </p> <p>First lets get the definition of IPersistStreamInit in place:</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SxwMrsWxj7I/AAAAAAAAAGM/L-lt2xyEXZI/s1600-h/image%5B10%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="167" alt="image" src="http://lh5.ggpht.com/_LPItL_MawEI/SxwMsJDcscI/AAAAAAAAAGQ/o9EeWo77s_Y/image_thumb%5B6%5D.png?imgmax=800" width="593" border="0" /></a> </p> <p>And this is how we can combine it with the HTMLDocumentClass (don’t forget to add a reference to the assembly Microsoft.mshtml.dll distributed with WatiN):</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SxwMsmxhdHI/AAAAAAAAAGU/kJf-_0Opkqg/s1600-h/image%5B11%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="166" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SxwMs9ImcUI/AAAAAAAAAGY/xgz5nYWdnOo/image_thumb%5B7%5D.png?imgmax=800" width="611" border="0" /></a> </p> <h4>Using multi browser support in WatiN 2.0</h4> <p>Knowing this we now need to give this code a place in the WatiN architecture. With the introduction of multi browser support in WatiN 2.0, the architecture of the WatiN API has been changed to allow adding new implementations for different browsers without having to change the WatiN.Core code. To create a new Browser implementation we need to create concrete implementations for the INative* interfaces specific for the browser we are adding. Since we are basing our new browser implementation on the same mshtml dll that Internet Explorer uses, we can reuse a lot of the IE specific native classes already available in the WatiN.Core.Native.InternetExplorer namespace. </p> <p>But since we don’t want to use WatiN.Core.IE and need to use WatiN.Core.Browser to tap into the WatiN architecture, we need to create our own browser class. Lets call it MsHtmlBrowser (inheriting the abstract class Browser). This forces us to implement 2 abstract methods (WaitForComplete and Close) and 1 abstract property (NativeBrowser). Lets focus on implementing the NativeBrowser property.</p> <h4>Implementing MsHtmlNativeBrowser</h4> <p>NativeBrowser returns a type implementing INativeBrowser. So lets create a class MsHtmlNativeBrowser which implements INativeBrowser. This requires several methods and properties to be implemented. Many of these we can’t provide an implementation for since we aren’t wrapping a real browser. Two of these we need to focus on NavigateTo(url) and the property NativeDocument.</p> <p>As you might guess, we can add our code (to load a page in an HtmlDocumentClass instance) to the NavigateTo method. After initialization of the object we wrap it into an IEDocument which will be returned by the NativeDocument property. Following the implementation. All the other methods do throw a NotImplementedException.</p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/SxwMtRrY-PI/AAAAAAAAAGc/ix4waH04vTU/s1600-h/image%5B16%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="371" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/SxwMt-5LD9I/AAAAAAAAAGg/FTkk9-PWhes/image_thumb%5B10%5D.png?imgmax=800" width="599" border="0" /></a> </p> <p>Back to implementing MshHtmlBrowser.</p> <h4>MsHtmlBrowser continued</h4> <p>Now that we have MsHtmlNativeBrowser, we can return an instance of this class in the NativeBrowser property of MsHtmlBrowser.</p> <p>The implementation of the Close method is empty since we don’t have a real browser we need to close. You might consider disposing the instance of MsHtmlNativeBrowser here.</p> <p>For the WaitForComplete method we can reuse functionality in the IEWaitForComplete class by passing in the IEDocument instance of the MsHtmlNativeBrowser. </p> <p>This results in the following implementation:</p> <p><a href="http://lh3.ggpht.com/_LPItL_MawEI/SxwMvuk4Q7I/AAAAAAAAAGk/xdKmMaCPme4/s1600-h/image%5B21%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="449" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SxwMw5COFUI/AAAAAAAAAGo/dT6UbT9fqs0/image_thumb%5B13%5D.png?imgmax=800" width="597" border="0" /></a> </p> <p> </p> <h4>Using the new MsHtmlBrowser</h4> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SxwMxKDTuFI/AAAAAAAAAGs/p-iVTAVmNJw/s1600-h/image%5B28%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="237" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SxwMxqwdQOI/AAAAAAAAAGw/iadh1sS40zs/image_thumb%5B18%5D.png?imgmax=800" width="486" border="0" /></a> </p> <p></p> <p></p> <p></p> <p></p> <p>Which concludes this example on creating a browserless Browser implementation. </p> <p>Enjoy testing with WatiN!</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a6cb86e1-1abc-4fba-b47c-e477b03582c9" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com1tag:blogger.com,1999:blog-8266872010677720335.post-13390727933521261422009-10-26T14:39:00.001+01:002009-10-26T14:39:19.531+01:00WatiN and MbUnit, a nice combo<p>Just a shameless repost of a mail <a href="http://blog.bits-in-motion.com" target="_blank">Jeff Brown</a> did send to the WatiN mailinglists. Interesting stuff, go check it out!</p> <h3>ANN: New samples for using WatiN with MbUnit.</h3> <p>I just released Gallio / MbUnit v3.1 Update 1.</p> <p>It's mainly a bug fix release but I also added some new samples <br />demonstrating one good way of using WatiN with MbUnit.</p> <p>The sample introduces a new custom attribute called [Browser] with some <br />fancy behavior like: <br /> <br /> * Capturing a screenshot if the test fails (or whenever you like). <br /> * Embedding a video capture of the test run if the test fails (or whenever <br />you like). <br /> * Running the same test repeatedly with different browsers. <br /> <br />The code is pretty easy to use so if you're already using MbUnit v3 and <br />WatiN then you should find it pretty easy to incorporate some of these <br />features from the samples into your own tests. <br /> <br />After installing Gallio v3.1 Update 1, look in %PROGRAMFILES%\Gallio\samples <br />for the WatiN samples and unzip them to a location of your choice.  You'll <br />need Visual Studio 2008 SP1 to run them out of the box. <br /> <br />Here's one of the sample tests to give you an idea of how this looks:</p> <p> <br />       /// <summary> <br />       /// Runs the same test repeatedly with different browsers. <br />       /// </summary> <br />       [Test] <br />       [Browser(BrowserType.IE)] <br />       [Browser(BrowserType.FireFox)] <br />       [Browser(BrowserType.Chrome)] <br />       public void MultipleBrowsers() <br />       { <br />           GoogleSearchPage.GoTo(Browser); <br />           Browser.Page<GoogleSearchPage>().Search("Fiddlesticks"); <br />       }</p> <p> <br />Full announcement and download links: <br /><a href="http://blog.bits-in-motion.com/2009/10/announcing-gallio-and-mbunit-v31-update.html">http://blog.bits-in-motion.com/2009/10/announcing-gallio-and-mbunit-v31-upda <br />te.html</a></p> <p> <br />You can also see a sample video capture from a previous release here: <br /><a href="http://www.youtube.com/watch?v=rN0CmutflFs">http://www.youtube.com/watch?v=rN0CmutflFs</a> <br /></p> <p>Enjoy, <br />Jeff.</p> <p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a3eee2d0-2721-425d-9d43-cbb5284d3047" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div></p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com3tag:blogger.com,1999:blog-8266872010677720335.post-84109463882529683682009-08-26T14:13:00.001+02:002009-08-26T14:13:42.193+02:00FREE Agile Software Development seminar by David Hussman<p>This is a shameless plug for a <strong><em>FREE</em></strong> presentation by David Hussman about Agile Software Development. So if you are in the Netherlands on September the 16th sign up! </p> <p>Following the invitation for this <strong><em>FREE</em></strong> event (or visit the LinkiT site for <a href="http://www.linkit.nl/support/nieuws/agenda?entry=20090817113352" target="_blank">the dutch invitation</a>)</p> <h3>Introducing Agile Software Development, by David Hussman</h3> <p>On September 16 LinkiT projects provides a presentation on Agile Software Development. The presentation will be given by David Hussman. David Hussman coaches organizations all over the world to adopt and apply Agile principles, techniques and tools. From the recent past there is a close link between David and LinkiT projects, created by an intense collaboration.</p> <p>For more information about David Hussman, see <a href="http://74.125.79.132/translate_c?hl=en&ie=UTF-8&sl=nl&tl=en&u=http://www.devjam.com/&rurl=translate.google.nl&usg=ALkJrhj4d1Fj7gjYfjfBHO8tQxRksofPwg">www.devjam.com.</a></p> <p>The presentation consists of two parts. In the first part David talks about why Agile Software Development came to existence, how to make the transition from waterfall to Agile, what pitfalls there may arise, and how to stay agile. In the second part of the presentation David will zoom in on a number of techniques used in Agile Software Development.</p> <p>Agile software development is currently 'hot'. The most popular methods are currently Scrum and XP, with Scrum being project management focused and XP focuses on the development techniques.</p> <p>Date / Time: Wednesday, September 16 18:00-21:00</p> <p>Location: The office of LinkiT, Rijnzathe 9, de Meern, Netherlands (<a href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=linkit+de+meern+nederland&sll=37.0625,-95.677068&sspn=65.645551,120.498047&ie=UTF8&ll=52.07915,5.054483&spn=0.025425,0.058837&z=15&iwloc=A" target="_blank">here</a>)</p> <p><b>Attending the presentation is free of charge, but the number of seats is limited!</b></p> <p>Audience: Developers, Project Managers, IT Managers, CIOs, Architects & User Managers</p> <p><a href="http://74.125.79.132/translate_c?hl=en&ie=UTF-8&sl=nl&tl=en&u=http://www.linkit.nl/systeem-applicatiebeheer/aanmeldingsformulier_agile_presentatie&rurl=translate.google.nl&usg=ALkJrhhaa1eoJziaZMQp4L8XiIcWHV8c4g">Sign up now!</a></p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-67626057809180299842009-06-26T16:45:00.003+02:002009-06-26T21:11:21.121+02:00Page class gets friends<p>In my <a href="http://watinandmore.blogspot.com/2009/06/introducing-page-class.html" target="_blank">previous blog post</a> I explained how you can use the new Page class in your code. Having this class available did spark some new ideas in the community. And again <a href="http://blog.bits-in-motion.com/" target="_blank">Jeff Brown</a> offered some hours of sleep to make your page classes even more terse by introducing the FindByAttribute. Another new attribute is the DescriptionAttribute.</p> <h3>FindByAttribute</h3> <p>The FindByAttribute can be used on Fields and Properties and gives you a declarative style of expressing how an element should be found. In the following example the GoogleSearchPage is revamped and makes use of the new FindByAttribute. </p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/SkTe7xbWf1I/AAAAAAAAAGE/m_4UH3Jhq8M/s1600-h/image%5B8%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="509" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SkTe8Qd-wHI/AAAAAAAAAGI/wOSP3RBm0JY/image_thumb%5B6%5D.png?imgmax=800" width="579" border="0" /></a> </p> <p>Note that I only changed the GoogleSearchPage class and didn't have to change the test. And yes indeed, no actual c# code is needed and it almost reads like a real sentence. If only we could get ride of the syntax overhead like the [()] public:</p> <p>FindBy Name q TextField SearchCriteria</p> <h3>And there is more</h3><div>Talking about readability, <a href="http://watintestrecord.sourceforge.com">Daaron Dwyer</a> suggested to add a DescriptionAttribute. This new attribute sets the (also new) Description property of an Element or Control instance. This description is set on the element when a page object gets instantiated. With the description you can give the element a meaningful name which will show up in the log WatiN can create (see the Logger class in WatiN). The description will also be used when ToString() is called on an Element or Control.</div><div><br /></div><div>If you like to have a look at these brand new features then go and get the source from the SourceForce code repository. If you are a little less adventures today, just wait until the next WatiN 2.0 release. </div>Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-31484301813054541332009-06-17T17:58:00.001+02:002009-06-17T23:39:53.622+02:00Introducing the Page class<p>When you create your first automated tests with WatiN you are happy with the results and how easy it is to create tests (at least that is what I keep hearing). Your happily copying and pasting code to find elements into new tests. While your test suite is growing rapidly, changes are made to the web pages and all of a sudden you are in a test code maintenance nightmare. You have created WET code (!= DRY). The solution: separate your test code in tests classes, page classes and control classes (more on controls in another post). So lets start mopping!</p> <p><a href="http://blogs.conchango.com/richardgriffin/archive/2006/11/14/Testing-Design-Pattern-for-using-WATiR_2F00_N.aspx" target="_blank">Richard Griffin</a>, <a href="http://infozerk.com/averyblog/watin-testing-pattern/" target="_blank">James Avery</a> and <a href="http://ayende.com/Blog/archive/2008/06/17/Zero-Friction-Creating-a-test-model.aspx" target="_blank">Ayende Rahien</a> all wrote about the problems they were having and the page model they developed. <a href="http://www.teknologika.com/blog/category/watin/" target="_blank">Bruce McLeod</a> even posted the <a href="http://watinjobsitesample.codeplex.com/" target="_blank">WatiN Jobsite Sample</a> on CodePlex to show you his page model in action. Thanks to the work of <a href="http://blog.bits-in-motion.com" target="_blank">Jeff Brown</a>, WatiN 2.0 beta 1 now comes with its own page model. The basic idea of a page model is that each web page in the web site under test has a page class counterpart in the test suite. These page classes expose elements through properties and actions through methods. The result makes it much easier to create new tests and to maintain your test code when changes happen to your web site.In this post I’ll transform the <a href="http://watin.sourceforge.net/index.html" target="_blank">Hello world example of web test automation</a>, as shown on the WatiN homepage, into a test using such a page class. </p> <p>First a new class needs to be created inheriting the WatiN.Core.Page class, lets call it GoogleSearchPage. This page class exposes properties for the searchcriteria field and the search button. After re-writing the “Hello world example” using the GoogleSearchPage class, the code looks like this (and of course you would put the GoogleSearchPage class in its own file/assembly in production code, but for this example I kept them together).</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SjkSiifYoXI/AAAAAAAAAFs/l3kAP40qWSM/s1600-h/image%5B5%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="508" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/SjkSjLrpgGI/AAAAAAAAAFw/X3hG7WLNaHM/image_thumb%5B3%5D.png?imgmax=800" width="600" border="0" /></a> </p> <p>The Page<> method on the Browser class provides an easy way to instantiate page classes and it does inject the Browser Document into the page class. Because the GoogleSearchPage inherits the new WatiN.Core.Page class, it can access to Document property exposed by the Page class to find elements on the page. </p> <p>Since the GoogleSearchPage has properties exposing the SearchCriteria textfield and the Search button, all logic to find these controls is held in one place and can be easily reused in other tests. Also notice how the test got much more readable compared to the <a href="http://watin.sourceforge.net/index.html" target="_blank">example</a> on the WatiN website.</p> <p>Ok, so we have modeled the page with its elements, lets take it one step further. Most web pages offer users one or more actions they can perform on the page. Modeling these actions as methods on your page class would encapsulate even more logic into one place and thus making it easier to maintain when changes happen to the web page. So let me add the method SearchFor to the GoogleSearchPage. Also see how it improves the readability of the test, again.</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SjkSjdCJXxI/AAAAAAAAAF0/JeyVqF0im3c/s1600-h/image%5B11%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="565" alt="image" src="http://lh3.ggpht.com/_LPItL_MawEI/SjkSj--OJpI/AAAAAAAAAF4/IqvXN3eVUy4/image_thumb%5B7%5D.png?imgmax=800" width="597" border="0" /></a> </p> <p>At this point, when I would navigate to <a href="http://www.bing.com">http://www.bing.com</a> and use the GoogleSearchPage, nothing would alarm me that the current page can’t be automated with the GoogleSearchPage class. Instead an ElementNotFoundException would be throw when trying to find an input element with the name btnG (in the SearchCriteria property). </p> <p>The new Page class offers you some ways to validate the current page before accessing elements on the page. The easiest way is to decorate a page class with the new PageAttribute. This attribute exposes a property UrlRegex which accepts a regular expression. This is used to match with the current browsers Url every time the Page.Document property is accessed. WatiN will check if the browser is still on the correct page and if not, throw a meaningful exception.</p> <p>If the regular expressions are not your thing or you want to check against another aspect of your page (for instance the title), you can also override the Page.VerifyDocumentProperties method and implement your own check and not use the PageAttribute.</p> <p>Wel that’s it about the new Page class in WatiN 2.0 beta 1. I hope it will help you to better structure your page model. Following our revamped <a href="http://watin.sourceforge.net/index.html" target="_blank">Hello world example of web test automation</a>. </p> <p><a href="http://lh5.ggpht.com/_LPItL_MawEI/SjkSkTNiIaI/AAAAAAAAAF8/aQ5XeblG3NE/s1600-h/image%5B23%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="593" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SjkSk93T1xI/AAAAAAAAAGA/ZXqxwFa6hyI/image_thumb%5B17%5D.png?imgmax=800" width="595" border="0" /></a> </p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e9f2c37f-4ea0-4cc7-82a0-efc95422ed2e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-28017768009333950892009-04-07T11:15:00.001+02:002009-04-07T11:15:35.988+02:00WatiN How To screen cast<p>I have been thinking for a while about creating a How To screen casts series about WatiN. Last week I sat down and experimented a bit with <a href="http://www.techsmith.com/jing/default.asp" target="_blank">Jing by TechSmith</a> (the creators of CamtasiaStudio). </p> <p>With Jing it really is very easy to get started with recording and not falling into the trap of creating the visually perfect video with Camtasia. Which, at the end, never gets done. I also like the 5 minute constraint that Jing enforces. This really makes you to focus on the core of things you want to example or show. And last but not least, they offer a 2 GB free storage on <a href="https://www.screencast.com/" target="_blank">screencast.com</a> to host your videos.</p> <p>For this How To trial episode I used this <a href="http://watinandmore.blogspot.com/2009/03/custom-elements-and-controls-in-watin.html" target="_blank">blog</a> about adding your own elements to WatiN. Let me know what you think about it? Do you like the length, the amount of information, should I do more like these and which topics would you like to be explained?</p> <p><a href="http://www.screencast.com/users/JvMenen/folders/Jing/media/08e4cfbd-6739-406c-b384-b86d172e71bf" target="_blank">Watch the episode.</a></p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:14fa9a5a-0171-4381-bbf7-5718c809e952" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-85036223897914509432009-04-07T10:51:00.001+02:002009-04-07T10:52:29.051+02:00Introducing the DialogHandlerHelper<p>Many questions on the watin-users mailinglist (and about WatiN in general) are about handling dialogs with WatiN. WatiN has build in support for handling many of Internet Explorers dailogs but it is hard to find out which DialogHandler is the right one for the job.</p> <p>WatiN 2.0 beta 1 introduced the new DialogHandlerHelper class. DialogHandlerHelper can be used to investigate which DialogHandler can be used for a specific dialog. The following example shows you how to use the DialogHandlerHelper .</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SdsUISAj3tI/AAAAAAAAAFM/SMAPxtgDDws/s1600-h/image%5B24%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="238" alt="image" src="http://lh5.ggpht.com/_LPItL_MawEI/SdsUJHBVR9I/AAAAAAAAAFQ/s8WQqWQLXXY/image_thumb%5B22%5D.png?imgmax=800" width="601" border="0" /></a> </p> <p>Lets walk through the example. First it creates an IE instance and navigates to a page. Then an instance of DialogHandlerHelper is created and registered with the DialogWatcher. A button is clicked which shows a dialog. The DialogHandlerHelper will now inspect the dialog and close it. Finally the CandidateDialogHandlers are written to the console window for you to inspect and create your final solution.</p> <p>For this example that would be:</p> <p><a href="http://lh5.ggpht.com/_LPItL_MawEI/SdsUJZX0VUI/AAAAAAAAAFc/RldNS2W_k0I/s1600-h/image%5B43%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="245" alt="image" src="http://lh5.ggpht.com/_LPItL_MawEI/SdsUKB61NzI/AAAAAAAAAFg/yNH5o3DzYdI/image_thumb%5B39%5D.png?imgmax=800" width="620" border="0" /></a></p> <p> </p> <h2>Just a thought</h2> <p>To make it even more simple, wouldn’t it be great if someone combined the following into a windows forms app:</p> <ul> <li><a href="http://www.codeproject.com/KB/dialog/FindWindow.aspx">http://www.codeproject.com/KB/dialog/FindWindow.aspx</a>: To let the user point at the dialog that needs to be automated.</li> <li>The code inside DialogHandlerHelper to inspect the chosen dialog and find candidate dailoghandlers.</li> <li>And, when a Dialoghandler is available for the dialog, uses the the class documentation that comes with the dialoghandler to show you example code about using that specific dialoghandler.</li> </ul> <p>Volunteers?</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:01b8e5b9-35bd-4f36-8b09-ebee35fd431d" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com1tag:blogger.com,1999:blog-8266872010677720335.post-40927269500897925372009-03-31T15:17:00.001+02:002009-03-31T15:40:40.743+02:00Reusing an IE instance in VS test<p>I was going over the WatiN questions on stackoverflow. One of the questions involved reusing an IE instance over multiple tests. Since Visual Studio’s test runner creates a new Thread for each TestMethod in a TestClass you get a nasty InvalidComObjectException with the additional information "COM object that has been separated from its underlying RCW can not be used.". </p> <p>Following the problem example as posted on stackoverflow. When running these tests, the first test “testOne” passes but the second test “testTwo” will throw the InvalidComObjectException.</p> <p><a href="http://lh4.ggpht.com/_LPItL_MawEI/SdIXx0VSyGI/AAAAAAAAAE0/Yx2W0j6ZRkI/s1600-h/image%5B14%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="325" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SdIXyeKKVHI/AAAAAAAAAE4/2fs_Z8vzg9s/image_thumb%5B10%5D.png?imgmax=800" width="498" border="0" /></a> </p> <p>Does this mean we can’t reuse an IE instance across multiple tests? Nope.</p> <p>We can still instantiate IE in the method decorated with the ClassInitialize attribute but in each test case we need to attach to the running instance using IE.AttachToIE(constraint). To find the Internet Explorer instance we created, we can use the window handle to find the instance. Somewhat like a “good-old-pointer”. Add a little bit logic to cache the found IE instance and return this as long as the CurrentThread hasn’t changed and the helper class could look something like this:</p> <p><a href="http://lh3.ggpht.com/_LPItL_MawEI/SdIXypu2BeI/AAAAAAAAAE8/W_FXYPQFQyo/s1600-h/image%5B13%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="483" alt="image" src="http://lh4.ggpht.com/_LPItL_MawEI/SdIXzBG5nbI/AAAAAAAAAFA/Ljhx7OxLhzU/image_thumb%5B9%5D.png?imgmax=800" width="568" border="0" /></a> </p> <p>To make use of this helper class, we create an instance of IEStaticInstanceHelper and assign it to a static field (as we did before with the IE instance). Next we assign an IE instance to the IE property. Now we can use this Internet Explorer instance in our test cases without bothering about different Threads. </p> <p>For clarity sake I wrapped the call to the  ieStaticInstanceHelper.IE property in an instance property of the test class, called IE. And to make sure the IE instance gets closed after all tests have run I added a method decorated with the ClassCleanup attribute.</p> <p> </p> <p><a href="http://lh6.ggpht.com/_LPItL_MawEI/SdIXzrFB45I/AAAAAAAAAFE/cweB_9VcCqk/s1600-h/image%5B34%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="561" alt="image" src="http://lh6.ggpht.com/_LPItL_MawEI/SdIX0UXKqDI/AAAAAAAAAFI/Z4aTtAFrYRM/image_thumb%5B22%5D.png?imgmax=800" width="583" border="0" /></a> </p> <p>Off course you could create a base class which is used by all your test classes, but that's up to you.</p> <p>You can download the code <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/Using%20watin%20with%20visual%20studio%20test.zip" target="_blank">here</a>.</p> <p>Happy testing with WatiN and Visual Studio test runner!</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:52312acf-ffb1-4dc6-8f28-edfe90c95e32" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-12592753215466968492009-03-30T23:48:00.001+02:002009-03-30T23:59:20.861+02:00Released WatiN 2.0 beta 1<p>I’m very happy to announce the release of WatiN 2.0 beta 1!</p> <p>It has been a long ride from the first CTP release to this beta release. This has mainly to do with the beta having a completely different architecture from the previous CTP releases. With the CTP releases we used interface like ITextField etc. to provide support for multiple browsers. This resulted basically in creating a complete new set of about 50 classes for each additional browser we wanted to support. With this release we have managed to reduce this amount to 6 classes for each additional browser.</p> <p>Another big change is made to the test suite. All the tests that came with WatiN 1.3 and were run against Internet Explorer, making sure every feature worked with IE6 and IE7, are now run against FireFox 2 and 3 and IE8 as well. This ensures that all features have the same behavior across all these browsers.</p> <p>We are not there yet, that’s why it is still a beta release. We will continue working on WatiN 2.0 to fix the list of known issues and to incorporate community feedback. We intend to do a release at the end of every month, working towards a final release in June or July.</p> <p>In the coming days I will blog some more about the new features. For now you can read the release notes at <a href="http://watin.sourceforge.net/releasenotes-2-0-10-x.html" target="_blank">http://watin.sourceforge.net/releasenotes-2-0-10-x.html</a> and download the release <a href="https://sourceforge.net/project/showfiles.php?group_id=167632&package_id=316438&release_id=672207" target="_blank">here</a>.</p> <p>Happy testing with WatiN!</p> <div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d9c6d52d-cf39-4cdb-8925-1d70531a7152" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-28298533654559720072009-03-26T15:56:00.001+01:002009-03-31T17:12:41.786+02:00Custom elements and controls in WatiN 2.0 beta<p><strong><em>Update 3/31/2009:</em></strong> You can download the example code for this blog post <a href="http://cid-7a759edaf62c1f79.skydrive.live.com/self.aspx/WatiNExamples/Adding%20an%20Element%20to%20WatiN.zip" target="_blank">here</a>.</p> <p>Still working on the beta release of WatiN 2.0 (will ship in the next few days), but I felt the need to blog about a new feature in the 2.0 beta. In previous posts I showed you how you could extend WatiN with your own controls:</p> <ul> <li><a href="http://watinandmore.blogspot.com/2008/11/supporting-custom-elements-with-watin.html" target="_blank">Supporting custom elements with WatiN, Part I</a> </li> <li><a href="http://watinandmore.blogspot.com/2008/11/supporting-custom-elements-with-watin_12.html" target="_blank">Supporting custom elements with WatiN, Part II</a> </li> <li>And part III never made it… </li> </ul> <p>In the upcoming beta WatiN will offer you these new features:</p> <ol> <li>Add support for native html elements not provided by WatiN. </li> <li>Add support for your (custom) web controls. </li> </ol> <p>Which make the previous posts obsolete. </p> <h4>Add your own native html element</h4> <p>WatiN doesn’t provide support for all html elements defined by the W3C standards. For instance there is no out-of-the-box support for <em>li </em>tagged elements. But starting with WatiN 2.0 beta 1 you can “add” support for linked lists yourself.</p> <p>First lets show you how you could make use of your own ListItem element.</p> <p><strong>ListItem list = browser.ElementOfType<ListItem >(Find.ById(“theElementId”));</strong></p> <p>(And yes, this syntax also works with the out-of-the-box elements like TextField etc..)</p> <p>Now we know how we could use a none native ListItem element in our (test) code, lets create this ListItem class.</p> <ol> <li>First create a new class called ListItem and make it inherit WatiN.Core.Element. </li> <li>Add the ElementTagAttribute to your class to tell WatiN which tagName(s) your element class can handle. Incase of ListItem: [ElementTag(“li”)] </li> <li>Add whatever properties and methods are needed to make this element work for you. </li> <li>The last thing you need to do is register ListItem with WatiN’s ElementFactory before you can use it in your (test) code: </li> </ol> <blockquote> <p><strong>ElementFactory.RegisterElementType(typeof(ListItem ));</strong></p> </blockquote> <p>That’s it, you’ve added a new (almost native) element to WatiN. You could make it look even more native by extending the IElementContainer  interface with some extension methods which do wrap the calls to ElementOfType<ListItem >(…) and make it look like:</p> <p><strong>ListItem list = browser.ListItem (Find.ById(“theElementId”));</strong></p> <h4>Add support for your (custom) web controls</h4> <p>I’ll tell you about that one in my next post… back to releasing the beta :-)</p> <p></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:03a15620-6588-4724-a9b4-b460a31e9ee2" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-51602560238518251562009-02-11T23:31:00.001+01:002009-02-11T23:31:19.273+01:00Released WatiN 2.0 CTP3<p>I'm happy to announce the third CTP release of WatiN 2.0, offering support for both Internet Explorer and FireFox.</p> <h4>Changes in this release</h4> <ul> <li>Implemented support on Mozilla.Frame to get access to elements inside the document of a Frame.</li> <li>Implemented support on Mozilla.Frame to get access to elements inside the document of an IFrame.</li> <li>Implemented Eval on Mozilla.Document (= FireFox and Frame) and added to the IFrame interface</li> </ul> <h4>Fixed bugs</h4> <ul> <li>Form.Submit didn't wait for a possible postback and page load. </li> </ul> <p>Enjoy testing with WatiN!</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:830f9025-daa4-41b9-bab3-4926734004a6" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Tags van Technorati: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com4tag:blogger.com,1999:blog-8266872010677720335.post-91467860877424871102009-01-15T23:52:00.001+01:002009-01-15T23:52:36.094+01:00Release WatiN 2.0 CTP2<p>I'm happy to announce the second CTP release of WatiN 2.0, offering support for both Internet Explorer and FireFox.</p> <h4>Changes in this release</h4> <ul> <li>Works with FireFox 3.x and FireFox 2.x (both jssh.xpi plug-ins are included in the Mozilla directory).</li> <li>Greatly improved performance and stability when running tests with FireFox <br /></li> </ul> <h4>Fixed bugs</h4> <ul> <li>Problem with setting ActiveElement in FF 3.x.</li> <li>SF issue 1954487  Setting TextField.Value for TextArea in FireFox fails</li> <li>SFssue 1913072  BrowserFactory.Settings.WaitForCompleteTimeOut doesn't work </li> </ul> <p>Thanks to Edward Wilde for making it work with FF 3.x <br /></p> <p>Enjoy testing with WatiN!</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com1tag:blogger.com,1999:blog-8266872010677720335.post-4475400246794281772009-01-13T23:39:00.001+01:002009-01-13T23:39:45.492+01:00WatiN roadmap update<p>In my last post I talked a bit about what was going on with the project. Following is an update on that <a href="http://watinandmore.blogspot.com/2008/12/watin-roadmap.html" target="_blank">post</a>.</p> <h4>WatiN 2.0</h4> <p>Edward Wilde has made some changes to the current CTP code to support FireFox 3.x as well. This will be released within one week. Edward Thanks!</p> <p>Development for the first beta is still in progress. The FireFox specific classes are added and progress is great! Still on track for a first beta in Q1. Just to give you a feel off what is already working, the following test fixtures in the WatiN.Core.UnitTests assembly do run against IE (7) and FireFox (3.1):</p> <ul> <li>BaseElementCollectionTest</li> <li>ButtonTests</li> <li>CheckBoxTests</li> <li>DocumentTests (work in progress)</li> <li>DivTests</li> <li>RadioButtonTests</li> <li>SelectListTests</li> <li>TestFieldTests</li> </ul> <p>Another very interesting initiative regarding the 2.0 version is taken by Jon Dick. He started last week writing a browser implementation to run tests with <a href="http://htmlunit.sourceforge.net/" target="_blank">HtmlUnit</a>. This is an in memory, no GUI  browser written in Java. Combined with <a href="http://www.ikvm.net/" target="_blank">IKVM</a> he already has the google test example running. Since this browser skips rendering it makes the tests run faster which is always a good thing.</p> <p>I also wondered of a little bit last week and took a look at automating <a href="http://www.google.com/chrome" target="_blank">Chrome</a> (the new browser by Google). One option is to use a telnet session to the browser, much like we currently do for the automation of FireFox (using the jssh plug-in). So hopefully after finishing FireFox support, Chrome support will be there very quickly.</p> <h4>WatiN 1.3.1</h4> <p>Although I have created the branch and already merged a lot of the fixes from the trunk, I still need to add the changes I made to the DialogHandlers which do type text in a dialog (like the prompt dialog, file upload dialog and file download dialog). I think it is worth waiting cause this will (finally) fix the hanging of WatiN test in a VPC or closed/minimized remote desktop session. Hope to get this done soon.</p> <h4>WatiN Test Recorder 2.0</h4> <p>Although I don't do any development on <a href="http://watintestrecord.sourceforge.net/" target="_blank">WatiN test recorder</a> project (All credits go to Daaron Dwyer!) I know he is busy working on a 2.0 release. So if you have feature request, this is the time to contact him or spam the trackers on sourceforge :-)</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-85940608355967186082008-12-09T22:58:00.001+01:002008-12-09T22:58:48.476+01:00WatiN roadmap<p>Today I received a question on the mailing list about the status of WatiN 2.0. I thought I publish my response here as well. </p> <blockquote> <p>No release date(s) yet, but I can report about the progress and speculate about a roadmap:</p> <ul> <li>Currently the development code (a continuation of the 1.3 code base) is refactored to add support for testing with different browsers (IE, FireFox for now). I estimate I'm at 60% of the changes that need to be done to get the basic stuff to work. <br /></li> <li>Next is the integration of the firefox specific code from the 2.0 CTP version into the development code. I estimate that I will go for a first integration around the end of this month.</li> </ul> <p>So my current guesstimate is that a beta or final release of 2.0 will be earliest at the end of q1 2009.</p> <p>In the meantime Edward Wilde will update the current 2.0 CTP version to add support for FireFox 3.x. We haven't spoken about a release date be hopefully this refresh will be available early next year. <br /> <br />I will also release WatiN 1.3.1 in December with some important bug fixes. <br /> <br />So nothing final yet but I hope this gives you (all) a feel of what we are aiming for.</p></blockquote> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com2tag:blogger.com,1999:blog-8266872010677720335.post-58726040199785596002008-12-09T22:49:00.001+01:002008-12-09T22:49:06.223+01:00WatiN Find.ByDefault explained<p>My next post will be Part III of Supporting custom elements with WatiN. I got so excited about the possibilities that I started working on a wrapper for the <a href="http://www.ra-ajax.org/">Ra-Ajax</a> controls as a show case. It is becoming very COOL and its fun to create as well. But as I said in my next post I'll show you more.</p> <p>This post is all about a new feature of WatiN 1.3 which might not be that discoverable so I felt it needed some promotion. </p> <h4>Find.ByDefault</h4> <p>When you want to automate some action against an element on a web page, WatiN offers you different types of elements (TextField, Button, etc) to find an element. Each of these offer overloads accepting something to find the element by. For example, if you want to find a TextField by its id ("firstName_Id" in this example) you would typically have this code:</p> <p>var firstNameField = ie.TextField("firstName_Id");</p> <p>Which is the same as: </p> <p>var firstNameField = ie.TextField(Find.ByDefault("firstName_Id"));</p> <p>And with the default Settings applied, it is the same as:</p> <p>var firstNameField = ie.TextField(Find.ById("firstName_Id"));</p> <p>In this post I'll show you how you can change the implementation and behavior of Find.ByDefault() by creating your own default factory class and assigning it to Settings.DefaultFinderFactory .</p> <h4>Make Find.ByName the default</h4> <p>If your site makes heavy use of the name attribute on elements (instead of ids) and you use these to find the elements in your tests, you would typically write code like:</p> <p>var firstNameField = ie.TextField(Find.ByName("firstName_Name"));</p> <p>Lets make Find.ByName() the default so your code will look like this:</p> <p>var firstNameField = ie.TextField("firstName_Name"); </p> <p>To make this work we need to create a new class which implements IFindByDefaultFactory. In the implementation of the ByDefault(string) method we can simply return Find.ByName(value). This is the implementation of the class:</p> <p>public class FindByNameFactory : IFindByDefaultFactory <br />{ <br />public BaseConstraint ByDefault(string value) <br />{ <br />  return Find.ByName(value); <br />} <br />    public BaseConstraint ByDefault(Regex value) <br />{ <br />  return Find.ByName(value); <br />} <br />}</p> <p>The last thing we need to do is register this new factory class and Find.ByName will be the new default: </p> <p>Settings.FindByDefaultFactory = new FindByNameFactory();</p> <h4>Handle ASP ids with</h4> <p>Another very useful way we could leverage this new feature is dealing with ASP.Net ids. When you automate a website which is build with ASP.Net webforms you probably have to deal with very long ids. By default ASP.Net creates unique ids by concatenating all of the ids of the container controls a control is in. For instance if a TextBox to enter a first name is placed within a tab control container and this is placed in a placeholder, the resulting id could be something like "plc_Main$tab_Details$txt_FirstName". With WatiN you have several ways to find this TextField by id.</p> <p><strong>Option 1: Using the full Id</strong> <br />The simplest option to find the control is to use the full id. Example:</p> <p>ie.TextField("plc_Main$tab_Details$txt_FirstName").TypeText("Jeroen");</p> <p>There are two disadvantages to this approach: <br />- It relies heavily on the ids of the controls the ASP:TextBox control is placed in. If you remove/rename or add another container to the stack, the TextField won't be found cause the id is changed. <br />- The longer the id gets the less readable this line of code becomes. Although you can (should in my opinion) abstract the way you find your controls by using a <a href="http://blogs.conchango.com/richardgriffin/archive/2006/11/14/Testing-Design-Pattern-for-using-WATiR_2F00_N.aspx">Page model</a>, this still is massy.</p> <p><strong>Option 2: Using a regular expression <br /></strong>The second option is to find the control by using the overload on TextField which accepts a regular expression. In the following example we create a Regex which matches TextFields ending (hence the $ sign) with "txt_FirstName" :</p> <p>ie.TextField(new Regex("txt_FirstName$")).TypeText("Jeroen");</p> <p><strong>Option 3: Make WatiN handle ASP ids by itself</strong></p> <p>public class FindByAspIdFactory : IFindByDefaultFactory <br />{ <br />public BaseConstraint ByDefault(string value) <br />{ <br />  return Find.ById(new Regex(value + "$")); <br />} <br />    public BaseConstraint ByDefault(Regex value) <br />{ <br />  return Find.ById(value); <br />} <br />}</p> <p>Register this new factory class: </p> <p>Settings.FindByDefaultFactory = new FindByAspIdFactory();</p> <p>And you can find controls with ASP ids like:</p> <p>ie.TextField("txt_FirstName").TypeText("Jeroen");</p> <h4>Using (magic) prefixes</h4> <p>If you don't like to always use a regular expression, like we did in the previous example, you could implement something like the <a href="http://www.incisif.net/blog/entries/2008-02-08%20Web_Testing_and_ASP.NET_ID.htm">Incisif</a> automation framework offers. They choose to put a prefix in front of the ASP id. So only if the specific prefix (a:) is in the id a lookup with a Regex will be done to find the element. Example:</p> <p>ie.TextField("a:txt_FirstName").TypeText</p> <p>and the Factory implementation:</p> <p>public class FindByAspIdFactory : IFindByDefaultFactory <br />{ <br /> <br />public BaseConstraint ByDefault(string value) <br />{ <br />  if (value.StartsWith("a:") <br />  { <br />   Regex regex = new Regex(string.format("(.*\${0}$)|(.*_{0}$)", value)); <br />   return Find.ById(regex); <br />  } <br />  return Find.ById(value); <br />}  <br /> <br />public BaseConstraint ByDefault(Regex value) <br />{ <br />  return Find.ById(value); <br />} <br />}</p> <h4>Other possible uses</h4> <p>Put the attribute you want to match with in front of the value</p> <p>ie.TextField("id:txt_FirstName").TypeText <br />ie.TextField("name:txt_FirstName").TypeText</p> <p>A ruby like notation to express a regular expression (starting and ending with a forward slash) instead of having new Regex() all over your code: <br /> <br />ie.TextField("/txt_FirstName$/").TypeText</p> <p>And I'm sure you can come up with many more possible uses. </p> <p>Enjoy!</p> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-65555766095528520042008-11-12T00:11:00.002+01:002008-11-13T10:53:20.740+01:00Supporting custom elements with WatiN, Part II<p>12 Nov 2008: Updated section about creating an extension method.</p><p>In <a href="http://watinandmore.blogspot.com/2008/11/supporting-custom-elements-with-watin.html">part I</a> of this series I explained why you should create wrappers and how you could create a basic wrapper for your custom or third party controls. In this post I will show you</p><ul><li>how to make use of the deferred find execution </li><li>how to use extension methods to make it all look integrated with WatiN<br /></li></ul><h4>What is Deferred Find Execution</h4><p>Deferred Find Execution in WatiN means that the search for an element in the current web page is done the first time you get a property value, set a property value or call a method on that element. An example:</p><p>using(IE ie = new IE())<br />{<br /> TextField name = ie.TextField("name"); </p><p> ie.GoTo(new Uri(Util.HtmlTestBaseURI, "EnterYourName.htm"));<br /> name.TypeText("Jeroen");<br />}</p><p>The first line will open a new Internet Explorer instance showing you an empty page (about:blank). Next we set the name variable to point to an input element of type text with the id 'name'. If WatiN did an immediate lookup it would throw an ElementNotFound exception cause these elements aren't on the page shown in the browser. But WatiN doesn't throw an exception, it actually returns an instance of TextField for which the find isn't executed yet. Then the browser navigates to a page with this name element on it. When calling TypeText on the TextField instance, WatiN will search for (and find) the input element with id 'name' before executing the TypeText action. So finding of the name element is deferred until the code actually needs a reference to that element. </p><p>WatiN heavily relies on this behavior so it seems like a good idea to play with the rules.</p><h4>Implementing deferred find execution</h4><p>To make this work for the DateTimeElement an element finder class needs to be passed to the base class of DateTimeElement. Lets replace the current constructor, which accepts a Table instance, with one that calls the base constructor accepting an INativeElementFinder instance. For readability I created a private method CreateElementFinder which does the actual creation of the INativeElementFinder instance. The base constructor also needs a DomContainer instance which can be provided by our IE instance in our test code. Here is the reviced code for DateTimeElement:</p><p>public class DateTimeElement : Table<br />{<br /> public DateTimeElement(DomContainer domContainer, string id) :<br /> base(domContainer, CreateElementFinder(domContainer, id)) { } </p><p> public void TypeDateTime(DateTime value)<br /> {<br /> TextField(new Regex("^date$")).TypeText(value.ToString("dd-MM-yyyy"));<br /> TextField(new Regex("^time$")).TypeText(value.ToString("hh:mm:ss"));<br /> } </p><p> private static INativeElementFinder CreateElementFinder(DomContainer domContainer,<br /> string id)<br /> {<br /> return domContainer.NativeBrowser.CreateElementFinder(ElementTags,<br /> Find.ById(id),<br /> domContainer);<br /> }<br />}</p><p>And here is how the code in our test looks like:</p><p>DateTimeElement element = new DateTimeElement(ie, "datetime2");<br />element.TypeDateTime(new DateTime(2008, 11, 1, 12, 00, 00));</p><p>All in all a small code change for a big change in behavior.</p><h4>Introducing CustomElementFinderHelper</h4><p>In the above code I choose to create the ElementFinder instance inside the DateTimeElement class. I did this because my focus was on introducing deferred find execution (always make small steps). But if we are going to create more wrappers for our custom or third party controls, this CreateElementFinder method seems to be needed in all of them. So lets do some refactoring and move this method into a new class which will be passed into the constructor of DateTimeElement. Here is the new class CustomElementFinderHelper:</p><p>public class CustomElementFinderHelper<br />{<br /> private readonly DomContainer _domContainer;<br /> private readonly BaseConstraint _constraint;<br /><br /> public CustomElementFinderHelper(DomContainer domContainer,<br /> BaseConstraint constraint)<br /> {<br /> _domContainer = domContainer;<br /> _constraint = constraint;<br /> }<br /><br /> public DomContainer DomContainer<br /> {<br /> get { return _domContainer; }<br /> }<br /><br /> public INativeElementFinder CreateElementFinder(ArrayList supportedTags)<br /> {<br /> return _domContainer.NativeBrowser.CreateElementFinder(supportedTags,<br /> _constraint,<br /> _domContainer);<br /> }<br />}</p><p>And this is our cleaned up DateTimeElement code:</p><p>public class DateTimeElement : Table<br />{<br /> public DateTimeElement(CustomElementFinderHelper helper) :<br /> base(helper.DomContainer, helper.CreateElementFinder(ElementTags)) { } </p><p> public void TypeDateTime(DateTime value)<br /> {<br /> TextField(new Regex("^date$")).TypeText(value.ToString("dd-MM-yyyy"));<br /> TextField(new Regex("^time$")).TypeText(value.ToString("hh:mm:ss"));<br /> }<br />}</p><h4>And to top things of, the extension method</h4><p>Our last refactoring has turned our testing code into an unreadable mess:</p><p>CustomElementFinderHelper helper = new CustomElementFinderHelper(ie, Find.ById<br /> ("datetime2"));<br />DateTimeElement element = new DateTimeElement(helper);<br />element.TypeDateTime(new DateTime(2008, 11, 1, 12, 00, 00));</p><p>The intention is completely lost and there is stuff we need to do over and over again if we use a DateTimeElement in our test automation. Again refactoring to a method will help, but wouldn't it be nice if we could use the same syntax in our tests as we use to find for instance a TextField. So we need to extend the IE class in some way. </p><p>One option would be to create a new sub class of the IE class, add a new method to find the DateTimeElement and use the sub class in all our tests. </p><p>A new and simpeler solution to get the same intellisense support and readable code in your tests, is the use of an extension method. We do have several options for our extension. We could use the IE class to extend. But a better candidate would be the DomContainer (inheritted by IE) so that this extension method is also available on the HtmlDialog class (for html popup dialogs). With our current implementation of CustomElementFinderHelper extending DomContainer seems to be the logical choice. So lets create a static DateTimeElementExtensions class with an extension method on DomContainer:</p><p>public static DateTimeElement DateTimeElement(this DomContainer domContainer,<br /> string id)<br />{<br /> CustomElementFinderHelper helper = new CustomElementFinderHelper(domContainer,<br /> Find.ById(id));<br /> return new DateTimeElement(helper);<br />} </p><p>And thanks to the magic of extension methods the code in our test now looks like:</p><p>ie.DateTimeElement("datetime2").TypeDateTime(new DateTime(2008, 11, 1, 12, 00, 00));</p><p>This refactoring cleans up the code big time and makes it look like DateTimeElement is part of the WatiN API itself. Ain't that sweat.... :-)</p><p>If your still using C# 2.0, first go to your manager and (again) explain why you need to move to C#3.0 (and it's a breeze!). If the answer (again) is NO than remove the this keyword from the method signature and you can call it like this:</p><p>DateTimeElementExtensions.DateTimeElement(ie, "datetime2").TypeDateTime(new<br /> DateTime(2008, 11, 1, 12, 00,00));</p><h4>Almost there</h4><p>And now you want to access a DateTimeElement as a child from a Frame, Div or Table element..... That is a no go with the current solution.</p><p>In part III I will show you how we can fix this by making some changes to the CustomElementFinderHelper and again the magic of extension methods. But this time on one of WatiN's interfaces.</p>Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0tag:blogger.com,1999:blog-8266872010677720335.post-49274367739829581132008-11-07T00:31:00.002+01:002008-11-11T23:55:35.337+01:00Supporting custom elements with WatiN, part I<p>When using WatiN it is easy to automate simple actions on standard elements in the browser. But when you try to automate (complex) controls of control vendors like Telerik, Infragistics or even your own custom controls, things get to start ugly quickly. Wouldn't it be nice if we could automate these controls in the same way we do automate a TextField ? </p> <p>In this blog post and the next one, I while show you how.</p> <h4>The html code to automate</h4> <p>Lets start small and simple. The following HTML snippet is created by a (fictitious) custom date time control. For one of our (again fictitious) tests we need to set the values of the date and time input elements.</p> <p><table id="datetime2"> <br />    <tr> <br />        <td> <br />            <input type="hidden" id="original_date" value="01-01-2007" /> <br />            <input type="text" id="date" value="01-01-2007" /> <br />        </td> <br />        <td> <br />            <input type="hidden" id="original_time" value="10:00:00" /> <br />            <input type="text" id="time" value="10:00:00" /> <br />        </td> <br />    </tr> <br /></table></p> <p>As you can see the html for this date time control contains two input fields, one for the date and one for the time. There are also two hidden input elements containing the original values of the input fields.</p> <h4>The simple way</h4> <p>To automate setting the date and time the following code will do the job nicely.</p> <p>IE ie = new IE("http://www.examples.watin.net/datetime.html"); </p> <p>ie.Table("datetime2").TextField(new Regex("^date$")).TypeText("01-11-2008"); <br />ie.Table("datetime2").TextField(new Regex("^time$")).TypeText("12:00:00");</p> <p>So what's wrong with this code you might wonder. It basically comes down to being code and logic that isn't reusable. To name two issues:</p> <ul> <li>To get the correct TextField for the date or time, you need to remember (or find out the hard way) the correct regular expression. Otherwise you might end up setting the value of the hidden input element which will give you a nice exception (and then you remember... and I can tell). </li> <li>The formatting of the date and time needs to be in this specific format for the control to work. </li> </ul> <p>We could refactor this into a method, but still. WatiN offers you all kinds of objects that wrap html elements so it feels more natural for this date time control to be wrapped as well.</p> <h4>Basic wrapping</h4> <p>So lets create a wrapper. I will use Table as the base for our new element class since Table seems to be the container element for the control. </p> <p>public class DateTimeElement : Table <br />{ <br />    public DateTimeElement(Table table) : base(table) { } </p> <p>    public void TypeDateTime(DateTime value) <br />    { <br />        TextField(new Regex("^date$")).TypeText(value.ToString("dd-MM-yyyy")); <br />        TextField(new Regex("^time$")).TypeText(value.ToString("hh:mm:ss")); <br />    } <br />}</p> <p>We can use this new DateTimeElement class in our tests like this:</p> <p>DateTimeElement element = new DateTimeElement(ie.Table("datetime2")); <br />element.TypeDateTime(new DateTime(2008, 11, 1, 12, 00, 00));</p> <p>In my opinion the readability and intention of this code is way better then our first approach. And it also encapsulate the knowledge of the regular expression and the specific formatting of the date and time. </p> <p>So are we happy now. Not completely. I think the syntax of creating the new DateTimeElement can be improved cause it feels weird to pass in a table element instance into the constructor. Another, not visible, drawback of passing in an element is that it doesn't use WatiN's deferred execution to find the table element on the page. In more complicated wrappers this might lead to unexpected behavior. For now I will spare you the details.</p> <h4>Stay tuned</h4> <p>In part II I will show you how you can get deferred find execution by providing a small helper class and making some changes to the DateTimeElement constructor. </p> <p>To top things off I will use extension methods (C# 3.0 only) to give you this end result in you test code:</p> <p>ie.DateTimeElement("datetime2").TypeDateTime(new DateTime(2008, 11, 1, 12, 00, 00));</p> <p>Stay tuned....</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:03d8f7e5-b8c8-4a1b-af07-1723c5e3bd47" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Tags van Technorati: <a href="http://technorati.com/tags/WatiN" rel="tag">WatiN</a></div> Jeroenhttp://www.blogger.com/profile/05989461179391848268noreply@blogger.com0