I Heart ReSharper!

Friday, April 03, 2009 3:56:27 PM (Mountain Standard Time, UTC-07:00)

I'm still surprised by just how many people still aren't using ReSharper. It's an amazing productivity adding for Microsoft Visual Studio.  Once you've spent the time learning a few keyboard shortcuts you will not go back to naked studio.

There are few things that are more frustrating then jumping on a machine that doesn't have ReSharper installed, then trying to edit some .cs files.

In an effort to prevent myself from ever having to jump on a pc that's still missing the glory of ReSharper, I decided to throw together a quick screen cast showcasing some of the features i enjoy.

ReSharper Warm Fuzzies Screen cast

If you haven't already. please, please give it a try (do it for me). It's a good addiction!

#

BDD on Creatine

Thursday, March 12, 2009 9:46:14 AM (Mountain Standard Time, UTC-07:00)

In an attempt to further understand BDD, I chose to revise the code from my previous post after receiving some amazing advice from two people I regard highly (Scott & JP). I should state that this is my interpretation of that advice. This may or may not be the direction they were trying to guide me towards.

   12 public class when_prompted_to_save_changes_to_the_project : concerns_for<SaveChangesView>

   13 {

   14     context c = () => { presenter = an<ISaveChangesPresenter>(); };

   15 

   16     after_the_sut_has_been_created after = () =>

   17                                                {

   18                                                    save_changes_window = sut;

   19                                                    save_changes_window.attach_to(presenter);

   20                                                };

   21 

   22     protected static ISaveChangesPresenter presenter;

   23     protected static SaveChangesView save_changes_window;

   24 }

   25 

   26 public class when_the_save_button_is_pressed : when_prompted_to_save_changes_to_the_project

   27 {

   28     it should_save_the_current_project = () => presenter.was_told_to(x => x.save());

   29 

   30     because b = () => save_changes_window.save_button.control_is(x => x.OnClick(new EventArgs()));

   31 }

   32 

   33 public class when_the_cancel_button_is_pressed : when_prompted_to_save_changes_to_the_project

   34 {

   35     it should_not_continue_processing_the_previous_action = () => presenter.was_told_to(x => x.cancel());

   36 

   37     because b = () => save_changes_window.cancel_button.control_is(x => x.OnClick(new EventArgs()));

   38 }

   39 

   40 public class when_the_do_not_save_button_is_pressed : when_prompted_to_save_changes_to_the_project

   41 {

   42     it should_not_save_the_project = () => presenter.was_told_to(x => x.dont_save());

   43 

   44     because b = () => save_changes_window.do_not_save_button.control_is(x => x.OnClick(new EventArgs()));

   45 }

 

I hope this is slightly more soluble, then my previous post.

#

BDD on Steroids

Wednesday, March 11, 2009 1:40:59 PM (Mountain Standard Time, UTC-07:00)

In the last couple of weeks I had a chance to sprinkle some of JP's syntactic sugar, all over my projects. It's amazing how much more concise my units test have become. I've had a couple of issues where I was mocking out the behavior of some Win Forms controls, but for the most part it's been an awesome experience!

I just wanted to take a moment to say Thank you JP! I am enjoying using your BDD (on steroids) extensions. If you haven't already you need to check it out here. NOW!

Maaad, maaaad props Mr. JP!

 

   10     public class behaves_like_save_changes_view_bound_to_presenter : concerns_for<SaveChangesView>

   11     {

   12         context c = () => { presenter = an<ISaveChangesPresenter>(); };

   13 

   14         because b = () => sut.attach_to(presenter);

   15 

   16         static protected ISaveChangesPresenter presenter;

   17     }

   18 

   19     public class when_the_save_button_is_clicked : behaves_like_save_changes_view_bound_to_presenter

   20     {

   21         it should_forward_the_call_to_the_presenter = () => presenter.was_told_to(x => x.save());

   22 

   23         because b = () => EventTrigger.trigger_event<Events.ControlEvents>(

   24                               x => x.OnClick(new EventArgs()),

   25                               sut.ux_save_button

   26                               );

   27     }

   28 

   29     public class when_the_cancel_button_is_clicked : behaves_like_save_changes_view_bound_to_presenter

   30     {

   31         it should_forward_the_call_to_the_presenter = () => presenter.was_told_to(x => x.cancel());

   32 

   33         because b = () => EventTrigger.trigger_event<Events.ControlEvents>(

   34                               x => x.OnClick(new EventArgs()),

   35                               sut.ux_cancel_button

   36                               );

   37     }

   38 

   39     public class when_the_do_not_save_button_is_clicked : behaves_like_save_changes_view_bound_to_presenter

   40     {

   41         it should_forward_the_call_to_the_presenter = () => presenter.was_told_to(x => x.dont_save());

   42 

   43         because b = () => EventTrigger.trigger_event<Events.ControlEvents>(

   44                               x => x.OnClick(new EventArgs()),

   45                               sut.ux_do_not_save_button

   46                               );

   47     }

 

Update: I posted the wrong link up top. here's the latest link.

#

Who do you wanna Jott? Twitter

Sunday, November 09, 2008 8:43:57 PM (Mountain Standard Time, UTC-07:00)

So I recently started twittering... or tweeting. I'm not sure what the correct lingo is, so hook me up if you know. It all started a while back when James announced that he was the newest Twit. He mentioned a WPF client called Witty, and I wanted to see what it was all about. So I setup a Twitter account to play with the app. After I had my fun, I never deleted my account. Or at least I never looked into how to delete my account.

About a week ago I received and email that a couple of people were following me on Twitter. Man that's flattering to read:

Hi, mo_khan.
Kyle Baley (kbaley) is now following your updates on Twitter.
Check out Kyle Baley's profile here:
http://twitter.com/kbaley
You may follow Kyle Baley as well by clicking on the "follow" button.
Best,
Twitter

Whaa... a celeb is interested in what I'm up to? *blush* So I jumped in, and so far it's been pretty fun. I found another service called "Jott". Jott's pretty cool, because I can call in to a number and I get an automated message that says:

"Who do you want to jott?"

I say ... "Twitter". Then I record my voice message.

Jott then takes that message transcribes it in to text, pushes it up to my twitter page, and drops a tinyurl to the actual audio. Sweet... that saves me a few pennies worth of text messages. But there's more...

I'm one of the poor saps who pay to much for mobile service up here in Canada, eh! I subscribe to Rogers Wireless, and the plan called "My5". I get to make unlimited phones calls to the 5 numbers that are in My5? So I put Jott on My5, and now I can shoot off messages to everyone for....

Free Ninety Nine.... well almost! If you're young, fabulous and ghetto broke (it aint funny) like myself then you ought to give Jott a try!

#

Container Configuration

Sunday, November 09, 2008 8:19:45 PM (Mountain Standard Time, UTC-07:00)

In my last post I briefly mentioned how we were wiring some components in to our container.  The syntax looked like the following:

            container.AddProxyOf(
                new ReportPresenterTaskConfiguration(), 
                new ReportPresenterTask(
                    Lazy.Load<IReportDocumentBuilder>(),
                    Lazy.Load<IApplicationSettings>())
                    );

We're using Castle Windsor under the hood, but we have an abstraction over it that allows us to configure it as we like. Even switching the underlying implementation. Which we did, from our hand rolled container to Castle Windsor. The implementation of the above method looks as follows:

        public void AddProxyOf<Interface, Target>(IProxyConfiguration<Interface> configuration, Target instance)
            where Target : Interface
        {
            var builder = new ProxyBuilder<Interface>();
            configuration.Configure(builder);
            AddInstanceOf(builder.CreateProxyFor(instance));
        }

Wikipedia defines the Proxy design pattern as:

A proxy, in its most general form, is a class functioning as an interface to another thing.

To understand the ProxyBuilder<Interface> implementation you can checkout JP's strongly typed selective proxies. The "AddProxyOf" method creates an instance of a proxybuilder. It then passes it to the configuration to allow it to configure the proxy builder before building the proxy. Then it registers the proxy as a singleton in to the container.

    public interface IConfiguration<T>
    {
        void Configure(T item_to_configure);
    }
    public interface IProxyConfiguration<T> : IConfiguration<IProxyBuilder<T>>
    {
    }

In this case the proxy configuration looks like:

    public class ReportPresenterTaskConfiguration : IProxyConfiguration<IReportPresenterTask>
    {
        public void Configure(IProxyBuilder<IReportPresenterTask> builder)
        {
            var constraint = builder.AddInterceptor<DisplayProgressBarInterceptor>();
            constraint.InterceptOn.RetrieveAuditReport();
        }
    }

This guy adds a progress bar interceptor, that displays a progress bar as the report is getting generated via the "RetrieveAuditReport" method on the IReportPresenterTask.

#

Lazy Loaded Interceptors

Sunday, November 09, 2008 2:55:32 PM (Mountain Standard Time, UTC-07:00)

Patterns of Enterprise Application Architecture defines Lazy Load as:

An object that doesn't contain all of the data you need but knows how to get it.

 

A while back I was trying to figure out how to lazy load objects from a container, so that I didn't need to depend on the objects dependencies needing to be wired up in the correct order. The syntax I was looking for was something like the following....

container.AddProxyOf(
    new ReportPresenterTaskConfiguration(),
    new ReportPresenterTask(
        Lazy.Load<IReportDocumentBuilder>(),
        Lazy.Load<IApplicationSettings>())
    );

Lazy.Load<T> will return a proxy in place of an actual implementation. This is just a temporary place holder that will forward the calls to the actual implementation. It wont load an instance of the actual type until the first time a call is made to it.

public class when_calling_a_method_with_no_arguments_on_a_lazy_loaded_proxy : lazy_loaded_object_context
{
    [Observation]
    public void should_forward_the_original_call_to_the_target()
    {
        target.should_have_been_asked_to(t => t.OneMethod());
    }

    protected override void establish_context()
    {
        target = dependency<ITargetObject>();

        test_container
            .setup_result_for(t => t.find_an_implementation_of<ITargetObject>())
            .will_return(target)
            .Repeat.Once();
    }

    protected override void because_of()
    {
        var result = Lazy.Load<ITargetObject>();
        result.OneMethod();
    }

    private ITargetObject target;
}

So when the method "OneMethod" is called on the proxy. It should forward the call to the target, which can be loaded from the container. The implementation depends on Castle DynamicProxy, and looks like the following...

public static class Lazy
{
    public static T Load<T>() where T : class
    {
        return create_proxy_for<T>(create_interceptor_for<T>());
    }

    private static LazyLoadedInterceptor<T> create_interceptor_for<T>() where T : class
    {
        Func<T> get_the_implementation = resolve.dependency_for<T>;
        return new LazyLoadedInterceptor<T>(get_the_implementation.memorize());
    }

    private static T create_proxy_for<T>(IInterceptor interceptor)
    {
        return new ProxyGenerator().CreateInterfaceProxyWithoutTarget<T>(interceptor);
    }
}

internal class LazyLoadedInterceptor<T> : IInterceptor
{
    private readonly Func<T> get_the_implementation;

    public LazyLoadedInterceptor(Func<T> get_the_implementation)
    {
        this.get_the_implementation = get_the_implementation;
    }

    public void Intercept(IInvocation invocation)
    {
        var method = invocation.GetConcreteMethodInvocationTarget();
        invocation.ReturnValue = method.Invoke(get_the_implementation(), invocation.Arguments);
    }
}

