Silverlight unittest / automation

Reading up on silverlight unittesting from Justin Angel’s post. I ran into some startup problems like not iheriting from SilverlightTest in my test class (took me two hours ;)) and adding the right assemblies to our project. But the biggest challenge was figuring out how each control could be addressed.

  • TextBox, text input with Value pattern
  • // create an automationpeer for the control
    var textBoxPeer = new TextBoxAutomationPeer(ctrl);
    // create a valueprovider to fill the control
    var textBoxProvider = (IValueProvider)textBoxPeer.GetPattern(PatternInterface.Value);
    // fill some text
    textBoxProvider.SetValue(fieldvalue);
    
  • ComboBox, find child with value to select and use SelectionItem pattern
  • // create an automationpeer for the control
    var comboBoxPeer = new ComboBoxAutomationPeer(ctrl);
    // find the child with the value to set
    var comboBoxSelectionItem = (ISelectionItemProvider)comboBoxPeer.GetChildren()
                    .Where(x => x.GetName().Equals(valueToSelect))
                    .First()  // will fail if valueToSelect is not found
                    .GetPattern(PatternInterface.SelectionItem);
    // select the value
    hoursComboBoxSelectionItem.Select();
    
  • RadioButton, select with the SelectionItem pattern. This raises the (Un)Checked event, not the Click event.
  • // create automationpeer for the control
    var radioButtonPeer = new RadioButtonAutomationPeer(ctrl);
    // create a selectionitemprovider to set the selection
    var radioButtonProvider = (ISelectionItemProvider)radioButtonPeer.GetPattern(PatternInterface.SelectionItem);
    // select the value
    // this will NOT raise the Click event, but the CHECKED event
    radioButtonProvider.Select();
    
  • Button, click it with Invoke pattern
  • // create an automationpeer for the button
    var buttonPeer = new ButtonAutomationPeer(ctrl);
    // create am invokeprovider to click the control
    var buttonInvoker = (IInvokeProvider)buttonPeer.GetPattern(PatternInterface.Invoke);
    // check button is available
    Assert.IsTrue(buttonPeer.IsEnabled(), "Button was not enabled");
    // click the button
    buttonInvoker.Invoke();
    

My next post is about custom AutomationPeer classes.

Posted in Test | Tagged , , , , , | Leave a comment

Use your own performance counters

Create and use your own performance counters to see how you program is doing in performancetests, stresstests, production, …
First register the performance counters. This is done with a PerformanceCounterCategory that contains the CounterCreationData objects for the performance counters. Be sure to check it doesn’t already exists or an exception is thrown.

// create performance counters if not already existing
if (PerformanceCounterCategory.Exists(CATEGORY) == false)
{
    var counters = new CounterCreationDataCollection();
    // create reads per second performance counter
    var reads = new CounterCreationData();
    reads.CounterName = "# reads per second";
    reads.CounterHelp = "Number of reads per second";
    reads.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
    counters.Add(reads);
    // create writes per second performance counter
    var writes = new CounterCreationData();
    writes.CounterName = "# writes per second";
    writes.CounterHelp = "Number of writes per second";
    writes.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
    counters.Add(writes);
    // create number of exceptions performance counter
    var fails = new CounterCreationData();
    fails.CounterName = "# failed actions";
    fails.CounterHelp = "Number of failed actions";
    fails.CounterType = PerformanceCounterType.NumberOfItems32;
    counters.Add(fails);
    // create new category with the counters above
    PerformanceCounterCategory.Create(CATEGORY, "My Project Category", PerformanceCounterCategoryType.SingleInstance, counters);
}

After the category is created you can use the PerformanceCounters in your code. You don’t need to create a new instance of the PerformanceCounter every time it needs to be incremented. I always create a variable at the start of a thread and use it in that thread only.

var reads = new PerformanceCounter(CATEGORY, "# reads per second", false);
// register a read with the performance counter
reads.Increment();

Clean up at the end of your program, the code below will remove the performance counters again.

// clean up the performance counters at the end of your program
if (PerformanceCounterCategory.Exists(CATEGORY) == true)
{
    PerformanceCounterCategory.Delete(CATEGORY);
}

If you don’t see any value changes in the Performance Monitor try closing and opening the Performance Monitor.

Posted in Test | Tagged , , , , , | Leave a comment

Expose WSDL

