Thursday, January 27, 2011

What is QuickUnit.net ?

May 2007.

QuickUnit.net is unit test framework of another kind. The key idea was to define test case input and output values as .NET attributes in the source code itself.

It was inspired by the post Annotating Your Code with Simple Tests from Leon Bambrick in may 2007.

QuickUnit.net was an experiment and because .NET attribute only support array of value type, building complex set of input and output data was not feasible.

The main feature still worth looking at it.

QuickUnit.net is written in C# 3.5 with samples in C# and VB.NET.

Download the source code.


Unit Testing IsALeapYear() Function

Assign the .NET attribute TestMethod to the method, define the expected value and the parameter set.

///  
/// Is Year a leap year? 
///  
/// The year in question///  
/// true if year is a leap year. false otherwise 
///  
[
    TestMethod( true  , 2000 ),
    TestMethod( false , 1900 ),
    TestMethod( true  , 1996 ),
    TestMethod( false , 2003 ),
    TestMethod( false , 1973 ),
    TestMethod( false , 1971 )
]
public  static  bool  IsALeapYear(int  year) {

    return  (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0);
}


Command Line Parameters

QuickUnit.net's tests can be executed by using the QuickUnit.net Console.

QuickUnit.net.Console.exe -a MyAssembly.dll [-class classname1,classname2] [-method methodname1,methodname2] [-logo false] [-pause true]
The exit code returns the number of error. During the build process, execute your QuickUnit.net unit tests before calling your unit tests implemented with an xUnit framework.


Unit Testing FullName Property

Here we test a property and also define the parameter set for the class constructor.

[TestClass()]
public  class  CPerson  {

    private  string       _LastName;
    private  string       _FirstName;
    
    public  CPerson(string  firstName, string  lastName) {
    
        this .FirstName  = firstName;
        this .LastName   = lastName;        
    }
    
    ///  
    /// Gets the full name. 
    ///  
    /// The full name. 
    [
        QuickUnit.Net.TestProperty("Joe Smith" , new  object [] { "Joe" , "Smith"  }) , 
        QuickUnit.Net.TestProperty("John Doe" ,  new  object [] { "John" , "Doe"   })
    ]
    public  string  FullName {
    
        get  { return  this .FirstName + " "  + this .LastName; }
    }
}    


 

Unit Testing AgeAt() Function

This example shows how to define the type of the parameters used when it is not infered.

///  
     /// If person was born on birthdate,'s their age, in whole years at atDate? 
/// 
/// The birth date./// At date./// Age in years (floored)
[
    TestMethod(43, new  object [] { "12/11/1964"  , "07/01/2007"  }),
    TestMethod(50, new  object [] { "12/11/1964"  , "07/01/2014"  }),
    TestMethod(15, new  object [] { "10/29/1992"  , "07/01/2007"  }),
    TestMethod(16, new  object [] { "10/29/1992"  , "07/01/2008"  }),
    TestMethod( 9, new  object [] { "01/29/1998"  , "07/01/2007"  }),
    TestMethod(10, new  object [] { "01/29/1998"  , "07/01/2008"  }),
]
public  int  AgeAt(DateTime birthDate, DateTime atDate) {

    System.TimeSpan TS = new  System.TimeSpan(atDate.Ticks-birthDate.Ticks);
    return  Convert.ToInt32(TS.TotalDays/365.25);
}



Expect an Exception

This example shows how to define the type of the parameters used when it is not infered.

[
    TestMethod(EX.EXCEPTION, typeof (System.DivideByZeroException ), new  object [] { 64, 0 } ),
    TestMethod( 3, new  object [] {  6, 2 } ),
    TestMethod(32, new  object [] { 64, 2 } )
]
public  int  DivInt(int  a, int  b) {

    return  a / b;
}


Pass an array

This example shows how to define the type of the parameters used when it is not infered.

[
    TestMethod(    3, new  object [] { new  int [] { 1,      2            } } ),
    TestMethod(11100, new  object [] { new  int [] { 100, 1000, 10000     } } ),
    TestMethod(  -10, new  object [] { new  int [] {  -1,   -2,    -3, -4 } } )
]
public int SumIntArray(int [] intValues) {

    int  a = 0;

    foreach  (int  i in  intValues) {

        a += i;
    }
    return  a;
}



Default and specific constructor value


[TestClass(new  object [] { 1 })] // Default constructor value
public  class  TestClassIntegerUnitTest  {

    private  int  _InitializedValue = -1;
    
