Monday, 19 January 2009

NAnt HowTo #4: How To Create And Use Custom NAnt Task

new class named OK, let's start. What is a NAnt task? Formally, it's a class that extends NAnt.Core.Task class from NAnt.Core.dll assembly located in your NAnt installation folder. As any class it will be placed in an assembly, and this assembly is the way you interact with NAnt. So, let's get it! The following steps describe how to create a simple HelloTask task.

1. Create new project

Create an empty class library project that will compile to .dll file.

2. Create new class derived from NAnt.Core.Task

Create new class named HelloTask and derive from NAnt.Core.Task:

public class HelloTask : Task
{

}

3. Override ExecuteTask method

As NAnt.Core.Task class is abstract VS will suggest you to override the ExecuteTask method - do it. Put the following implementation into it (assume that Person property is already defined ;)):

protected override void ExecuteTask()
{
Project.Log(Level.Info, String.Format("Hello, {0}!", Person));
}
Have a look at Project.Log() call - it will output some message with needed level.

4. Define task name

To define task name, you should apply NAnt.Core.Attributes.TaskNameAttribute attribute to your class:
[TaskName("hello")]
public class HelloTask : Task


5. Define task attributes

To define task attributes, you should define property of appropriate type and mark it with the NAnt.Core.Attributes.TaskAttributeAttribute attribute:

[TaskAttribute("person", Required = true)]
public String Person
{
get;
set;
}
Attribute constructor allows you to specify several options, like whether this attribute is required.

6. Load assembly with you class in NAnt

To use your new task you should place your assembly somewhere NAnt has access to. Two most appropriate options are in NAnt installation folder and in build execution folder. Though I prefer the last one, the first one may be useful if you use your custom tasks regularly though not changing them often.

As soon as assembly is properly placed, you should load tasks from it in your build file. Use loadtasks attribute to load it:

<loadtasks assembly="Leaves.NAnt.Custom.dll" />

7. Use your task

Just use it in the most obvious way:

<hello person="world" />
The output will be the following:

all:

[loadtasks] Scanning assembly "Leaves.NAnt.Custom" for extensions.
Hello, world!

It works!

8. Summarize

This is what we've got in our task:

using System;
using NAnt.Core;
using NAnt.Core.Attributes;

namespace Leaves.NAnt.Custom
{
[
TaskName("hello")]
public class HelloTask : Task
{
protected override void ExecuteTask()
{
Project.Log(Level.Info, String.Format("Hello, {0}!", Person));
}

[
TaskAttribute("person", Required = true)]
public String Person
{
get;
set;
}
}
}
And build file:

<?xml version="1.0"?>

<project
name="NAnt HowTo 4" default="all" xmlns="http://nant.sf.net/release/0.85-rc2/nant.xsd">
<target
name="all">
<loadtasks
assembly="Leaves.NAnt.Custom.dll" />
<hello
person="world" />
</target>
</project>
kick it on DotNetKicks.com

Friday, 16 January 2009

ASP.NET MVC impressions

It's awesome! As a fan of Ruby on Rails I can tell you: ASP.NET MVC is f*cking awesome!

Monday, 5 January 2009

NAnt HowTo #3: How To Run NUnit Tests From Your Build File

This post continues my NAnt HowTo series. In previous posts I've covered topics of compiling your project and splitting your build file. Today I want to tell you how to run NAnt unit tests from your NAnt build script.

First of all you may notice that main NAnt distribution has TWO NUnit tasks: nunit and nunit2. First one is designed to work with NUnit 1.0 and second one with NUnit 2.2. This simple moment can warn you that something is not as good as it seems here. And you will be right :) Me personally had a problem running NUnit of some lately version using this nunit2 task. After some googling I've found a solution in Scott Hanselman's blog where he spoke with his friend on same topic. As a result of this conversation Scott recommended using nunit-console.exe instead. I've tried it - it works :) Now changing NUnit version will not break as nunit-console command-line specification is not something to change when switching from 2.x to 2.(x+1).

How can we do this? Simple enough:

<target name="tests.unit.run" description="Run unit tests">
<exec
program="D:/bin/nunit/nunit-console.exe"
workingdir="D:/projects/MyProject/Integration"
commandline="MyProject.Tests.dll /xml:TestResults.xml /nologo"/>
</target>