public static class func_extensions
{
    public static Func<T> memorize<T>(this Func<T> item) where T : class
    {
        T the_implementation = null;
        return () => {
                   if (null == the_implementation) {
                       the_implementation = item();
                   }
                   return the_implementation;
               };
    }
}

"resolve" is a static gateway to the underlying IDependencyRegistry. This idea was totally inspired by JP's strongly typed selective proxies. If you haven't already, you should definitely check it out.

Download the source.

#

I love milestones...

Thursday, November 06, 2008 11:20:23 AM (Mountain Standard Time, UTC-07:00)

I love being the guy to hit 1000 tests first... I guess I should check in first. doh!

one_thousand_tests

#

Mocking Queryables

Tuesday, November 04, 2008 10:01:09 AM (Mountain Standard Time, UTC-07:00)

Recently, we've been mocking out IQueryable's as return values, which had led to setups that look like the following...

programs.setup_result_for(x => x.All()).Return(new List<IProgram> {active_program,inactive_program}.AsQueryable());

I just switched over to the following syntax... by creating an extension method.

programs.setup_result_for(x => x.All()).will_return(active_program,inactive_program);

The following are the extensions methods to make this work.

public static IMethodOptions<IEnumerable<R>> will_return<R>(this IMethodOptions<IEnumerable<R>> options,
                                                            params R[] items)
{
    return options.Return(items);
}

public static IMethodOptions<IQueryable<R>> will_return<R>(this IMethodOptions<IQueryable<R>> options,
                                                           params R[] items)
{
    return options.Return(new Query<R>(items));
}

