Test helpers #1: Repetition Extensions and Scenario

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
&#91;/sourcecode&#93;</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]

Ping-services for your blog posts

I just wrote off some ping urls (some german services, too) from the book Website Boosting 2.0 by Mario Fisher. When posting with Windows Live Writer these can be configured for beeing pinged on publishing new blog posts. Several blog engines also have configuration options or plugins for auto-pinging available.

http://blo.gs
http://weblogs.com
http://blogsearch.google.com/ping
http://blogsearch.google.com/ping/RPC2
http://blogg.de/ping.php
http://rpc.technorati.com/rpc/ping
http://blogoole.com/ping/
http://api.feedster.com/ping
http://api.my.yahoo.com/RPC2
http://api.my.yahoo.com/rss/ping
http://bblog.com/ping.php
http://blogmatcher.com/u.php
http://bulkfeeds.net/rpc
http://coreblog.org/ping/
http://ping.feedburner.com
http://ping.syndic8.com/xmlrpc.php
http://ping.wordblog.de/
http://rpc.blogbuzzmachine.com/RPC2
http://rpc.blogrolling.com/pinger/
http://rpc.newsgator.com/
http://rpc.pingomatic.com/
http://rpc.weblogs.com/RPC2
http://www.bloglines.com/ping
http://www.pingomatic.com/
http://xmlrpc.blogg.de