So, step by step.
  1. We use <exec> task to run an executable. This also means that if our nunit-console.exe executable fails (read: some test fails) it will break our build. Of course, you may use failonerror="false" attribute on your <exec> task but I do not recommend doing so - why would anyone ever need tests if their failure will be ignored?!

  2. We specify path to our nunit-console.exe executable via the program attribute.

  3. We specify working directory (usually it's integration dir where you have all needed assemblies) via the workingdir attribute.

  4. We pass command line parameters via the commandline attribute.
Actually this could be the end of the post but I want to say some words on command line arguments of nunit-console.
  1. First non-keyed (with no preceding /im-a-key: keys) several arguments specify assemblies to run tests from.

  2. Argument after /xml: key is a bit more interesting. It indicates the XML file where test results will be stored. You may not need it at the moment but you'll definitely need this file when you'll be integrating your NAnt build script with CruiseControl.NET or any other integration software.

  3. /nologo key suppresses NUnit copyright information display on each run
You can read more about these command line arguments on the official NUnit website.

That's the end :) Next time I will probably speak on writing NAnt custom tasks. Stay online.


kick it on DotNetKicks.com

Tuesday, 30 December 2008

NAnt HowTo #2: How To Split Your Build File

Let's assume you have a large build file with many-many targets, properties, etc. After some time it becomes pretty hard to support and extend it. What can we do? As for me, the best option here is to split your build file to several pieces. Below goes an example on how you can do this.

My default.build file:

<?xml version="1.0"?>

<project
name="NAnt HowTo 2" default="all" xmlns="http://nant.sf.net/release/0.85-rc2/nant.xsd">
<!--
Includes -->
<include
buildfile="build.include" />
<include
buildfile="test.include" />

<target
name="all" description="Default target, calls all deployment tasks.">
<call
target="rebuild" />
<call
target="test" />
</target>

<target
name="rebuild" descripton="Rebuilds all projects." >
<call
target="clean" />
<call
target="build" />
</target>

<target
name="test" description="Runs all tests.">
<call
target="tests.unit.run" />
<call
target="tests.integration.run" />
</target>
</project>
build.include file:
<project xmlns="http://nant.sf.net/release/0.85-rc2/nant.xsd">
<target
name="clean">
<echo
message="Rebuild: clean" />
</target>

<target
name="build">
<echo
message="Rebuild: build" />
</target>
</project>
test.include file:

<project
xmlns="http://nant.sf.net/release/0.85-rc2/nant.xsd">
 <target name="tests.unit.run">
<echo
message="Test: unit tests" />
</target>

<target
name="tests.integration.run">
<echo
message="Test: integration tests" />
</target>
</project>
As you can see, actual inclusion takes place when you use <include> element and specify it's buildfile attribute to point to some .include file.

.include
files should contain root <project xmlns="http://nant.sf.net/release/0.85-rc2/nant.xsd"> element with necessary xmlns attribute. Without this attribute NAnt won't be able to parse this file and use it's targets.

Included files become a piece of main build file and share all properties with it. This means that properties from included file are visible in main file and vise-versa. I usually place commonly used properties to separate .include files, for example, I have projects.include file with all properties that point to project names and folders.

kick it on DotNetKicks.com

Monday, 29 December 2008

NAnt HowTo #1: How To Compile A Project?

NAnt provides a CSC task that will allow you to compile your C# project (sorry, VB guys, no info for you :)). It may be used this way:

<!--  2. Building shared data project -->
<csc
target="library" debug="false" warnaserror="true"
output="D:/projects/MyProject/Integration/MyProject.dll">
<sources
basedir="D:/projects/MyProject/Source">
<include
name="**/*.cs" />
</sources>

<references>
<include
name="D:/projects/MyProject/External/NHibernate.dll" />
</references>

<resources>
<include
name="D:/projects/MyProject/Source/NHib/*.hbm.xml"/>
</resources>

<nowarn>
<warning
number="1702" />
</nowarn>
</csc>

So let's have a look in details at each part of this task.

Attributes

One by one:
  1. target="library" - indicates that we want to have a .dll as result of our compilation. Possible values are exe, winexe, library or module.

  2. debug="false" - indicates that no debug symbols will be included into our assembly. Possible values are Enable, Full, None and PdbOnly. Although you can use aliases (like I did): true stands for Enable and false stands for None.

  3. warnaserror="true" - has same effect like checking 'Treat warnings as errors - All' option in Visual Studio. All warnings will be treated as errors.

  4. output="D:/projects/MyProject/Integration/MyProject.dll" - output of compilation. Make sure your output target extension is adequate to your compilation target (although I haven't tried compiling target library to output .exe :-P)

Sources

This nested element allows you to select files that should be compiled. It's only attribute I use here is:

basedir
="D:/projects/MyProject/Source" - base directory for source files. Usually this is root folder for some project.

The <include> element allows you to specify elements that should be compiled. It's attribute, name, deserves some attention. First, it uses wildcards to pick necessary items. Second, it uses double asterisk to recursively pick all files from all folders. Have a look:
  1. name="*.cs" will pick .cs files only in current folder

  2. name="**/*.cs" will pick .cs files from current folder and from all subfolders, their subfolders, etc.

References

This nested element allows you to specify assemblies that should be references. Syntax also supports wildcards so you can easily specify *.dll to reference all .dll files in some folder.

Resources

This element allows you to deal with resources embedded into your assembly. In this particular case I use this element to embed NHibernate .hbm mappings.

Nowarn

This section allows you to ignore some specific warnings via nested <warning /> element. Use it's number="1702" attribute to specify some specific warning you want to ignore.

Conclusion


That's a short explanation on CSC target, more information can be found here. Hope this post will be helpful to anyone other than myself :D

kick it on DotNetKicks.com

NAnt HowTos

Lately I had to dive into NAnt and I'm going to post here several posts on some simple NAnt questions.

Wednesday, 24 December 2008

Things to complete

Here goes the list of things I want to complete in the nearest future:

  1. Master ASP.NET MVC
  2. Become senior software engineer at next internal attestation
  3. Dive deep into .NET attributes programming
  4. Master JQuery

How to become a better specialist?

Work with those who are smarter and more professional than you. This is a modified quote from some chess book and it applicable to literally any profession.

Applying this statement to my profession (I'm a .NET developer if anyone could have forgotten that ;)), you can become better much faster if you work with someone more qualified than you. I've been working with two nice developers for almost six months and now I can see my level is growing way too faster than if I would increase my skills myself. I'm actually approaching their level, day after day.

That's why in one of my dreams I imagine myself working together with such persons like Martin Fowler or Scott Guthrie. That could be a real experience boost!

Sharp Architecture

Do you want to become a better developer? Try this project. Yes, just download it and read the code. Comments are marvelous, design is outstanding. I love it. I've picked several tricks and two absolutely new libraries/approaches for myself.

Although it's designed to use with ASP.NET MVC beta you'll easily grab NHibernate code as it was designed not to depend on view framework.

Just try it

Tuesday, 23 December 2008

ASP.NET Form Autocompletion

Our customer was really interested in enabling autocompletion feature for registration page. I've searched a lot, I've found a huge number of pages describing how to turn it off and (at last!) only one page about how turning it on.

All magic is hidden in AutoCompleteType property of asp:TextBox. You can read about it in details here but in a nutshell this field allows you to specify what information should be autosuggested for this particular TextBox.

Enjoy!

Thursday, 18 December 2008

Internet Explorer 8 Release Candidate 1

According to a friend of my friend, IE8 RC1 has been accessible for Microsoft partners a month ago :( And seems like:

  1. No standards
  2. Slow JavaScript
  3. Security problems
  4. 17 in ACID3

I hope it was very old build. VERY old.

=(

Leaves Bugs System

Are you satisfied with Bugzilla? My answer is NO. I know it's has many nice features but I'm absolutely disappointed with it's UI. How could anyone create such a crap?! It's unusable and usually I spend up to 10 minutes to search for defects assigned to me for some specific iteration.

I saw nice solutions, but all of them had some drawbacks that made me drop using them off. One of these drawbacks was the price =). Anyway, me decision is to create something of my own. And as it is my graduation project, I have to complete it.

I'll develop it on top of the ASP.NET MVC Beta, NHibernate as my ORM (I'm disappointed with the EF at the moment) and JQuery as a great accelerator for UI. I'll try to follow best practices, including TDD and CI. Hope this will be a nice project ;)

Yesterday I've created some basic folder structure and started writing NAnt script for my new solution. I've also set up SVN server and added my projects to subversion. If everything goes fine I'll manage to set up CI at the earliest stage possible - and that's a good point. And later on - no step without TDD :) It's just too good to work without it.

New info coming soon!

Web Developer Wish List

Nice article on what you may ask for Christmas :) My choice is office chair - together with other 55 people who voted the same.

View wish list

IE 8 coming soon!

Or at least it's release candidate :) That would be a great Christmas present!

Read here

Wednesday, 17 December 2008

New Live Writer

Could you image what could be better for blogging than Microsoft Live Writer? Earlier I could not, but now I see how I was mistaken :) And the answer is...