and...

 internal classQuery<T> : IQueryable<T>
{
    private readonly IQueryable<T> query;

    public Query(params T[] items)
    {
        query = items.AsQueryable();
    }

    public Expression Expression
    {
        get { return query.Expression; }
    }

    public Type ElementType
    {
        get { return query.ElementType; }
    }

    public IQueryProvider Provider
    {
        get { return query.Provider; }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return query.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

 

Hope, this helps!

#

JetBrains Seeder Program

Friday, October 24, 2008 12:44:56 PM (Mountain Standard Time, UTC-07:00)

Today I received an email about the JetBrains Seeder Program, and thought that I would try to sign up for an account to find out more.

Can you help me understand, what JetBrains is trying to tell me?

jetbrains_subliminal_messages 

horning

#

Too Quick

Wednesday, May 21, 2008 3:39:52 PM (Mountain Standard Time, UTC-07:00)

Thank you Mr. Aaron, today we just grabbed the latest beta version of Rhino.Mocks and out test times significantly dropped....

Our times before the update were 450ish seconds to run all the unit tests and create the report:

before

Our times after are 100ish seconds:

after

#

Loading From an SVN Dump File

Monday, April 14, 2008 12:18:56 PM (Mountain Standard Time, UTC-07:00)

Loading a subversion repository from a dump file isn't as hard as I thought it would be. It's as easy as:

> svnadmin path.to.repository.directory < repository.dump.file

You just have to make sure that:

  • you've got subversion installed or that you can hit "svnadmin.exe" directly.
  • the "path.to.repository.directory" has a repository created in it.

All that this seems to be doing is replaying every commit that ever happened on the original repository. This is pretty sweet, especially for a class room set up when the student afterwards want to go through different revisions to compare changes or things learned in class.

svn.dump

#

Keepin' it real with SVN

Friday, February 01, 2008 4:05:09 PM (Mountain Standard Time, UTC-07:00)

Earlier this month I read...

Pragmatic Version Control: Using Subversion (The Pragmatic Starter Kit Series)(2nd Edition)
by Mike Mason

Read more about this title...

If you're an svn or tortoise junkie I recommend that you check out this book. Although most of the information provided in this book can probably be found in the SVN documentation, I much preferred reading this top to bottom. This book walks you through several different project scenarios and shows you how to effectively use svn as your source control system.

The appendices also offers a lot of very helpful information on setup and third party tools. Some must have tools for svn are:

  • TortoiseSVN
  • VisualSVN
  • SVN.exe

I love that visual svn takes care of things like moving files, add and deleting it really simplifies the check in process. Tortoise is a great windows explorer shell that provides a wicked abstraction over the svn shell.

Since reading the book I've found that I'm using tortoise less for checkin's and updates. Here's a couple of simple commands to get you started:

Update:

svnUp

Commit (check in):

svnci

#

NAnt: Start Using the C# 3.0 Compiler Without Visual Studio 2008

Wednesday, December 05, 2007 9:25:46 PM (Mountain Standard Time, UTC-07:00)

One of the benefits about building with NAnt is being able to flip the switch and start targeting a different compiler, without having to switch to the latest version of Visual Studio. Although, you wont get the intellisense provided by studio for new features.

So today we flipped the switch on a project at work, from targeting the C# 2.0 compiler to the C# 3.0 compiler. We haven't started leveraging any of the new functionality available in the new compiler but at least we know we can start.

So to flip the switch you'll need to update your "nant.exe.config" file to include the .NET Framework version 3.5. Remember with this release we got a new version of the .NET Framework assemblies, a new C# 3.0 compiler but we're still running it all in the 2.0 version of the CLR.

The new xml element to add to your "Nant.exe.config" file looks something like this:

                <framework
                    name="net-3.5"
                    family="net"
                    version="3.5"
                    description="Microsoft .NET Framework 3.5"
                    runtimeengine=""
                    sdkdirectory="${path::combine(sdkInstallRoot, 'bin')}"
                    frameworkdirectory="${path::combine(installRoot, 'v3.5')}"
                    frameworkassemblydirectory="${path::combine(installRoot, 'v2.0.50727')}"
                    clrversion="2.0.50727">
                    <task-assemblies>
                        <!-- include .NET specific assemblies -->
                        <include name="tasks/net/*.dll" />
                        <!-- include .NET 2.0 specific assemblies -->
                        <include name="tasks/net/2.0/**/*.dll" />
                        <!-- include Microsoft.NET specific task assembly -->
                        <include name="NAnt.MSNetTasks.dll" />
                        <!-- include Microsoft.NET specific test assembly -->
                        <include name="NAnt.MSNet.Tests.dll" />
                    </task-assemblies>
                    <project>
                        <readregistry
                            property="installRoot"
                            key="SOFTWARE\Microsoft\.NETFramework\InstallRoot"
                            hive="LocalMachine" />
                        <readregistry
                            property="sdkInstallRoot"
                            key="SOFTWARE\Microsoft\.NETFramework\sdkInstallRootv2.0"
                            hive="LocalMachine"
                            failonerror="false" />
                    </project>
                    <tasks>
                        <task name="csc">
                            <attribute name="exename">csc</attribute>
                            <attribute name="supportsnowarnlist">true</attribute>
                            <attribute name="supportswarnaserrorlist">true</attribute>
                            <attribute name="supportskeycontainer">true</attribute>
                            <attribute name="supportskeyfile">true</attribute>
                            <attribute name="supportsplatform">true</attribute>
                            <attribute name="supportslangversion">true</attribute>
                        </task>
                        <task name="vbc">
                            <attribute name="exename">vbc</attribute>
                            <attribute name="supportsdocgeneration">true</attribute>
                            <attribute name="supportsnostdlib">true</attribute>
                            <attribute name="supportsnowarnlist">true</attribute>
                            <attribute name="supportskeycontainer">true</attribute>
                            <attribute name="supportskeyfile">true</attribute>
                            <attribute name="supportsplatform">true</attribute>
                            <attribute name="supportswarnaserrorlist">true</attribute>
                        </task>
                        <task name="jsc">
                            <attribute name="exename">jsc</attribute>
                            <attribute name="supportsplatform">true</attribute>
                        </task>
                        <task name="vjc">
                            <attribute name="exename">vjc</attribute>
                            <attribute name="supportsnowarnlist">true</attribute>
                            <attribute name="supportskeycontainer">true</attribute>
                            <attribute name="supportskeyfile">true</attribute>
                        </task>
                        <task name="resgen">
                            <attribute name="exename">resgen</attribute>
                            <attribute name="supportsassemblyreferences">true</attribute>
                            <attribute name="supportsexternalfilereferences">true</attribute>
                        </task>
                        <task name="al">
                            <attribute name="exename">al</attribute>
                        </task>
                        <task name="delay-sign">
                            <attribute name="exename">sn</attribute>
                        </task>
                        <task name="license">
                            <attribute name="exename">lc</attribute>
                            <attribute name="supportsassemblyreferences">true</attribute>
                        </task>
                        <task name="ilasm">
                            <attribute name="exename">ilasm</attribute>
                        </task>
                        <task name="ildasm">
                            <attribute name="exename">ildasm</attribute>
                        </task>
                    </tasks>
                </framework>                 

To flip the switch you can either override the nant setting in your build file ...

<property name="nant.settings.currentframework" value="net-3.5" />

or you can change the default target framework in the "nant.exe.config" file.

<platform name="win32" default="net-3.5">

I can't steal the credit for figuring this out, I spent about an hour adding the new framework version to the Nant.exe.config file but the thing I missed was that there is no new version of the CLR. So Thank you Mr. Palermo!

Source Nant.exe.config

#

NUnit vs. MbUnit

Friday, October 26, 2007 10:30:21 PM (Mountain Standard Time, UTC-07:00)

Can't we all just get a long? A couple weeks ago I was asked why I preferred using MbUnit over NUnit... and i realized the question kind of stumped me. Did I choose MbUnit or did I just start using because everyone else is?

So why do I like MbUnit? I think the first reason is this... I'm glad the Unit Runner support for MbUnit is limited. I know there's a plugin some where that allowed you to debug your MbUnit unit tests in version 2.* of JetBrains Unit Test Runner. But since 3.0 came out it's been difficult to do, and I'm kind of glad!

My dependence on the debugger is becoming less and less. Admittedly, in the current project I seem to be running the debugger more because of my on going battle with Crystal Reports, but that's another story. I've found that since I started using MbUnit, I've spent less time using the debugger and more time developing new functionality. At first there was definitely a stunt in development when learning to work without the debugger, but I'm getting better on not relying on it, and i feel good about it.

I like the MbUnit reports... you can take your pick of text, html, xml or dox. The text report is great for getting quick feedback to see if your tests have passed or if you need to walk through the stack trace to find out where tests have blown up. (Just give me the line #) I haven't completed figured out what the "dox" report type is supposed to be used for or if it has any relationship to "doxygen", a great documentation generation tool I used to use during my days of C development (Thank you Mr. Mark!). But I like the report that it generates. It writes out the names of the tests so that they read almost like plain English. Here's an example:

- merchandise,should_ have_ 1 0_ percent_ sales_ tax

In the above example, "merchandise" was the name of the class and "should_ have_ 1 0_ percent_ sales_ tax" is the name of the test. Pretty clear and easy to read, it definitely describes the intent of each test nicely!

Combining the "/sr" (show report) switch with a command line build and a readable report makes for some quick development and quick feedback. It's awesome when you can bang out code, run a build quickly and get quick descriptive response to help you.

Next up... I'm liking the "RowTest" attribute. When it comes to triangulating tests against your subject under test, this attribute can come back handy. Take this for example:

        [RowTest]
        [Row( 12.49 )]
        [Row( 0.85 )]
        [Row( 9.75 )]
        public void Should_Calculate_0_Percent_Tax_On_Item( double forPrice ) {
            AssertAreEqual( 0, CalculateTax( forPrice, ZeroPercent ) );
        }

Instead of having to write out 3 different tests, or jamming the 3 different assertions into a single test, I can make use of the "RowTest" attribute to ensure my subject is behaving as I expect it to. Pretty nice!

Next up, the "Rollback" attribute... when you decorate your test method with this little attribute it rolls back any changes made to a database. This comes in quite handy for an integration test against a database. Now you can also make use of the TransactionScope type as while and roll out your own base class for data access tests, but I like that this is baked right in to the unit testing framework. Although, I admit I have not spent much time using this feature yet.

One of the cool new features in the latest version of NUnit is a new "That" method, which allows you write more readable assertions. For example:

            Assert.That(new Money(expected), Is.EqualTo(actual));

Right now it seems that integrating NUnit with other tools like CruiseControl is much easier and supported more, since it is the de-facto standard for unit test frameworks, but spending time trying to figure out how to get MbUnit to get along with others tools help you to get a better understanding of how each tool works and how they work with others.

Either way, I can't say I'm biased to either MbUnit or NUnit. I think they're both great unit testing frameworks and I'm glad that they're around and free to use.

#

Good Quality Tools

Thursday, August 23, 2007 6:29:00 AM (Mountain Standard Time, UTC-07:00)

"Every craftsman starts his or her journey with a basic set of good-quality tools. A woodworker might need rules, gauges, a couple of saws, some good planes, fine chisels, drills and braces, mallets, and clamps. These tools will be lovingly chosen, will be built to last, will perform specific jobs with little overlap with other tools, and, perhaps most importantly, will feel right in the budding woodworker's hands."

I read the above paragraph from the pragmatic programmer, and thought it made a lot of sense. My appreciation for tools continues to grow, and grow. And as I learn to use different tools, I find different sorts of productivity gains.

Some of the tools I use:

 

The Pragmatic Programmer: From Journeyman to Master
by Andrew Hunt, David Thomas

Read more about this title...

#

NAnt: Running Your Unit Tests

Friday, June 08, 2007 8:12:54 AM (Mountain Standard Time, UTC-07:00)

There's a lot of cool things that you can do with nAnt, like running your tests against NUnit or another unit testing framework. Let's pretend we already have a target called "compile" that will compile our application into an assembly into the build folder. See...

We can create a new target that will compile our test project(s) into a single test assembly and save it to our build folder, where we saved our application assembly. The following target will recurse through a subdirectory called "test" and compile all files with a .cs extension into our test assembly.

    <target name="test.compile" depends="compile">
        <csc target="library" output="build\${project::get-name()}.Test.dll" debug="${debug}">
            <sources>
                <include name="src\test\**\*.cs" />
                <exclude name="src\test\**\AssemblyInfo.cs" />
            </sources>
            
            <references>
                <include name="build\${project::get-name()}.dll" />
                <include name="tools\nunit\bin\nunit.framework.dll" />
                <include name="tools\rhinomocks\Rhino.Mocks.dll" />
            </references>
        </csc>
    </target>    

The references element allows us to include other assemblies that our test assembly depends on. In the above case I'm using NUnit, and RhinoMocks. Our test assembly also depends on the application assembly, after all that is what our tests are supposed to be testing.

So far we have compiled our application assembly and test assembly, and saved them to the same directory called build. Now lets create a target that will run our unit tests using the nunit-console.exe.

    <target name="test" depends="test.compile">

        <copy todir="build" flatten="true">
            <fileset basedir="tools">
                <include name="**\Rhino.Mocks.dll" />
            </fileset>
        </copy>

        <copy todir="build" flatten="true">
            <fileset basedir="tools\nunit\bin">
                <include name="*.dll" />
            </fileset>
        </copy>
        
        <exec basedir="tools\nunit\bin" 
            useruntimeengine="true" 
            workingdir="build" 
            program="nunit-console.exe" 
            commandline="${project::get-name()}.Test.dll /xml=${project::get-name()}.Test-Result.xml" />        
        
    </target>

The above target will copy over the Rhino.Mocks.dll, and NUnit dlls into our build folder. Then execute "nunit-console.exe" from the command line and pass it in the path to our test assembly, and will tell it what to name the xml file that nunit will spit out with the test results.

As you can see the test results are also shown to the console window. As you can see, I have run 8 tests, with 3 failures. (Looks like I've made a breaking change!)

#

nAnt: Compiling Your Applications

Friday, June 08, 2007 7:11:51 AM (Mountain Standard Time, UTC-07:00)

I've been spending some time trying to learn how to create builds using nAnt. You can use a special nAnt element to compile your .cs source files against the C# compiler.

    <target name="compile">
        <csc target="library" output="build\${project::get-name()}.dll" debug="${debug}">
            <sources>
                <include name="src\app\**\*.cs" />
                <exclude name="src\app\**\AssemblyInfo.cs" />
            </sources>                        
        </csc>
    </target>

The above target will compile all .cs files into a single assembly called <PROJECT_NAME>.dll. ( You specify your project name in the name attribute of the project element.)

<project name="LogMyTime">

The compile target will recurse through all the files in a subdirectory called "src" and compile all the files with a .cs extension into the final assembly, excluding the AssemblyInfo.cs file (If you have multiple projects, each one will most likely have a different "AssemblyInfo.cs" file containing assembly info for that project.). The target will try to save the assembly to a folder called "build".

Before compiling you should ensure that the build folder exists. To do this you could create another nAnt target that creates the build directory. Here is an example.

    <target name="init">
        <mkdir dir="build" />
    </target>

We could now create a dependency between the compile target and the init target so that, the init target always runs before attempting to compile by adding the "depends" attribute.

    <target name="compile" depends="init"> ... </target>

Now we can run our nAnt task from the commandline:

The output will tell us what nAnt targets ran and if there were any compilation warnings or errors:

Related Resources:

#

Resharper Test Template

Tuesday, May 08, 2007 10:52:34 AM (Mountain Standard Time, UTC-07:00)

My Resharper Test template....

/*
* Created by: $AUTHOR$
* Created: $DATE$
*/

using NUnit.Framework;
using Rhino.Mocks;

namespace $NAMESPACE$
{
    [TestFixture]
    public class $CLASS$
    {
        private MockRepository _mock;

        [SetUp]
        public void SetUp( )
        {
            _mock = new MockRepository( );
        }

        [TearDown]
        public void TearDown( )
        {
            _mock.VerifyAll( );
        }
        
        [Test]
        public void _Should()
        {
            
        }
    }$END$
}


#

What's Open about Open ID?

Saturday, May 05, 2007 8:47:00 AM (Mountain Standard Time, UTC-07:00)

Open ID is definitely an interesting concept. The basic premise is that you maintain a single Identity that you can use to verify who you are to different sites that support Open ID.

You identify yourself with a unique URI. To log in to a Open ID site you enter your Uri. The website should then re-direct you to your Open ID provider, where you provide your log in credentials to verify that it's actually you trying to claim to use this Open ID.

Here's a good screen cast on the topic Open ID screen cast.

There are several libraries written in different languages available to developers for use on their Open ID affiliate sites. Found here...

The one I tinkered with was Nerdbanks Open ID web control, which references JanRains Open ID library. The control was very simple to use and start using... the full source is available and released under a LGPL license.

I ran the Nerdbanks assembly against FxCop and found several things that could be improved on. Personally, I would want to fix a lot of these issues before using this myself, but it's nice to have a starting point to begin working with. The Nerdbanks assembly also contains a lot of extra code all bundled into a single assembly, again my personal preference would be to probably break out the "tools" from the "web controls" into separate assembly's.

Open ID seems like a pretty cool concept and it's nice to have libraries available to start with... anyways this just skims the surface of what Open ID is... but hopefully it's a good primer!

#