Working with my java colleagues I came to love SOAPUI for testing services. Now Microsoft seems to have catched up with the WCF Test Client. A blog post of dotNET colleague Rick van den Bosch made me search for it in the Common7 folder.
Adding a service is done by putting the URL to the WSDL in the inputbox. So I had to make sure my services expose the WSDL. See below for some configuration options for exposing the WSDL. In both cases the WSDL is exposed on http://SomeMachine/Some/Services/Calculator?wsdl

<!-- Make use of a named behavior configuration -->
<system.serviceModel>
  <services>
    <!-- Service with specified behavior, 
         the behavior contains the address for the WSDL -->
    <service name                  = "SomeService.CalculateImplementation"
             behaviorConfiguration = "CaculateServiceWSDLBehavior" >
      <endpoint
        address                    = "http://SomeMachine/Some/Services/Calculator"
        binding                    = "basicHttpBinding"
        contract                   = "SomeService.ICalculate"
      />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <!-- Named behavior containing the WSDL URL (httpGetUrl) -->
      <behavior name               = "CaculateServiceWSDLBehavior">
        <serviceMetadata 
          httpGetEnabled           = "true"
          httpGetUrl               = "http://SomeMachine/Some/Services/Calculator" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>
<!-- Make use of baseAddress -->
<system.serviceModel>
  <services>
    <!-- Service with default behavior -->
    <service name                = "SomeService.CalculateImplementation" >
      <!-- baseAddress used for WSDL url -->
      <host>
        <baseAddresses>
          <add baseAddress       = "http://SomeMachine/Some/Services/Calculator" />
        </baseAddresses>
      </host>
      <!-- Endpoint without address, because that is fully 
           specified in the baseAddress -->
      <endpoint
        address                  = ""
        binding                  = "basicHttpBinding"
        contract                 = "SomeService.ICalculate" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <!-- Default behavior for every service 
           use of baseAddress needed for WSDL -->
      <behavior>
        <serviceMetadata 
          httpGetEnabled         = "true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Need some online service to get started with WCF Test Client? Check webservicex.

Posted in Development | Tagged , , , , , , | Leave a comment

<clear></clear> is not the same as <clear/>

In the dotNET configuration files you can add items to a collection like appSettings with

<appSettings>
   <add key="" value=""/> 
</appSettings>

Because this is XML you can also use the following line to add an item:

<appSettings>
   <add key="" value=""></add>
</appSettings>

But not the same for clearing the list. Try adding <clear></clear> to the top of your appSettings section and you likely get the exception “Unrecognized element ‘add'”.
According to Tess Ferrandez the workaround is so simple that Microsoft is not going to fix it.
Using reflector on the dotNET 2.0 system.configuration assembly I saw some strange code. Look at the OnDeserializeUnrecognizedElement of System.Configuration.ConfigurationElementCollection and in there you’ll see this part of code:

...
while (reader.MoveToNextAttribute())
{
   string name = reader.Name;
   throw new ConfigurationErrorsException(SR.GetString("Config_base_unrecognized_attribute", new object[] { name }), reader);
}
...

Reading this made me realize that the following xml will work, because there is no “unrecognized” tag after the closing clear tag.

<appSettings>
   <clear></clear>
</appSettings>

So be safe and always use <clear/> in config files. Because this behavior affects all configuration. Remember this the next time you add a AuthorizationPolicy.

Posted in Development | Tagged , , , , , | Leave a comment

Password confirm in WPF

In WPF the PasswordBox control doesn’t expose any property to bind it. You’ll need solutions as described here to get the password the ‘WPF way’. Getting it to validate is a different story.
Whenever a user is created you want the password to be confirmed. That was, is and allways will be the way to make sure the user knows the password. Mistakes are quickly made and this way the mistake has to be made twice before it becomes a problem. But how to compare two PasswordBox controls that use the passwordhelper?
Use the IDataErrorInfo to implement your own validation. A sample implementation is below. Ignore the Error property of the interface as we don’t use it in this implementation.

public string this[string columnName]
{
    get
    {
        string result = null;
        // columName is the name of the property whose error message to get
        switch (columnName)
        {
            case "PasswordConfirm":
                // only check if password is supplied, else confirm is obsolete
                // password must be equal to confirm
                if (string.IsNullOrEmpty(Password) == false && 
                    Password.Equals(PasswordConfirm) == false)
                {
                    result = "Passwords differ";
                }
                break;
        }
        return result;
    }
}

A complete sample is available for download here.

Posted in Development | Tagged , , , | 1 Comment