About Me

Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

Interested in trading in your NAnt builds (a teaser)?
BDD Extension Methods
Small bit of code cleanup
Updates to improve readability of tests using mocks
Destinations For Nothin But .Net For 2009
Last Chance To Take A Nothin But .Net Course in 2008!!!

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 431
This Year: 1
This Month: 1
This Week: 1
Comments: 1158

 Thursday, October 30, 2008
Thursday, October 30, 2008 4:52:00 PM (Mountain Standard Time, UTC-07:00) ( Continuous Integration )

I thought I would demo how I have been using powershell to do my automated build (currently with the help of my own modified version of PSake). The following script leverages both powershell and PSake and with the power of a full blown scripting language I have consolidated disparate build files into a single PSake script with a lot less verbosity:

includes .\build_utilities.ps1 properties { $project_name = "nothinbutdotnetstore" } properties{#directories $framework_dir = "$env:systemroot\microsoft.net\framework\v2.0.50727" $base_dir = [System.IO.Directory]::GetParent("$pwd") $build_dir = "$base_dir\build" $build_tools_dir = "$build_dir\tools" $build_artifacts_dir = "$build_dir\artifacts" $config_dir = "$build_dir\config" $third_party_dir = "$base_dir\thirdparty" $third_party_tools_dir = "$third_party_dir\tools" $third_party_lib_dir = "$third_party_dir\lib" $product_dir = "$base_dir\product" $docs_dir = "$base_dir\docs" $sql_dir = "$build_dir\sql" $sql_ddl_dir = "$sql_dir\ddl" $sql_data_dir = "$sql_dir\data" $thirdparty_lib_dir = "$third_party_dir\lib" $docs_dir = "$base_dir\docs" $config_dir = "$build_dir\config" $product_dir = "$base_dir\product" $product_app_dir = "$product_dir\app" $product_test_dir = "$product_dir\test" $web_ui_dir = "$product_app_dir\nothinbutdotnetstore.web.ui" $coverage_dir = "$build_artifacts_dir\coverage" $compile_dir = $build_artifacts_dir $deploy_dir = "$build_dir\deploy" $deploy_web_dir = "$deploy_dir\web" $deploy_web_app_dir = "$deploy_web_dir\app" $deploy_web_src_dir = "$deploy_web_dir\source" $deploy_web_src_dir_bin = "$deploy_web_src_dir\bin" $deploy_web_src_dir_images = "$deploy_web_src_dir\images" } properties{#filesets $all_template_files = get_file_names(get-childitem -path $build_dir -recurse -filter "*.template") $third_party_libraries = get_file_names(get-childitem -path $third_party_lib_dir -recurse -filter *.dll) $third_party_tools = get_file_names(get-childitem -path $third_party_tools_dir -recurse -filter *.dll) $all_third_party_dependencies = $third_party_tools + $third_party_libraries $all_sql_ddl_files = get_file_names(get-childitem -path $sql_ddl_dir -recurse -filter *.sql) $all_sql_data_files = get_file_names(get-childitem -path $sql_data_dir -recurse -filter *.sql) $all_web_images = get_file_names(get-childitem -path $web_ui_dir -recurse -include @("*.jpg","*.gif")) $all_web_code_files = get_file_names(get-childitem -path $web_ui_dir -recurse -include @("*.cs")) $all_web_markup_files = get_file_names(get-childitem -path $web_ui_dir -recurse -include @("*.aspx","*.css","*.master","*.js",
"*.ascx","*.asax")) } properties{ #files $studio_app_config = "$product_app_dir\NothinButDotNetStore\bin\debug\NothinButDotNetStore.dll.config" $log4net_config = "$config_dir\log4net.config.xml" $now = [System.DateTime]::Now $project_lib = "$project_name.dll" $db_timestamp = "$sql_dir\db.timestamp" $nant_properties_file = "$build_dir\local_properties.xml" } properties{#logging $log_dir = "$build_dir\logs" $log_file_name = "${log_dir}\log.txt" $log_level = "DEBUG" } properties{#asp app mapping settings $executable="$framework_dir\aspnet_isapi.dll" $extension = ".store" $verbs = "GET,POST" } properties{#transient folders for build process $transient_folders = $build_artifacts_dir, $deploy_web_app_dir, $deploy_web_src_dir, $deploy_web_src_dir_bin, $deploy_web_src_dir_images } properties{#machine dependent external properties . $build_dir\local_properties.ps1 $app_config = "$config_dir\$($local_settings.app_config_template.replace(`".template`",[System.String]::empty))"; $run_url = "http://$env:computername/$($local_settings.virtual_directory_name)/$($local_settings.startup_page)" } task default -depends init task build_db -depends init{ if (files_have_changed $all_sql_ddl_files $db_timestamp -eq $true) { process_sql_files $all_sql_ddl_files $local_settings.osql_exe $local_settings.osql_connectionstring } else { "DB is upto date" } touch $db_timestamp } task load_data { process_sql_files $all_sql_data_files $local_settings.osql_exe $local_settings.osql_connectionstring } task init -depends clean{ $transient_folders | foreach-object{ make_folder $_ } expand_all_template_files $all_template_files $local_settings } task clean{ $transient_folders | foreach-object{ drop_folder $_} } task compile -depends init{ $nant = "$build_tools_dir\nant\bin\nant.exe" $build_file = "$build_dir\project_simple.build" $command_line = "-buildfile:$build_file -D:project_lib=$build_artifacts_dir\$project_name.dll -D:project_test_lib=$build_artifacts_dir\$project_name.test.dll compile" exec $nant $command_line } task make_iis_dir{ make_iis_dir "nothinbutdotnetstore" "$deploy_web_app_dir" add_iis_mapping "nothinbutdotnetstore" $false $extension $verbs $executable } task test -depends compile{ $all_third_party_dependencies | foreach-object {copy-item -path $_ -destination $build_artifacts_dir} copy-item -path $log4net_config -destination $build_artifacts_dir copy-item -path $app_config -destination "$build_artifacts_dir\$project_name.test.dll.config" $xunit = "$third_party_tools_dir\mbunit\bin\MbUnit.Cons.exe" $command_line = "$build_artifacts_dir\$project_name.test.dll $($local_settings.xunit_console_args)" exec $xunit $command_line } task deploy -depends compile,make_iis_dir{ $third_party_libraries | foreach-object {copy-item -path $_ -destination $deploy_web_src_dir_bin} copy-item "$build_artifacts_dir\$project_lib" $deploy_web_src_dir_bin copy-item $log4net_config $deploy_web_src_dir copy-item "$app_config" "$deploy_web_src_dir\web.config" $all_web_images | foreach-object{copy-item -path $_ -destination $deploy_web_src_dir_images} $all_web_code_files | foreach-object{copy-item -path $_ -destination $deploy_web_src_dir} $all_web_markup_files | foreach-object{copy-item -path $_ -destination $deploy_web_src_dir } exec "$framework_dir\aspnet_compiler.exe" "-v /$($local_settings.virtual_directory_name) -u -p $deploy_web_src_dir $deploy_web_app_dir" } task run_web_app -depends deploy{ exec "$($local_settings.browser_exe)" "$run_url" }

The prep material for the course is going to be updated with powershell based build scripts also, so all new students of the Nothin But .Net course can enjoy getting a glimpse of build automation with powershell.

I am hoping to do some posts on this in the next couple of weeks.

Develop With Passion!!

Comments [6] | | # 
 Wednesday, October 29, 2008
Wednesday, October 29, 2008 4:00:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp )

In response to a comment from the  last post, here is the interface of the BDDExtensions that were driven out from the last NBDN course:

public static class BDDExtensions { public static void force_traversal<T>(this IEnumerable<T> items) public static void should_be_null(this object item) public static void should_contain<T>(this IEnumerable<T> items, T item) public static void should_be_greater_than<T>(this T item, T other) where T : IComparable<T> public static void should_not_be_equal_to<T>(this T item, T other) public static void should_be_equal_ignoring_case(this string item, string other) public static void should_only_contain<T>(this IEnumerable<T> items, params T[] items_to_find) public static void should_only_contain_in_order<T>(this IEnumerable<T> items, params T[] items_to_find) public static void should_be_true(this bool item) public static void should_be_false(this bool item) public static void should_be_equal_to<T>(this T actual, T expected) public static ExceptionType should_throw_an<ExceptionType>(this Action work_to_perform) public static void should_not_throw_any_exceptions(this Action work_to_perform) public static void should_be_an_instance_of<Type>(this object item) public static void should_not_be_null(this object item} }

This is the main base set of extensions. I usually have a whole family of application specific extensions that come into play for doing application specific assertions.

Develop with Passion!!

Comments [1] | | # 
Wednesday, October 29, 2008 2:36:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp )

Thanks to a suggestion from Albert Weinert I have added 2 new test attributes to the spec helpers layer of my codebase (this is the folder that contains all of the test related utilities).

For a long time I have been aliasing the TestAttribute and changing it to observation. Instead with a suggestion from Albert, I have now added 2 new attribute classes to the spec helpers layer (Albert sent me the code, I just renamed the TestPatternAttribute class):

[AttributeUsage(AttributeTargets.Method,AllowMultiple = false)] public class ObservationAttribute : TestPatternAttribute {}

[AttributeUsage(AttributeTargets.Class,AllowMultiple = false)] public class Observations : TestFixturePatternAttribute { public Observations(string description) : base(description) { } public Observations() { } public override IRun GetRun() { var run = new SequenceRun(); run.Runs.Add(new OptionalMethodRun(typeof(SetUpAttribute),false)); run.Runs.Add(new MethodRun(typeof(ObservationAttribute),true,true)); run.Runs.Add(new OptionalMethodRun(typeof(TearDownAttribute),false)); return run; } }

This is much cleaner than aliasing (as well as adhering to DRY). I chose to keep this in my codebase vs rolling it into MbUnit as it gives people the freedom to name the attributes the way they feel. Because all of my test fixtures inherit from a base fixture, this change only required changing the attribute on my base test fixture as well as a quick search/replace to eliminate the:

