Thursday, June 17, 2010

Simple tool for unit testing

The below unit testing example has UnitTestingTool class, Logger class and few unit test cases for the Logger class.

UnitTestingTool is the class used for unit testing.
It supports testing function which returns bool, object,
string data types. It also has the counts of passed and failed test cases.
The pass and fail counts can be reset to zero and also displayed on the console.

Logger is the class which is unit tested.
The Logger class is used for logging string message to a text file.
The Logger class function call sequence is
  1. Create Logger object
  2. Call Open function
  3. Call WriteToFile function
  4. Call Close function
C# example- Simple unit testing tool.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace UTLogger
{
    //unit testing tool class
    class UnitTestingTool
    {
        private int m_iPassCount = 0;
        private int m_iFailCount = 0;
        public UnitTestingTool()
        {
        }
        public void Reset()
        {
            m_iPassCount = 0;
            m_iFailCount = 0;
        }
        public bool ValidateBool(bool blnResult,
            bool blnExpectedResult, string strRemarks)
        {
            bool blnStatus = false;
            StringBuilder objSBResult = new StringBuilder();
            if (blnExpectedResult == blnResult)
            {
                m_iPassCount++;
                blnStatus = true;
            }
            else
            {
                m_iFailCount++;
                objSBResult.AppendLine("Bool test failed:"
                    + strRemarks);
                objSBResult.AppendLine("Result:"
                    + blnResult);
                objSBResult.AppendLine("Expected Result:"
                    + blnExpectedResult);
                Console.WriteLine(objSBResult);
            }
            return blnStatus;
        }
        public bool ValidateObject(object objResult,
            object objExpectedResult, string strRemarks)
        {
            bool blnStatus = false;
            StringBuilder objSBResult = new StringBuilder();
            if (objExpectedResult == objResult)
            {
                m_iPassCount++;
                blnStatus = true;
            }
            else
            {
                m_iFailCount++;
                objSBResult.AppendLine("Object test failed:"
                    + strRemarks);
                objSBResult.AppendLine("Result:"
                    + objResult);
                objSBResult.AppendLine("Expected Result:"
                    + objExpectedResult);
                Console.WriteLine(objSBResult);
            }
            return blnStatus;
        }
        public bool ValidateString(string strResult,
            string strExpectedResult, string strRemarks)
        {
            bool blnStatus = false;
            StringBuilder objSBResult = new StringBuilder();
            if (strExpectedResult == strResult)
            {
                m_iPassCount++;
                blnStatus = true;
            }
            else
            {
                m_iFailCount++;
                objSBResult.AppendLine("string test failed:"
                    + strRemarks);
                objSBResult.AppendLine("Result:"
                    + strResult);
                objSBResult.AppendLine("Expected Result:"
                    + strExpectedResult);
                Console.WriteLine(objSBResult);
            }
            return blnStatus;
        }
        public void DisplayResult()
        {
            StringBuilder objSBResult = new StringBuilder();
            objSBResult.AppendLine("Test result");
            objSBResult.AppendLine("------------------------");
            objSBResult.AppendLine("Pass count:" + m_iPassCount);
            objSBResult.AppendLine("Fail count:" + m_iFailCount);
            objSBResult.AppendLine("------------------------");
            objSBResult.AppendLine("Total count:"
                + (m_iPassCount + m_iFailCount));
            Console.WriteLine(objSBResult);

        }

    }
    class Logger
    {
        public string FilePath { get; set; }
        private StreamWriter m_objStreamWriter = null;
        private object m_objLocker;
        public Logger()
        {
            m_objLocker=new object();
            FilePath = @"d:\log.txt";
        }
        public bool Open()
        {
            bool blnStatus = false;
            try
            {
                m_objStreamWriter = new StreamWriter(FilePath, true);
                blnStatus = true;
            }
            catch (Exception objEx)
            {
                Console.WriteLine(objEx.StackTrace);
            }
            finally
            {
            }
            return blnStatus;
        }
        public bool Close()
        {
            bool blnStatus = false;
            try
            {
                if (m_objStreamWriter != null)
                {
                    m_objStreamWriter.Close();
                    blnStatus = true;
                }
            }
            catch (Exception objEx)
            {
                Console.WriteLine(objEx.StackTrace);
            }
            finally
            {
            }
            return blnStatus;
        }
        //make sure Open is called before calling WriteToFile
        //make sure Close is called once all logging is done
        public bool WriteToFile(string strMessage)
        {
            bool blnStatus = false;
            if (strMessage != string.Empty && strMessage != null)
            {
                try
                {
                    lock (m_objLocker)
                    {
                        if (m_objStreamWriter != null)
                        {
                            //logs only the time and not the date
                            m_objStreamWriter.WriteLine(
                                DateTime.Now.TimeOfDay
                                + " - "
                                + strMessage
                                );
                            blnStatus = true;
                        }

                    }
                }
                catch (Exception objEx)
                {
                    //use messagebox if winforms application
                    Console.WriteLine(objEx.StackTrace);
                }
                finally
                {
                }
            }
            return blnStatus;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Logger objLogger = null;
            UnitTestingTool objUTT = null;
            objLogger = new Logger();
            objUTT = new UnitTestingTool();
            bool blnStatus = false;
            blnStatus = objUTT.ValidateBool(
                objLogger.WriteToFile(""),
                false,
                "EmptyString Message"
                );
            if (true == blnStatus)
            {
                blnStatus=objUTT.ValidateBool(
                    objLogger.WriteToFile(null),
                    false,
                    "null Message"
                    );
            }
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.WriteToFile("test1"),
                    false,
                    "Valid Message without opening the logger"
                    );
            }
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.Close(),
                    false,
                    "Close objLogger without opening"
                    );
            }
            //invalid filepath
            objLogger.FilePath = @"z:\log.txt";
            //expect the exception message on the console
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.Open(),
                    false,
                    "Open objLogger with invalid filepath"
                    );
            }
            //valid filepath
            objLogger.FilePath = @"d:\log.txt";
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.Open(),
                    true,
                    "Open objLogger with valid filepath"
                    );
            }
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.WriteToFile("test1"),
                    true,
                    "Valid Message"
                    );
            }
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.WriteToFile("test2"),
                    true,
                    "Valid Message"
                    );
            }
            if (true == blnStatus)
            {
                blnStatus = objUTT.ValidateBool(
                    objLogger.Close(),
                    true,
                    "Close objLogger"
                    );
            }
            objUTT.DisplayResult();
            Console.ReadLine();
        }
    }
}

Output:
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, I
nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions o
ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access,
FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamWriter.CreateFile(String path, Boolean append)
   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encodin
g, Int32 bufferSize)
   at System.IO.StreamWriter..ctor(String path, Boolean append)
   at UTLogger.Logger.Open() in D:\code2009\Sample\UTLogger\Program.cs:line 121
Test result
------------------------
Pass count:9
Fail count:0
------------------------
Total count:9

Note: The above UnitTestingTool class can be extended for other data types.

No comments: