While writing tons of tests I would like to share some of my helper classes here. My first ones are for doing simple performance measurements (not too accurate) and repeating actions.
Code:
using (new Scenario("Sum of all squares from 1 to 100")) Console.WriteLine("Sum is: {0}", 100.Times(x => x * x).Sum()); using (new Scenario("Print all squares from 1 to 10")) 10.Times(x => Console.WriteLine("{0} * {0} = {1}", x, x*x));
Output:
>> {1} - Sum of all squares from 1 to 100 Sum is: 1000000 << {1} 15ms for Sum of all squares from 1 to 100 >> {2} - Print all squares from 1 to 10 1 * 1 = 1 2 * 2 = 4 3 * 3 = 9 4 * 4 = 16 5 * 5 = 25 6 * 6 = 36 7 * 7 = 49 8 * 8 = 64 9 * 9 = 81 10 * 10 = 100 << {2} 13ms for Print all squares from 1 to 10 [/sourcecode]</pre></div> <h2>Repetition Extensions</h2> <div style="display:inline;float:none;margin:0;padding:0;" id="scid:4CF65DF0-5960-450c-B43D-AE27EAE72175:64baee98-e9e4-4a96-9dc8-a453ac2997da" class="wlWriterEditableSmartContent"><pre> public static class RepetitionExtensions { public static IEnumerable<int> Times(this int count) { for (int i = 1; i <= count; i++) { yield return i; } } public static void Times(this int count, Action<int> action) { foreach (var i in count.Times()) { action(i); } } public static void Times(this int count, Action action) { count.Times((i) => action()); } public static TResult[] Times<TResult>(this int count, Func<TResult> action) { var results = new List<TResult>(count); count.Times(() => results.Add(action())); return results.ToArray(); } public static TResult[] Times<TResult>(this int count, Func<int, TResult> action) { var results = new List<TResult>(count); count.Times(() => results.Add(action(count))); return results.ToArray(); } public static IEnumerable<TResult> LazyTimes<TResult>(this int count, Func<TResult> action) { foreach (var i in count.Times()) { yield return action(); } } public static IEnumerable<TResult> LazyTimes<TResult>(this int count, Func<int, TResult> action) { foreach (var i in count.Times()) { yield return action(i); } } }
Scenario
public class Scenario : IDisposable { private readonly string message; private readonly Stopwatch stopwatch = new Stopwatch(); private static int nextUid = 0; private int uid = nextUid+=1; public Scenario(string message) { this.message = message; stopwatch = new Stopwatch(); Console.WriteLine(">> {{{0}}} - {1}", uid, message); stopwatch.Start(); } public void Dispose() { stopwatch.Stop(); var elapsed = stopwatch.Elapsed; var elements = new List(4); if (elapsed.Days != 0) elements.Add(string.Format("{0} days", elapsed.Days)); if (elapsed.Hours != 0) elements.Add(string.Format("{0} hours", elapsed.Hours)); if (elapsed.Minutes != 0) elements.Add(string.Format("{0} minutes", elapsed.Minutes)); if (elapsed.Seconds != 0 && elapsed.Milliseconds != 0) elements.Add(string.Format("{0}.{1}s", elapsed.Seconds, elapsed.Milliseconds)); else if (elapsed.Seconds != 0) elements.Add(string.Format("{0}s", elapsed.Seconds)); else if (elapsed.Milliseconds != 0) elements.Add(string.Format("{0}ms", elapsed.Milliseconds)); var formatted = new StringBuilder(); if (elements.Count > 0) { if (elements.Count > 1) { formatted.Append(string.Join(", ", elements.Take(elements.Count - 1).ToArray())); formatted.Append(" and "); } formatted.Append(elements.Last()); } Console.WriteLine(string.Format("<< {{{0}}} {1} for {2}", uid, formatted, message)); } } [/sourcecode]