    public  TestClassIntegerUnitTest(int  initializedValue) {
    
        this ._InitializedValue = initializedValue;
    }
    
    [
        TestMethod(1, new  object [] {} ), // Use the default constructor parameter value
        TestMethod(2, new  object [] {} , new  object [] {2}) // Define a constructor parameter value
    ]
    public  int  InitializedValue() {
    
        return  this ._InitializedValue;
    }
}


Testing the function IsInArray()


[
    // Value not in the array ignore case or not
    TestMethod(false , new  object [] { "Z" ,  new  string [] { "A" , "B"  , "C"  } , true   } ),
    TestMethod(false , new  object [] { "Z" ,  new  string [] { "A" , "B"  , "C"  } , false  } ),
    
    // Value in the array ignore case or not
    TestMethod(true ,  new  object [] { "A" ,  new  string [] { "A" , "B"  , "C"  } , true   } ),
    TestMethod(true ,  new  object [] { "A" ,  new  string [] { "A" , "B"  , "C"  } , false  } ),
    
    // Value in the array if ignore case
    TestMethod(true ,  new  object [] { "a" ,  new  string [] { "A" , "B"  , "C"  } , true   } ),
    TestMethod(false , new  object [] { "a" ,  new  string [] { "A" , "B"  , "C"  } , false  } ),
    
    // Value in the array if ignore case - variant
    TestMethod(true ,  new  object [] { "A" ,  new  string [] { "a" , "B"  , "C"  } , true   } ),
    TestMethod(false , new  object [] { "A" ,  new  string [] { "a" , "B"  , "C"  } , false  } ),
    
    // Value not in a empty array  ignore case or not
    TestMethod(false , new  object [] { "A" ,  new  string [] {                } , false  } ),
    TestMethod(false , new  object [] { "A" ,  new  string [] {                } , true   } ),
    
    // Null value not in the array ignore case or not
    TestMethod(false , new  object [] { null , new  string [] { "a" , "B"  , "C"  } , true   } ),
    TestMethod(false , new  object [] { null , new  string [] { "a" , "B"  , "C"  } , false  } ),
    
    // Null value in the array case ignore case or not
    TestMethod(true ,  new  object [] { null , new  string [] { "a" , "B"  , null } , true   } ),
    TestMethod(true ,  new  object [] { null , new  string [] { "a" , "B"  , null } , false  } ),
    
    // We do not pass an array, we pass null ignore case or not
    TestMethod(EX.EXCEPTION, typeof (System.NullReferenceException ),  new  object [] { "A" ,  null  , true    } ),
    TestMethod(EX.EXCEPTION, typeof (System.NullReferenceException ),  new  object [] { "A" ,  null  , false   } ),
]
public  static  bool  IsInArray(string  value, string [] values, bool  ignoreCase) {
    
    if  ( (ignoreCase) && (value!=null ) ) value = value.ToLower();
    
    foreach  (string  ss in  values) {
    
        string  s = ss;
        
        if  ( (ignoreCase) && (s!=null ) ) s = s.ToLower();
        
        if  (s == value) {
        
            return  true ;
        }
    }
    return  false ;
}



HiShort()


[
    TestMethod(  0,     0),
    TestMethod(  0,     1),
    TestMethod(  0,     2),
    TestMethod(  0,     4),
    TestMethod(  0,     8),
    TestMethod(  0,    16),
    TestMethod(  0,    32),
    TestMethod(  0,    64),
    TestMethod(  0,   128),
    TestMethod(  1,   256),
    TestMethod(  2,   512),
    TestMethod(  4,  1024),
    TestMethod(  8,  2048),
    TestMethod( 16,  4096),
    TestMethod( 32,  8192),
    TestMethod( 64, 16384),
    TestMethod(127, 32767)
]
public  static  int  HiShort(short  number) {

    return  (number >> 8) & 0xff;
}



Fibonacci()


[
    TestMethod(      0 ,  0 ),
    TestMethod(      1 ,  1 ),
    TestMethod(      1 ,  2 ),            
    TestMethod(      2 ,  3 ),
    TestMethod(      3 ,  4 ),
    TestMethod(      5 ,  5 ),
    TestMethod(     55 , 10 ),
    TestMethod(    610 , 15 ),
    TestMethod(   6765 , 20 ),
    TestMethod( 832040 , 30 )
]
public  static  int  Fibonacci(int  n){
    switch (n){
        case  0 : return  0;
        case  1 : return  1;
        default  : return  Fibonacci(n-1) + Fibonacci(n-2);
    }
}

No comments:

Post a Comment