James's profileJames McCaffreyBlogLists Tools Help

Blog


    October 27

    The Best Way to Perform Web Application UI Test Automation

    Suppose you have a Web application of some kind and you want to write test automation which exercises the app through the application GUI. There are several approaches you can take. First, you can buy a commercial record-playback tool. A record-playback solution involves the use of a software tool which captures a user's manual manipulation of a Web application running within a browser, and then records a representation of the user's actions as a script of some kind. This script can be manually edited if necessary, and then re-run against new versions of the Web application under test in order to verify that any new functionality in the application has not introduced application failures. These tools are generally easy to use and can be effective for regression testing of relatively simple scenarios. However, these tools are expensive, browser-dependent, and relatively sensitive to changes in the GUI of the Web app under test.
     
    Second, you can use a JavaScript approach. A JavaScript based solution involves creating a lightweight Web page harness which consists of two HTML frame objects. One frame of the page harness holds the Web application under test. The second frame of the harness holds JavaScript code which loads the Web application under test into the first frame, exercises the application through a series of state changes by simulating user actions such as button-clicks using the simple JavaScript code wrappers around the browser's Document Object Model, and examines the final state of the Web application for an expected state to determine a pass-fail test scenario result. This approach is simple, effective, and relatively browser-agnostic. However, JavaScript does not have any built-in debugging capabilities, and does not fully support object oriented programming, making JavaScript tests somewhat difficult to create.
     
    Third, you can use a UI automation API approach. A UI automation API based solution involves writing code which calls directly into the low-level functions exposed by a browser's Document Object Model. For Internet Explorer, these function calls can be made directly, typically by using the C++ language, or indirectly, by using wrapper code such as the C# language P/Invoke mechanism. Or, for Firefox you can use XPCOM calls. The API approach gives you maximum control into a browser DOM but is the most difficult to write and is browser-dependent.
     
    Fourth, you can use some open source framework such as WATIR. These frameworks are script language wrappers (Ruby in the case of WATIR) around browser DOM API sets. These frameworks are relatively easy to use but create a clear external dependency.
     
    There a several variations on the four approaches described too. So, which is the best approach? There isn't a single best approach. Each technique has pros and cons depending upon your particular testing scenario. The point is you need to be aware of these approaches so you can decide which is best to use in your particular scenario.
    October 16

    Searching Active Directory with PowerShell

    Microsoft uses thousands of employees from various vendor companies. The other day I wanted to get a list of the names and e-mail addresses of some of these vendor employees. I decided that I didn't want to work with COM/ADSI and that C# was slight overkill for such a relatively simple (or so I thought at first) task. I discovered that virtually all of the examples I found on the Web of how to search AD using PowerShell had significant errors. So I put together my own short PowerShell script. The script begins:
     
    $target = "(&(objectCategory=User)(company=*Acme*))"
    $root = new-object directoryServices.directoryEntry
    $seeker = new-object directoryServices.directorySearcher
    $seeker.searchRoot = $root
    $seeker.SearchScope = "Subtree"
     
    I set up a search filter for all AD users who have a Company attribute that contains 'Acme' (the * characters are wildcards). Then I instantiate a DirectoryEntry object from the System.DirectoryServices namespace, and a DirectorySearcher object to actually perform the search. I specify to begin searching at the root of the Active Directory hierarchy, and to search the entire tree. My script continues:
     
    $seeker.serverTimeLimit = -1
    $seeker.clientTimeout = -1
    $seeker.filter = $target
    $seeker.pageSize = 10
     
    The -1 arguments mean "do not ever timeout". The PageSize argument is important. Because the Microsoft AD is so huge, a PageSize value tells the DirectorySearcher object to buffer 10 results at a time until finished. Now I can execute the search:
     
    $colProplist = "name", "mail"
    foreach ($i in $colPropList){
      $seeker.PropertiesToLoad.Add($i) | out-null
    }
    $$resultsCollection = $seeker.findAll()
     
    Here I say to fetch just user's name and mail properties, and then I search using the FindAll() method. Now I can display results. This is the point where all the existing examples I found glossed over what is happening. Consider my code:
     
    $resultsCollection = $seeker.findAll()
     
    foreach ($result in $resultsCollection) {   
      $propertiesCollection = $result.Properties
      $mailValues = $propertiesCollection.mail  
      $mailString = $mailValues.Item(0)         
      $mailString += ";"
      write-output $mailString # use write-output so can redirect to file
    }
     
    This part is actually quite tricky. The FindAll() method returns a SearchResultCollection collection type. And then in my foreach loop, each $result is a complex SearchResult type. The 'Properties' property returns a ResultPropertyCollection collection type. Then I grab just the 'mail' property but in fact this property is also a collection of type ResultPropertyValueCollection! Finally the Item(0) property is the actual String type value of the user's e-mail address. I could use a similar pattern to get the users names:
     
    $nameValues = $propertiesCollection.name  
    $nameString = $nameValues.Item(0)
     
    Anyway, working with AD is somewhat more tricky than I expected.
    October 10

    Testing ASP.NET MVC Applications

    The ASP.NET team is on schedule to release the new MVC (Model-View-Controller) framework sometime early in 2009. The MVC framework gives Web developers a new way to create Web apps. In my mind, ASP.NET Web Forms are useful when I want a Web app that gives the appearance of a single Web page. The new MVC framework is especially useful when your Web application consists of a collection of related, but different-looking, pages. Think of an e-commerce system like amazon.com for example. Anyway, I'm currently creating a training class "VS 473 - Testing ASP.NET MVC Applications" for contract and full-time software engineers working at Microsoft. I have found that the design of the MVC framework really lends itself well to test automation. The MVC framework supports unit testing, but unit testing is primarily a development activity; using unit testing does not mean you can omit thorough testing of MVC apps. The screenshot below shows an ASP.NET MVC application and a proof-of-concept of some lightweight test automation. The MVC app is a slight variation of the Task List application, an excellent example written by Microsoft's Stephen Walther, from the tutorials section of the ASP.NET MVC Web site. The test automation running in the command shell uses a GET request to send information to the MVC application, instructing the app to mark the "Work on second task" task item as Complete. The test automation fetches the HTTP response from the GET request and examines the response for HTML code that indicates the MVC app responded correctly. Very, very simple. I took the screenshot just before the MVC Web app refreshed to show the task had been marked as Complete. The investigation demo showed me that writing test automation to complement manual testing of ASP.NET MVC applications will be very easy, powerful, and efficient.
     
    ASPdotNETMVCAppTesting
     
    October 03

    WPF Application UI Test Automation - Working with Menu Controls

    I've been looking at testing WPF (Windows Presentation Foundation) applications lately. It took me a while to warm up to WPF apps but now I'm a big fan. UI automation for WPF apps is a new ball game. By far the best approach is to use the Microsoft UI Automation (MUIA) library which, like WPF, is part of the .NET 3.0 Framework. One thing I especially about WPF applications is the new Menu control model. Classic WinForms use a completely separate model for the main application menu and non-menu user controls. The idea was back then that menu-ing was really hooking directly into low-level Windows API functions so the menu control model should be different from the model forother user controls. See the screenshot below for an example of automating WPF Menu controls. Then at some point .NET revised the menu model (I think in .NET Framework 2.0 as I recall) to use a menuStrip control but this just added mild confusion (to me anyway). But WPF applications treat Menu controls just like any other user controls. This makes them much easier to automate than classic WinForm, non-WPF, menu controls. Unfortunately, in Visual Studio 2008 there is no built in support for drag-and-drop design for menu controls so you have to code the XAML by hand. But it's not hard. For example, the automation in the screenshot below is exercising a WPF app with this menu XAML I added by hand:
     
    <Menu Height="22" Name="menu1"
      VerticalAlignment="Top" IsMainMenu="True" >
      <MenuItem Header="_File">
        <MenuItem Header="_New" Name="fileNew" />
        <MenuItem Header="_Open" Name="fileOpen" />
        <Separator />
        <MenuItem Header="E_xit" Name="fileExit"
         InputGestureText="Alt-F4" ToolTip="Exit StatCalc"
         Click="OnFileExit" />
      </MenuItem>
      <MenuItem Header="_Help">
        <MenuItem Header="Help Topics" />
        <Separator />
        <MenuItem Header="About StatCalc" />
      </MenuItem>
    </Menu>
     
    Notice the Click="OnFileExit" in the UI design. At compile time this will generate a C# method:
     
    public void OnFileExit(object sender, RoutedEventArgs e)
    {
      // TODO
    }
     
    and you can simply add: this.Close(); to the method body. Neat. Anyway, test automation for WPF apps is very interesting. I am writing up an article for MSDN Magazine that addresses all the key issues.
     
    UIAutomationForWPF-WorkingWithMenus