Archive

Posts Tagged ‘Testing’

Simplify Time Measurement in Tests and Debug Code

February 23rd, 2009

A simple helper class I derived from a more generic pattern: For debugging and testing, I quite often want to measure the time used for a given process. Usually, this looks somewhat like this:

 

public void TestElapsedTime()
{
  DateTime start = DateTime.Now;

  //do some work

  DateTime end = DateTime.Now;
  double elapsedTime = end.Subtract(start).TotalMilliseconds;
  Console.Out.WriteLine("Work took {0} milliseconds", elapsedTime);
}

 

However: The code above, while being pretty simple, can be easily wrapped into a generic helper class:

 

/// <summary>
/// A guard that can be used to measure the time
/// used for a given process by simply wrapping it
/// in a using statement.
/// </summary>
public class TimeGuard : IDisposable
{
  private readonly Action<double> action;
  private readonly DateTime startTime;


  /// <summary>
  /// Creates the guard with a given action that receives the
  /// elapsed time in milliseconds.
  /// </summary>
  /// <param name="setDelta">The action that is being invoked
  /// with time (in milleconds) that was taken between construction
  /// of this instance until disposal.</param>
  /// <exception cref="ArgumentNullException">If <paramref name="setDelta"/>
  /// is a null reference.</exception>
  public TimeGuard(Action<double> setDelta)
  {
    if (setDelta == null) throw new ArgumentNullException("setDelta");
    
    action = setDelta;
    startTime = DateTime.Now;
  }


  /// <summary>
  /// Calculates the elapsed time since construction
  /// and submits the delta to the <see cref="action"/>
  /// action.
  /// </summary>
  public void Dispose()
  {
    var now = DateTime.Now;
    action(now.Subtract(startTime).TotalMilliseconds);
  }
}

 

Using the TimeGuard class, I can perform time measurements without having to deal with DateTime instances and the calculation of the elapsed time at all. Two samples:

 

public void TestElapsedTime()
{
  double elapsedTime = 0;
  using (new TimeGuard(t => elapsedTime = t))
  {
    //do some work
  }

  Console.Out.WriteLine("Work took {0} milliseconds", elapsedTime);
}

 

[Test]
public void TestElapsedTime()
{
  using (new TimeGuard(t => Assert.Less(t, 500)))
  {
    //do some work here that should take less than 500 ms
  }
}

 

Apart from providing cleaner code, I also prefer this approach because it encapsulates time measurement functionality in a single class and simplifies adjustments, like using a different pattern to retrieve time stamps, or using the StopWatch class to get a more accurate measurement (thanks to Simone Chiaretta for the hint).

Author: Categories: C#, Testing Tags:

Generic Extension Methods to Test INotifyPropertyChanged

November 22nd, 2008

Just two extension methods I wrote in order to simplify testing of classes that implement INotifyPropertyChanged.

The first one just checks that the PropertyChanged event fires once and for the specified property:

 
/// <summary>
/// Checks whether a given action produces a change event for
/// a given property.
/// </summary>
/// <typeparam name="T">A class that implements <see cref="INotifyPropertyChanged"/>.
/// </typeparam>
/// <param name="host">The object that contains the changed property.</param>
/// <param name="changeAction">An action that triggers the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
/// <param name="propertyName">The name of the changed property, as advertised by the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
public static void AssertFiresPropertyChangedEvent<T> (this T host, string propertyName,
                                                       Action<T> changeAction)
                                                       where T : INotifyPropertyChanged
{
  bool fired = false;
  
  //register handler with assertion
  PropertyChangedEventHandler handler = (sender, e) =>
    {
      fired = true;
      Assert.AreEqual(propertyName, e.PropertyName);
    };

  //register listener, trigger action, then deregister
  host.PropertyChanged += handler;
  changeAction(host);
  host.PropertyChanged -= handler;

  Assert.IsTrue(fired);
}
 
Now in order to run my test, I can write something like this as long as I’m not having multiple threads that change my object under test:
 
 
//create new user
User user = new User("Tim");

//make sure changing the name raises event
user.AssertFiresPropertyChangedEvent("Name", u => u.Name = "Tom");

 

The second extension method makes sure the event is fired a given number of times for a specified property. Apart from the obvious one (looping a few times), this one has additional use cases:

  • I can test that the event doesn’t fire at all by setting the expected number of events to 0.
  • This method ignores events for other properties, whereas the snippet above fails.

 

/// <summary>
/// Checks whether a given action produces a specified number of property
/// change events for a given property.<br/>
/// This event listener just ignores event for properties other than
/// <paramref name="propertyName"/>.
/// </summary>
/// <typeparam name="T">A class that implements <see cref="INotifyPropertyChanged"/>.
/// </typeparam>
/// <param name="host">The object that contains the changed property.</param>
/// <param name="numberOfEvents">The expected number of change events for
/// the specified property</param>
/// <param name="changeAction">An action that triggers the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
/// <param name="propertyName">The name of the changed property, as advertised by the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
public static void AssertPropertyChangedEventCount<T>(this T host, string propertyName,
                                                      int numberOfEvents,
                                                      Action<T> changeAction)
                                                      where T : INotifyPropertyChanged
{
  int eventCount = 0;

  //register handler with assertion
  PropertyChangedEventHandler handler = (sender, e) =>
    {
      //increment if the event refers to the tested property
      if (e.PropertyName == propertyName) eventCount++;
    };

  //register handler, trigger action, then deregister
  host.PropertyChanged += handler;
  changeAction(host);
  host.PropertyChanged -= handler;

  //compare counted events with expected number
  Assert.AreEqual(numberOfEvents, eventCount);
}

 

Update:

If you want to test a full set of properties of a class at once, check out Josh Twist’s ClassTester: This handy little library simplifies things remarkably when it comes to testing complete classes or even assemblies.

Author: Categories: C#, Testing Tags: