TheJoyOfCode.QualityTools.PropertyTester

The PropertyTester (formerly known as the ClassTester) automatically tests properties by calling the set and get methods and ensuring that the same value is returned. If the property is a set only or get only then this check can't be made but the set and get will be called.

Here's an example object that might be targetted with such a test:

public class Person
{
    private string _name;
 
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
 
    private DateTime _dateOfBirth;
 
    public DateTime DateOfBirth
    {
        get { return _dateOfBirth; }
        set { _dateOfBirth = value; }
    }
 
    public double AgeInDays
    {
         get {  return (DateTime.Today.Subtract(_dateOfBirth).TotalDays);  }
    }

    private ISomeProvider _provider

    public ISomeProvider Provider
    {
        get { return _provider; }
        set { _provider= value; }
    }
    // etc..
}


Which could be tested like so.

   PropertyTester tester = new PropertyTester(new Person());
   tester.TestProperties();


This would give great coverage of this class testing Name, DateOfBirth and AgeInDays properties with only one problem...

Obviously, to call set the PropertyTester must create a type to pass as a value. It has a TypeFactory to support the creation of types but there are limitations to the types that it can create. For more information see TypeFactory. The most obvious limitations are abstract classes (including interfaces) and classes with non-default constructors.

Note: The functionality in the AgeInDays property is NOT validated by the PropertyTester and we'd recommend you test this using a seperate, manual unit test.

If you try to TestProperties() on a Class that exposes a property of an unsupported type (like our ISomeProvider type) you will get a PropertyTestException thrown with a message along the lines of:

"Cannot generate type 'ISomeProvider' to set on property 'Provider'. Consider ignoring this property on the type 'Person'"

This doesn't mean that you can't use the PropertyTester with this type, we just need to exclude that particular property.

Exclusions

It's easy to exclude a property from the test:

    PropertyTester tester = new PropertyTester(new Person());
    tester.IgnoredProperties.Add("Provider");
    tester.TestProperties();

INotifyPropertyChanged support

One of the key motivations for creating the original ClassTester was to test that classes implementing INotifyPropertyChanged fire the correct events appropriately. Here's an example implementation:

public class Person : INotifyPropertyChanged
{
    private string _name;
 
    public string Name
    {
        get { return _name; }
        set 
        { 
            _name = value; 
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Name"));
        }
    }


As you can imagine, authoring such classes is error prone and therefore testing this functionality is important.

The PropertyTester automatically inspects classes to see if they implement INotifyPropertyChanged and verifies that PropertyChangedEvents are raised when the value of the property changes.

Note: The PropertyTester will try to set the value once and then set it again with a different value to test for PropertyChangedEvents (because you may implement INotifyPropertyChanged to only fire if the value actually changes!). Therefore, if the TypeFactory can't generate two different random values you will get a PropertyTestException: "Could not generate two different values for the type 'SomeType'. Consider ignoring the 'YourProperty' property on the type 'YourType' or increasing the MaxLoopsPerProperty value above 1000".

Last edited Jan 4, 2008 at 11:46 AM by molmorg, version 2

Comments

No comments yet.