using Observation = MbUnit.Framework.TestAttribute;

Thanks Albert.

Develop With Passion

Comments [0] | | # 
 Tuesday, October 28, 2008
Tuesday, October 28, 2008 10:43:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp )

In my ongoing quest to simplify the use of mock objects and to make the test code that I write remove the need for testing specific nomenclature. I made a small update to the BDDExtensions that I use when working with Rhino Mocks. Here is the class in question:

public static class RhinoMocksExtensions { public static VoidMethodCallOccurance<T> was_told_to<T>(this
T mock, Action<T> item) { return new VoidMethodCallOccurance<T>(mock, item); } public static IMethodOptions<R> when_told_to<T, R>(this T mock
, Function<T, R> func) where T : class { return mock.Stub(func); } }

The above 2 extension methods are the only ones I need to use when working with my mock objects. As you can see, they are just non-testing-nomenclature specific wrappers around existing rhino mocks methods.The was_told_to extension method is a method that I use to verify that a void method call message was sent to a mock object. You can see that the method returns a VoidMethodCallOccurance class that looks like this:

public class VoidMethodCallOccurance<T> { public Action<T> action; private T mock; public VoidMethodCallOccurance(T mock, Action<T> action) { this.mock = mock; this.action = action; mock.AssertWasCalled(action); } public void times(int number_of_times_the_method_
should_have_been_called) { mock.AssertWasCalled(action, y => y.Repeat.Times(number_of
_times_the_method_should_have_been_called)); } public void only_once() { times(1); } public void twice() { times(2); } }

This class allows you to specify the number of times a method was called on mock object. Which allows you to do this:

[Observation] public void should_tell_the_log_4_net_initialization_command_
to_run() { initialization_command.was_told_to(x => x.run())
.only_once(); }

as opposed to this:

[Observation] public void should_tell_the_log_4_net_initialization_command_
to_run() { initialization_command.AssertWasCalled(x => x.run()
,y => y.Repeat.Times(1)); }
 
It is a small change, but one that, IMHO, adds a lot to the
readability of the test.
 
Develop With Passion!!
Comments [3] | | # 
 Friday, October 10, 2008
Friday, October 10, 2008 5:20:07 AM (Mountain Standard Time, UTC-07:00) ( Training )

This year has truly been a year where my family and I can say that Nothin But .Net officially went global (having ventured into other parts of Europe as well as the Dominican Republic). We are extremely thankful to God for the amazing opportunities He has opened up for us and the many amazing people that we have been able to meet along the way.

Not content to stop there, Lord willing, next year we are going to step out to take the course into other locations that have been making requests for the course. The plan for next year is to hit the following new countries:

  • Australia
  • Cambodia
  • India

As well as the countries that we have already been and love:

  • Canada
  • US
  • England
  • Germany
  • Dominican Republic

If you live in one of those countries and have suggestions about where demand for the course might be, please feel free to get in contact with me.

If your company is thinking that they would like to get some training done in the new year, we have also hosted several private iterations of the bootcamp. So feel free to contact me if that is something you might be interested in.

Why the drive to hit all these places? It might sound a little cheesy, but I have seen this course change lives (literally) and the emotions around that are something that are very difficult to express in words. I want to take this course to as many places as possible and prayerfully have as much of a positive impact on the lives and careers of many other developers.

Cambodia in particular is going to be exciting because I have been informed that they do not have access to any significant advanced training there, and the cost of the typical courses elsewhere is much too prohibitive. I am working with people there to ensure that the course can be bought to them with a cost that will work within their typical developer budget and allow as many people as possible to participate in what could be a great experience for them.

Hopefully I will see you in 2009!!

Develop With Passion!!

Comments [12] | | # 
 Wednesday, October 08, 2008
Wednesday, October 08, 2008 4:29:19 PM (Mountain Standard Time, UTC-07:00) ( Training )

It is almost November, and God has amazingly blessed the Nothin But .Net Developer Bootcamp. I am going to post in a little while about the amazing opportunities and encounters that have occurred this year as a result of the course.

In the meantime, this is a reminder to those who are thinking about registering to go ahead and register for either of the upcoming courses:

Nothin But .Net - In Las Vegas

Nothin But .Net - In Philadelphia

These two courses are the last courses that I will be running for the 2008 calendar year. As far as the 2009 schedule goes, I am not going to start "public" courses again until Q2 of 2009.

If you are curious as to what people are saying about the course, check out some of the blog posts from some of the most recent attendees:

Simon Brown

Dirk Rodermund

Sebastian Kramer

Bjorn Rochel

Stefan Lieser (german only)

Michel Grootjans



And of course, you can read my recap of the last course here .

It truly has been, and continues to be, a blessing and honor to be able to reach so many developers in this way.
There are only a couple of seats left for the Las Vegas course in 2 weeks, and only about 8 spots left for the Philadelphia course in November.
I look forward to potentially seeing you at a future course!!
Develop With Passion.




Comments [2] | | #