Testing your logging functionality, using the Enterprise library and a custom trace listener. As I was in need of a method to test some loggin functions, i googled away and found this exellent article
<http://blogs.msdn.com/ploeh/archive/2006/04/06/
UnitTestYourEnterpriseLibraryLoggingLogic.aspx> by ploeh.
I have slightly modified this code to use a text file, allowing me to view the test data in a text file and read it back in. Here is my alterations (consider this a small tribute to a great article.)
In the rest of this article i will go through the differences
the Write and WriteLine methods output the the textfile
/// <summary>
/// Overriden write menthod, this will write directly to
/// the log
/// </summary>
/// <param name="message"></param>
public override void Write(string message)
{
StreamWriter sw = null;
try
{
sw = new StreamWriter(CreateLog());
sw.Write(message);
}
catch (Exception ex)
{
throw new Exception("cannot write to file :", ex);
}
finally
{
if (sw != null)
sw.Close();
}
}
/// <summary>
/// Write line
/// </summary>
/// <param name="message"></param>
public override void WriteLine(string message)
{
StreamWriter sw = null;
try
{
sw = new StreamWriter(CreateLog());
sw.WriteLine(message);
sw.WriteLine("<--End-->");
sw.WriteLine("");
}
catch (Exception ex)
{
throw new Exception("cannot writeline to file :", ex);
}
finally
{
if (sw != null)
sw.Close();
}
}
The overriden TraceData method remins similar just removed the addtion to the collection
public override void TraceData(TraceEventCache eventCache,
string source, TraceEventType eventType, int id,
object data)
{
LogEntry le = data as LogEntry;
if (le != null)
{
if (Formatter != null)
{
WriteLine(Formatter.Format(le));
return;
}
}
base.TraceData(eventCache, source, eventType, id, data);
}
now when you add this to your Logging as a listner it will produce a log which will look similar to this
[code]
Timestamp: 04/02/2008 15:58:04
Message: 3ef9ed0b-33a2-4701-8b98-c76b4ace8ae0
Category: General
Priority: 1
EventId: 123
Severity: Critical
Title:unit test 04/02/2008 15:58:04
Machine: machineName
Application Domain: UnitTestAdapterDomain_ForD:\TestLogging.dll
Process Id: 2296
Process Name: C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\vstesthost.exe
Win32 Thread Id: 344
Thread Name: AdpaterExeMgrThread1
Extended Properties:
<--End-->
Timestamp: 04/02/2008 19:04:34
Message: 33beaba7-4d21-4d55-a7ac-629877cdaac0
Category: General
Priority: 1
EventId: 123
Severity: Critical
Title:unit test 04/02/2008 19:04:33
Machine: machineName
Application Domain: UnitTestAdapterDomain_ForD:\TestLogging.dll
Process Id: 4276
Process Name: C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\vstesthost.exe
Win32 Thread Id: 5940
Thread Name: AdpaterExeMgrThread1
Extended Properties:
<--End-->
So Now we need a function or two to get the results back as log objects, allowing us to write unit tests against the results. Using regular expressions, we can get all the information quite simply :
[code]
((?:Timestamp\:)(?<Timestamp> .*))
((?:Message\:)(?<Message>(.|[\n\r])*?))
((?:Category\:)(?<Category> .*))
((?:Priority\:)(?<Priority> .*))
((?:EventId\:)(?<EventId> .*))
((?:Severity\:)(?<Severity> .*))
((?:Title\:)(?<Title>.*))
((?:Machine\:)(?<Machine> .*))
((?:Application Domain\:)(?<ApplicationDomain> .*))
((?:Process Id\:)(?<ProcessId> .*))
((?:Process Name\:)(?<ProcessName> .*))
((?:Win32 Thread Id\:)(?<Win32ThreadId> .*))
((?:Thread Name\:)(?<ThreadName> .*))
((?:Extended Properties\:)(?<ExtendedProperties>(.|[\n\r])*?))
This regex will work for the default formatter which the Patterns and Practices uses. As you may have noticed it uses groups, allowing for us to easily reference the values in a method to retrive. The following takes the above regex and populates the values into LogEntry objects
/// <summary>
/// load all the log into an array
/// </summary>
/// <param name="fileLocation"></param>
/// <returns></returns>
public static List<LogEntry> GetAllLogEntries()
{
Regex reg = new Regex(logRegEx, RegexOptions.Multiline);
string log = File.ReadAllText(LogLocation);
List<LogEntry> result = new List<LogEntry>();
MatchCollection mC = reg.Matches(log);
LogEntry l;
Console.WriteLine("loading data");
foreach (Match m in mC)
{
l = new LogEntry();
l.Message = m.Groups["Message"].ToString().Trim();
l.TimeStamp = DateTime.Parse(m.Groups["Timestamp"].ToString().Trim());
l.Priority = int.Parse(m.Groups["Priority"].ToString().Trim());
l.Title = m.Groups["Title"].ToString().Trim();
result.Add(l);
}
Console.WriteLine("loaded " + result.Count.ToString() + "logs entries");
return result;
}
Its simple to use, I placed this in a Class library built it and then referenced it from the logger and from my unit tests.
TextTraceListener.cs (6.34 kb)
Todo:
add this into a class library project. (give it the name :LoggingLibraryTest)
Compile the project (this will generate a DLL file.)
reference the DLL with in your TDD ptoject, and also set the Enterprise logging to custom and point the custom listner to a copy of the DLL.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5