Live Writer 2009!!!!

Actually, this is just a release candidate, but the list of improvements looks fine:

  1. Support for YouTube
  2. Support for Flickr
  3. Spellchecking for some more non-English languages
  4. Support for Digg
  5. Support for Twitter

Waiting for release =)

Tuesday, 16 December 2008

Chrome vs IE 8 Beta

This article shows that IE8 Beta loses the battle to Google Chrome. I think that it's mostly because of BETA in IE 8 name and Google Chrome has recently dropped same suffix.

Hope IE8 wins =)

Ruby-based barmen DSL

It's wonderful!

Just have a look at this sexy code:

drink 'Screwdriver' do
serve_in 'Highball Glass'
ingredients do
2.ounces :vodka
5.ounces :orange_juice
end
end


 



I like it! And you? ;)

Some interesting links

  1. It Oxite as good as it's claimed to be? According to this well-proved article, it's not and, moreover, it will hurt ASP.NET community.
  2. How your team goes agile? Our team tries to be agile but it's not a one-second process and it takes some time to adapt from previous techniques to agile methodology. That's why I really like articles about other agile teams as I can pick some interesting thoughts on agile from them. From this article I've actually taken four thoughts (2 absolutely new, 2 I knew earlier fundamentally explained)
  3. Some new Ruby book, available free in e-book format.