<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4930279255087763993</id><updated>2024-10-24T10:50:03.030+02:00</updated><category term="Build"/><category term="Continuous Delivery"/><category term="PowerShell"/><category term="psake"/><category term="Continuous Integration"/><category term="TeamCity"/><category term="Artifacts"/><category term="Testing"/><category term="WPF"/><category term="BDD"/><category term="Client Architecture"/><category term="DSL"/><category term="Silverlight"/><category term="TDD"/><category term="Architecture"/><category term="Boo"/><category term="DDD"/><category term="Mockups"/><category term="Presentation Model"/><category term="Prototypes"/><category term="Refactoring"/><category term="Rule engine"/><category term="SharpDevelop"/><category term="Vista 64-bit"/><category term="nested builds"/><title type='text'>{ blog: &#39;Gøran Sveia Kvarv&#39; }</title><subtitle type='html'>//Software Development</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4359034383040560910</id><published>2012-10-11T23:02:00.001+02:00</published><updated>2012-10-16T14:54:42.486+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Visualizing a pipeline REVISED</title><content type='html'>The series so far: &lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html&quot;&gt;Continuous Delivery with psake and TeamCity - Visualizing a pipeline&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Environment Configuration Management&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Time for Some Refactoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.no/2012/02/continuous-delivery-with-psake-and_13.html&quot; target=&quot;_blank&quot;&gt;Continuous Delivery with psake and TeamCity - Config Templates&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
In one of my pervious post, &lt;a href=&quot;http://gorankvarv.blogspot.no/2011/11/continuous-delivery-with-psake-and_30.html&quot; target=&quot;_blank&quot;&gt;Continuous Delivery with psake and TeamCity - Visualizing a pipeline&lt;/a&gt; I wrote about how you could sync build numbers between build configuration. In that post I suggested to create a file that contained the build number which would be published to the artifact repository in TeamCity and used by dependent build configurations to set the build number. That was not exactly an optimal solution. &lt;br /&gt;
 In &lt;a href=&quot;http://gorankvarv.blogspot.no/2012/02/continuous-delivery-with-psake-and.html&quot; target=&quot;_blank&quot;&gt;Continuous Delivery with psake and TeamCity - Time for Some Refactoring&lt;/a&gt; I talked about how you could use the inherited build number from the “parent” build configuration and pass that into the build script and then set the build number in TeamCity. This was certainly a better solution, but it would be better to just let TeamCity handle setting the build number. To fix this, go to General Settings in the dependent build configuration and put &lt;em&gt;dep.btX.build.number&lt;/em&gt; in the “Build number format” text box.&lt;br /&gt;
 &lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4qZ7vSjmEpkZNZi7mYJtFMCr0BAmHjPndAdd-P1p2GOD7y-v9nOFELDlPmUBJyQwxzMbjSgVaGHOqTiUMFL_0dmQ4KNrdSSZvuAtRveciU4xjSlF-jBw-hQiikd5RlOKPFyvRJ-sPQGQ/s1600-h/image%25255B15%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;125&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj20fRahNKFCS4cx4az9iTfbMSfMSYBcvKMYUpS5tNf0FXdQL_Gi_6sFXV3uU5lJDwct3nkTXPkknwpu29DRPKrHcgsrjqx4KW1XIqFo7v_KO96ADMy5Kkazq0awHe-CUS3pnzRnOZGxTw/?imgmax=800&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;420&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
 Actually I have been doing it this way for a long time now, so I should have written this post much sooner. Sorry.&lt;br /&gt;
  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4359034383040560910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2012/10/continuous-delivery-with-psake-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4359034383040560910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4359034383040560910'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2012/10/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Visualizing a pipeline REVISED'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj20fRahNKFCS4cx4az9iTfbMSfMSYBcvKMYUpS5tNf0FXdQL_Gi_6sFXV3uU5lJDwct3nkTXPkknwpu29DRPKrHcgsrjqx4KW1XIqFo7v_KO96ADMy5Kkazq0awHe-CUS3pnzRnOZGxTw/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-470502984542936149</id><published>2012-02-13T23:18:00.001+01:00</published><updated>2012-02-13T23:18:49.336+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Config Templates</title><content type='html'>&lt;p&gt;The series so far:  &lt;ol&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html&quot;&gt;Continuous Delivery with psake and TeamCity - Visualizing a pipeline&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Environment Configuration Management&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and.html&quot; target=&quot;_blank&quot;&gt;Continuous Delivery with psake and TeamCity - Time for Some Refactoring&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;When we are deploying we always do some config transforms so that the application is configured for the right environment. In Nant we got &lt;a href=&quot;http://nant.sourceforge.net/release/0.91/help/tasks/xmlpoke.html&quot; target=&quot;_blank&quot;&gt;xmlpoke&lt;/a&gt;, in msbuild 4.0 we got &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ff598687.aspx&quot; target=&quot;_blank&quot;&gt;XmlPoke&lt;/a&gt; and there&#39;s also &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd465318.aspx&quot; target=&quot;_blank&quot;&gt;web.config transforms&lt;/a&gt; in .Net 4.0 which has been transformed to a &lt;a href=&quot;http://ctt.codeplex.com/&quot; target=&quot;_blank&quot;&gt;general config transformation tool&lt;/a&gt;. In psake there isn’t something like this available, however as James Kovacks himself &lt;a href=&quot;http://jameskovacs.com/2011/07/07/token-replacement-in-powershell/&quot; target=&quot;_blank&quot;&gt;says&lt;/a&gt;, it’s very easy to do with PowerShell. I’ve created a little PowerShell script called &lt;em&gt;Replace-Tokens,&lt;/em&gt; which you can find on &lt;a href=&quot;https://github.com/kvarv/PowerShellScripts/tree/master/Replace-Tokens&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;, that does the work. Given a file &lt;em&gt;some.template&lt;/em&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;hello #{world}
&lt;/pre&gt;
&lt;p&gt;and a file &lt;em&gt;some.data.ps1&lt;/em&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;@{
    world = &#39;world&#39;
}&lt;/pre&gt;
&lt;p&gt;When we run:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;replace_tokens_with_file &quot;some.data.ps1&quot; &quot;some.template&quot; &quot;output.txt&quot;
&lt;/pre&gt;
&lt;p&gt;The output is the file &lt;em&gt;output.txt&lt;/em&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;hello world
&lt;/pre&gt;
&lt;p&gt;The main idea here is that we pass in a hash table who&#39;s keys will be located in the template file and swapped by the value. We can also pass in a hash table directly instead of a file. So referring to my former&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html&quot; target=&quot;_blank&quot;&gt; post&lt;/a&gt;,&amp;nbsp; if we were to change the app.config of the application when deploying to &lt;em&gt;Test&lt;/em&gt; and &lt;em&gt;Acceptance Test&lt;/em&gt;&amp;nbsp; we could use the script and do the transformation. Change the &lt;em&gt;test.ps1&lt;/em&gt; properties file to:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;$database_server = &quot;Server 2&quot;

$app_config_data = @{
    &quot;database_connection_string&quot; = &quot;Data Source=$database_server;Initial Catalog=App;Integrated security = true&quot;;
}
&lt;/pre&gt;
&lt;p&gt;Then change the &lt;em&gt;deploy&lt;/em&gt; task of &lt;em&gt;deploy.ps1&lt;/em&gt; to:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;task deploy -depends set_build_number{
    Write-Output &quot;deploying to $env =&amp;gt; database is deployed to $database_server&quot;
    $app_path = &quot;$build_artifacts_dir\Debug\ContinuousDelivery.WpfApplication&quot;
    $config_file = &quot;ContinuousDelivery.WpfApplication.exe.config&quot;
    replace_tokens $app_config_data &quot;$configs_dir\$config_file.template&quot; &quot;$app_path\$config_file&quot;
}&lt;/pre&gt;
&lt;p&gt;Note that we pass in the &lt;em&gt;$app_config_data&lt;/em&gt; from the test environment properties file. Now we just need to create a template of the app.config called &lt;em&gt;ContinuousDelivery.WpfApplication.exe.config.template&lt;/em&gt; and place in in folder called &lt;em&gt;configs &lt;/em&gt;under the &lt;em&gt;build &lt;/em&gt;folder:&lt;/p&gt;&lt;pre class=&quot;brush: xml;&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;connectionStrings&amp;gt;
    &amp;lt;add name=&quot;database&quot; connectionString=&quot;#{database_connection_string}&quot;/&amp;gt;
  &amp;lt;/connectionStrings&amp;gt;
&amp;lt;/configuration&amp;gt;

&lt;/pre&gt;
&lt;p&gt;This will overwrite the app.config based on the values found in the environment specific properties file when we deploy. Download the code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part9&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/470502984542936149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/470502984542936149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/470502984542936149'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and_13.html' title='Continuous Delivery with psake and TeamCity - Config Templates'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-7885847291384986525</id><published>2012-02-07T23:55:00.001+01:00</published><updated>2012-02-07T23:55:11.413+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="nested builds"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Time for Some Refactoring</title><content type='html'>&lt;p&gt;Refactoring is not just something you do with code. It’s also something you do with the build scripts and build process. Today we will split up our build script in nested builds and do some changes to how we pass on the build number to the next build configuration in the pipeline. &lt;p&gt;My previous installments in this series: &lt;ol&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies&lt;/a&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html&quot;&gt;Continuous Delivery with psake and TeamCity - Visualizing a pipeline&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Environment Configuration Management&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;First up, I want to change how I pass in the task to run and the environment to the build script. It looked something like this for the &lt;em&gt;CI&lt;/em&gt; configuration&lt;em&gt;:&lt;/em&gt;&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1 ci -parameters @{env=&#39;ci}}
&lt;/pre&gt;
&lt;p&gt;See how &lt;em&gt;ci&lt;/em&gt; gets passed in, both for the task and the env parameter. I want to change this so the build script gets these values from TeamCity through &lt;em&gt;Configuration Parameters&lt;/em&gt;. By doing that it’s a little bit easier to see and change these values. Let’s define some configuration parameters. Go to &lt;em&gt;Build Parameters&lt;/em&gt; and add this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtcbYTqGomkDqrnmJF9ZDZQcntFOxkm6ymBF1FWtjO1ijKIfupcmXvWYrvNo1i9lyMbRAkyrCQJs1fwxIG4gM6lP63xkEY46LshJYe61G43RfZJq2yRQzM1vpfew5uPya4UqKLkWwSFd4/s1600-h/image%25255B5%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO4oigOTCbZi8utfjXYsFEE-kWCFUkhgcjSTA8DjuzapbKqldT-3fzX1f-H7P2cbqkaPW6bUaMl8hBbeKFa-6CkGu2qi27RvB1hyNguKIRd-au7b4fTK520raCOZzo5bQ4MrN4_fy5hSw/?imgmax=800&quot; width=&quot;456&quot; height=&quot;163&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Change the PowerShell build step to:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1 %task% -parameters @{env=&#39;%environment%&#39;}}
&lt;/pre&gt;
&lt;p&gt;TeamCity let’s you access the parameters that you have defined by typing &lt;em&gt;%parameter_name%&lt;/em&gt;. Do the same changes for the &lt;em&gt;Test&lt;/em&gt; and &lt;em&gt;Acceptance Test&lt;/em&gt; build configuration.&lt;/p&gt;
&lt;p&gt;Next we’ll do something similar to pass in the build number from &lt;em&gt;CI&lt;/em&gt; to &lt;em&gt;Test&lt;/em&gt; and &lt;em&gt;Acceptance Test&lt;/em&gt;. When you set up a dependent build you get access to all the build parameters passed and set by the build a build configuration is dependent on. So if C is dependent on B and B is dependent on A, C gets access to both A’s and B’s build parameters. So the build number of &lt;em&gt;CI&lt;/em&gt; gets passed to &lt;em&gt;Test&lt;/em&gt; and &lt;em&gt;Acceptance Test&lt;/em&gt; as &lt;em&gt;%dep.bt2.build.number%&lt;/em&gt; where &lt;em&gt;bt2&lt;/em&gt; is the build configuration id of &lt;em&gt;CI&lt;/em&gt;. For &lt;em&gt;Test&lt;/em&gt; and &lt;em&gt;Acceptance Test&lt;/em&gt; add the following build parameter:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh70UGfL1Lon8AOlxanML_fcRdxxfJqmFMHowPDlM5mhuQJyZmGDv5PhuiTAez5RdfFnBRa213-gP8TUTcmei0aJSb4XsxPMf5oMWM3HdLen6Z6s1fc265Ch9wAeOwSMNDT34HKCs16p20/s1600-h/image%25255B10%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC1ZtpAp4okaUPWKSLOsR7vaI-BC-i9efGhHvwWyN8DAQo4yFrfMjPAVt_evK3Gtj_-Ip7bVwS9lcD-l-d_TigIlIfK1LFCXziJO3BhQmL8HLOkjFUKEh9lp-yjgN1bJc0U0WmufvoZ58/?imgmax=800&quot; width=&quot;494&quot; height=&quot;154&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and change the PowerShell build step to:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1 %task% -parameters @{env=&#39;%environment%&#39;; build_number=&#39;%build_number%&#39;}}
&lt;/pre&gt;
&lt;p&gt;The final thing I want to change how we call the task &lt;em&gt;deploy&lt;/em&gt; and &lt;em&gt;set_build_number&lt;/em&gt;. Both these tasks are relevant only to deployment so we’ll move them to a separate file called &lt;em&gt;deploy.ps1:&lt;/em&gt;&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;$framework = &#39;4.0&#39;

include .\..\tools\psake\teamcity.ps1

task default -depends deploy

task deploy -depends set_build_number{
    Write-Output &quot;deploying to $env =&amp;gt; database is deployed to $database_server&quot;
}

task set_build_number {
    TeamCity-SetBuildNumber $build_number
}
&lt;/pre&gt;
&lt;p&gt;and then we’ll add a new deploy task in &lt;em&gt;build.ps1&lt;/em&gt; which calls the the deploy build script so that we get nested builds, a feature in psake. Here we also pass along all the parameters and properties so that the nested build can access the same variables:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;task deploy {
    invoke-psake .\deploy.ps1 -properties $properties -parameters $parameters
}
&lt;/pre&gt;
&lt;p&gt;Remember to always refactor your build scripts and build process. It’s just as important as code refactorings :)&lt;/p&gt;
&lt;p&gt;Download the bits from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part8&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/7885847291384986525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/7885847291384986525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/7885847291384986525'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2012/02/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Time for Some Refactoring'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO4oigOTCbZi8utfjXYsFEE-kWCFUkhgcjSTA8DjuzapbKqldT-3fzX1f-H7P2cbqkaPW6bUaMl8hBbeKFa-6CkGu2qi27RvB1hyNguKIRd-au7b4fTK520raCOZzo5bQ4MrN4_fy5hSw/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-7181985211137639535</id><published>2012-01-29T23:39:00.001+01:00</published><updated>2012-01-29T23:39:07.731+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Environment Configuration Management</title><content type='html'>&lt;p&gt;Happy New Year! I’ll start of the year by adding another post to the series about continuous delivery with psake and TeamCity. So far we’ve covered:  &lt;ol&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html&quot;&gt;Continuous Delivery with psake and TeamCity - Visualizing a pipeline&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Today we’ll look at how to take care of configuration settings when we are deploying to different environments. &lt;/p&gt; &lt;p&gt;Let’s say that we have set up three environments; “CI”, “Test” and “Acceptance Test”:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3DpWPAJ1fJsnkjzfGw3MgaTB8rj8LqFR9cFEXD2F0b1Z9Ux75EcUHr8Ia-05gVvRKlWBsxOFKapP1PSDVrrRywwH9T3jAqFGqUsQq-26XWN0Ta5N8sS048VF-7hAHPhPzuRCuSzfAD0/s1600-h/image4.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWv2Ye3LkvfQZdCROj1-HMGidXMcH3XMpMM3Q9Y9orI8FHxvkGLrgtb-miJOwGx4Exvb2xclBlxDwq0j2cyphNbeMG5-_p_Szd83tWjAdNj8CwBH8_3JIl4cdKrLA1cjf25-PkjNXDCrU/?imgmax=800&quot; width=&quot;385&quot; height=&quot;214&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Each of these environments need to have specific settings, for example which server to deploy a database to.&lt;/p&gt; &lt;p&gt;Powershell has the concept of &lt;a href=&quot;http://technet.microsoft.com/en-us/library/ee176949.aspx#ECAA&quot;&gt;dot sourcing&lt;/a&gt;. Basically it lets you include a PowerShell script from within another script and then you get access to all those variables and methods you defined in the script you included. We’ll use this feature to load an environment specific file into our build script based on an environment parameter that we pass into the build.&lt;/p&gt; &lt;p&gt;Modify the build script called build.ps1 from the previous post&amp;nbsp; and add the highlighted line to the properties section:&lt;/p&gt;&lt;pre class=&quot;brush: ps; highlight: [11];&quot;&gt;properties {
    $base_dir = resolve-path .\..
    $build_dir = &quot;$base_dir\build&quot;
    $properties_dir = &quot;$build_dir\properties&quot;
    $source_dir = &quot;$base_dir\src&quot;
    $build_artifacts_dir = &quot;$base_dir\build_artifacts&quot;
    $tools_dir = &quot;$base_dir\tools&quot;
    $config = &quot;Debug&quot;
    $test_dir = &quot;$build_artifacts_dir\$config\tests&quot;
    
    . &quot;$properties_dir\$env.ps1&quot;
}
&lt;/pre&gt;
&lt;p&gt;Next we’ll add three environment specific files to the path “.\build\properties”:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;# ci.ps1
$database_server = &quot;Server 1&quot;
&lt;/pre&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;# test.ps1
$database_server = &quot;Server 2&quot;
&lt;/pre&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;# acceptance_test.ps1
$database_server = &quot;Server 3&quot;
&lt;/pre&gt;
&lt;p&gt;One of these files will be loaded when we pass in the &lt;em&gt;env&lt;/em&gt; parameter to the build script from TeamCity. &lt;/p&gt;
&lt;p&gt;Copy the &lt;em&gt;Test&lt;/em&gt; build configuration and call it &lt;em&gt;Acceptance Test&lt;/em&gt;. Remember to republish the artifacts downloaded in the &lt;em&gt;Test&lt;/em&gt; build configuration and make&lt;em&gt; Acceptance Test &lt;/em&gt;dependent on the last pinned build of &lt;em&gt;Test:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnopUh6hB5_jqAlChDEvKn_Bq41HkFyz-4lYPhh-EXhnCClM8OTT4oDnvT2Fs49M_nlytkDv0EfA4PL3I6639upr4aEV2NZrPs5jn4vtWBkZV1HQGvmeJ_s5rA3fb5sXWEgzNd0u_Ieeg/s1600-h/image%25255B3%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtPrp3NjQ7XxyqiieiTlfvHxnoxIsJJGW2V4VXbe2AgJQjuX2w0eTv9dlesYemLc1ZNqvTuPggXq3H4EAtljqYuBZNpS-gx36-sMkDXyzgnkSqMa_K0-tsuU_GWdAcfAWRE3NiU17xKpI/?imgmax=800&quot; width=&quot;435&quot; height=&quot;319&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Change the Powershell build step (see picture below) in TeamCity and add &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimauKk7RSg6-WsehpX2H0Ylcq1CRhilwy6operDfzyLiNpKQCCHTuxxGxU8t7of8vHed7DheHWrUfPjNGduwsjJ77n0aX3Wsj18P7qmqVF_EAI4Tt_yb4FJ1EM4yedEnji2qXox9qjrHs/s1600-h/image16.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGB7af2T6BLzNfatkYpj4Cs0sgKy4YmaXY4VpYuA8eCrhvtRillb8dB8MglDVNSQIEYBirXQ_a7gM4sFGi3b1rMyrzLS0oJuyOFJzAdlqBx4e-LERC6juhsmehuGHEceMhJmBOADIxrTQ/?imgmax=800&quot; width=&quot;378&quot; height=&quot;227&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;-parameters @{env=&#39;ci&#39;} to the &lt;em&gt;CI&lt;/em&gt; build configuration,&lt;br&gt;-parameters @{env=&#39;test&#39;} to the &lt;em&gt;Test&lt;/em&gt; build configuration and&lt;br&gt;-parameters @{env=&#39;acceptance_test&#39;} to the &lt;em&gt;Acceptance Test&lt;/em&gt; build configuration.&lt;/p&gt;
&lt;p&gt;Let’s modify the deploy task in &lt;em&gt;build.ps1&lt;/em&gt; and print out some information about the environment:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;task deploy -depends set_build_number{
    Write-Output &quot;deploying to $env =&amp;gt; database is deployed to $database_server&quot;
}
&lt;/pre&gt;
&lt;p&gt;and also add the following to the compile task:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;Write-Output &quot;Integrating database changes for $env at $database_server&quot;
&lt;/pre&gt;
&lt;p&gt;to simulate that we integrate database changes. Since we defined the variable &lt;em&gt;database_server&lt;/em&gt; in the environment specific files we can now access it in the build file.&lt;/p&gt;
&lt;p&gt;We should now be able to verify in the build log that we have “deployed” to our specified server:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqgSKyj5lhQNuvGet5663DVof7tczYpCoAwRB68PvSbdwV1kBCc-D-XH2kjYFHlAFMh0EK3fJnBiIYd9-AOJabrLx-4qnWUTGZkZHTW6SpCti8PsD38RP0LUzkFNkt_bfwtLtgnt4sOrs/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjOYutv6AYafxgb7qUNMmH-g1KTX-5ifmk7lo1wp770djI7Mojr_JHwbV2a3p9_I12Ew1A9uMAO7_vaHenJD9gUkrXOSJzdFOALH0vbSjpwczXWM6vWNcKIVKUgKf8G5-v9CR4AcODHIg/?imgmax=800&quot; width=&quot;533&quot; height=&quot;56&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also see that builds flow between the different environments and be able to see which build is deployed to which environment:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBlwfdtyBHmc6Io-tMhCCp2Y-iRWGbONYURkkyNaOb8K6FT2wv4FVFLRhOvuhbikFkKN7suQSA_TZo7BmkFAaoDTh8thRBmNEmdqH4MbSQ1xdaAZ8lMyZde5Hs5ESdC7rt519lhtDdqxU/s1600-h/image%25255B12%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpW9C52_lJeUxZUAcPo2oiYtIp7c4hxwxCwBNIllkmqUmw7NcLv1GPBbIWrB9IuyKv2HVAsc7md2zQGH0Pj29PYHBVF8jm_ex7GSrhMuRGFJkSoIjLhAHhVoHUz_mr9dX4QgeotZP3JyE/?imgmax=800&quot; width=&quot;346&quot; height=&quot;272&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As always, download the code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part7&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/7181985211137639535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/7181985211137639535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/7181985211137639535'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2012/01/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Environment Configuration Management'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWv2Ye3LkvfQZdCROj1-HMGidXMcH3XMpMM3Q9Y9orI8FHxvkGLrgtb-miJOwGx4Exvb2xclBlxDwq0j2cyphNbeMG5-_p_Szd83tWjAdNj8CwBH8_3JIl4cdKrLA1cjf25-PkjNXDCrU/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4267872636562870545</id><published>2011-11-30T00:17:00.001+01:00</published><updated>2011-11-30T13:10:35.532+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Artifacts"/><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Visualizing a pipeline</title><content type='html'>So far we’ve covered:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
Today I will show you how to update the build number of a deployment build with the build number of the build it is dependent on. &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh96Eq_H_fO5PsVA8XCfJ-gU1ivBhmvvk6NTrc2Ikf_L3GvEdXzpNkLa6Cv9JHdLtTenutVdbvbb3ZK806J95eZVWyPTTw4LY-Ohyphenhyphen46Wmz-GrV_z64rNtHhRcx_mA3UZBGLe8wKHKrVLPE/s1600-h/image%25255B3%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;180&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhEAHI6t-2e-ovctbJhFMuovG4GXEBFxfT7yAdA9M4hrQcWwL0_vf-AQr5V5XJz_HZ3wAX0iHEPZci55ZE8in6kxsbbqv-1I_rtKcrUcp2icZp5HzxtGtb45980ML0GuCIEJ8hEmXj5iE/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;ol&gt;&lt;/ol&gt;
So if we were to deploy to test and the build number of the dependent build is 1.0.0.24, we want to visualize that this build number is actually deployed to test by updating the build number from our build script. One strategy for implementing this is to let the CI build output a file with the build number and publish it to the artifact repository in TeamCity. &lt;br /&gt;
The first thing we have to do is to create a task that outputs a file with the build number:&lt;br /&gt;
&lt;pre class=&quot;brush: ps;&quot;&gt;task create_build_number_file {
    &quot;$env:build_number&quot;  | out-file &quot;$base_dir\build.number&quot; -encoding &quot;ASCII&quot; -force  
}

# Add this task as a dependency to ci
task ci -depends compile, test, create_build_number_file
&lt;/pre&gt;
&lt;em&gt;$env:build_number&lt;/em&gt; is an environment variable set by TeamCity containing the build number of the running build.&lt;br /&gt;
Next we have to publish this file to the artifact repository. Add&lt;em&gt; build.number&lt;/em&gt; to the Artifact paths in TeamCity:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbLUh6pLVS6lJL7vzg6DU_IPR_4VTYR2ACudeJzDvvJl2reUMS8rxJM1sJcNqsI0TfDFV2nE5OwFabAecRqYgX0ktybndLcjyBt-ckk6JAKkqsi40BBAm8GYFwGhQgtlED82FeXQNfOAU/s1600-h/image%25255B19%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;115&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmHU_zR4uGlFymJZ4DT2lEh8v1GELgRS-wZRyzeoth-mGpQHlF3anJ1eZ1ze-vJ-Vg7ByOMpx5RgyIXgizL0r7Gk3jyPDZ2YB4AR9cb2yeHju8b5um6GicZ6nzumIWNYio7ipd8kmKS2E/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
If we now run the CI build we should see something like the following under the Artifacts tab of the build:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlgz1dqop5ohE-ju4QThv4x3o6S9MPSJV3ym3Q1NfOaPnuKMfSFxGLcDM11pDvH5LIekHCGaCeRvPVdcjL8wyONKmCtUQ8URwC4xpo86ARpqqwuvA2NqBjNdsMUGLUrAs2dPAqNlO_1YE/s1600-h/image%25255B7%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;172&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAlRSZzoQpA4Wud2J7ibER6V_v3nZ3yXFv16RUWkN26oNh8P_Uc-v7pLfChgkIqynDsUNpuGPSyGQT4RaKs1umOQWXzTKvl6NCG4k4BNhlGJ9pz5IO_aJt4mso-FpaZs1OxlX3YCG8oic/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
So far, so good! Next up is to read this file when we deploy to test and set the build number.&lt;br /&gt;
&lt;pre class=&quot;brush: ps;&quot;&gt;task set_build_number {
    $script:build_no = get-content &quot;$build_artifacts_dir\build.number&quot;
    TeamCity-SetBuildNumber $script:build_no
}

# Add this task as a dependency to deploy
task deploy -depends set_build_number{
    Write-Output &quot;deploying to test!&quot;
}

# Make sure to add this line after the properties declarations
include .\..\tools\psake\teamcity.ps1&lt;/pre&gt;
&lt;em&gt;TeamCity-SetBuildNumber&lt;/em&gt; is a helper function that is defined in teamcity.ps1 which comes bundled with psake.&lt;br /&gt;
&lt;br /&gt;
We also have to tell TeamCity to download the build.number file when Deploy to Test is run:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivzMHxeNT8bE5oA9nOQRprPQv3w9Z-FbH2lKDFt1keE2Lx3rwEVWL-Z97OzYeYwIMckvLcHVrQFtZWJDdWmMPKDWrVX2huDEnpqewaxhw1x6ZjCAb4Yn5-ZSXqSoogBjrSpeLKd22arWQ/s1600-h/image%25255B23%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsYBiFg2cG1It27xqq1CkljYKlXhA81Y66pxg1ARPHuIlsRXQNmbmADW1fpKzOs23-nwiAzEbyJkAEK62EkbndeUrbgZbMC2lZomZN9toYknXlAV8CYOipJyW13AiGeYisqBkT19vmAfw/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
If we run Deploy to Test the TeamCity dashboard should look similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtf4_VQcO7qlzAu_PZStFbBiMMWRHVc41KxD_lwKcxwxF_1DLCUCOrvW0e-YzLml9MZJVddeIhiOUj-BtUqffpWEeb8SomaBbfVbP9LMvk3rpcTrrcPdWpBcFD0diunnulKdzf3L0cWUI/s1600-h/image%25255B27%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;171&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtMNB9R1s7LZHVyoSE-NbhFuu3-LPtoKNMXW6ZxEkAK06dNs59-zqCx76vqdHusQxyIPbxBEEhMUCzfYBdkfkfrxSXWI66V698Vv8do_RTTyL-hcYGAsyuc35-RK3VhKtFRnAkIWTw-Qk/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-color: initial; border-bottom-style: initial; border-bottom-width: 0px; border-left-color: initial; border-left-style: initial; border-left-width: 0px; border-right-color: initial; border-right-style: initial; border-right-width: 0px; border-top-color: initial; border-top-style: initial; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
We have now seen how we can visualize which build number is deployed to which environment. Happy days!&lt;br /&gt;
As always you can download the source from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part6&quot;&gt;GitHub&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4267872636562870545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4267872636562870545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4267872636562870545'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and_30.html' title='Continuous Delivery with psake and TeamCity - Visualizing a pipeline'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhEAHI6t-2e-ovctbJhFMuovG4GXEBFxfT7yAdA9M4hrQcWwL0_vf-AQr5V5XJz_HZ3wAX0iHEPZci55ZE8in6kxsbbqv-1I_rtKcrUcp2icZp5HzxtGtb45980ML0GuCIEJ8hEmXj5iE/s72-c?imgmax=800" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-6577227155167469341</id><published>2011-11-02T23:55:00.001+01:00</published><updated>2011-11-02T23:55:27.005+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Artifacts"/><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies</title><content type='html'>&lt;p&gt;In my last post we learned how to publish artifacts from a build that we can use to create a continuous delivery pipeline. So far in this series we’ve covered:  &lt;ol&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Preparing for a pipeline&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Today we’ll create a build that has an artifact dependency on the CI build that we’ve already setup. This let’s us reuse the artifacts that we published in CI so that we don’t have to compile our solution once again. First, we’ll have to create a deploy task in our build script so that we can simulate a deployment. Edit build/build.ps1 and add this task:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;task deploy {
    Write-Output &quot;deploying to test!&quot;
}
&lt;/pre&gt;
&lt;p&gt;Let’s create a build configuration called &quot;Deploy to Test” where we will use our newly created task and simulate a deployment to a test environment. Add a Poweshell Build Step with script source:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1 deploy}
&lt;/pre&gt;
&lt;p&gt;This tells TeamCity to run psake with the specified deploy task. Next we’ll have to setup the dependency between the “Deploy to Test”-configuration and the “CI”-configuration. Go to the &lt;em&gt;Dependency&lt;/em&gt; tab in TeamCity and click &lt;em&gt;Add new artifact dependency&lt;/em&gt;. This brings up the following dialog where you can specify the properties of the dependency:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJWoNf2WyCT7yLaXnr60VqL9FDKHrzMrTicwHbcOK72bAHsXR9QHaqfKJIsPv42nho00pdzwE93bEoSAO6soF2nRbdbNwUDVG2ZgkvBOrCT5nSCgKehTW4f7mxGYxUsLXHnRpFFwem4kM/s1600-h/image%25255B5%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiixkzsnB6-6PRndhvSeqaY35-065g-qbseXnydIeibqAfatEyBgqTBKO7yoEjNns77XvJiItuVBf472FDiDnZq2fYaQMFqmy6WrNTblCxKEQ3gJ8gT7CflVDxFz5PHkAUjqmqVnHZCv0/?imgmax=800&quot; width=&quot;475&quot; height=&quot;322&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here I have specified that I want to get the artifacts from the last successful build of CI and that I want to download the file &lt;em&gt;app.zip&lt;/em&gt; and extract it to the folder &lt;em&gt;build_artifacts&lt;/em&gt;. You can read more about this configuration and wildcards &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD65/Artifact+Dependencies#ArtifactDependencies-artifactsPath&quot;&gt;here&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;By now you might think that we&#39;re ready for running the build. However, running it would fail. The reason for this is that TeamCity wouldn’t find psake or our build script. We have to have a strategy for getting the build scripts and tools. One option is to publish them to the artifact repository from the CI build and download them from there. Another option is to download the build scripts and tools from source control. With the latter option you could potentially try to deploy new deployment items, say a web service, from a build that hasn’t got it yet. In other words, you have to be very careful if you update the build script because you always get the latest version, whereas the binaries you get from the artifact repository could be older and not contain what the build script expects. With the former option you have to go through every step in the pipeline to get an update of the build script. Say you find out that you have an error in the build script regarding deployment to production. To fix it you have to go through every step in the pipeline. This is time consuming and it also means that you cannot deploy the original build to production. You now how to deploy the new version. At my current client I have taken the former approach, but based on my experiences I would personally recommend that you download the build scripts and tools from source control. This makes it a lot easier to fix errors and do refactoring.&lt;/p&gt;
&lt;p&gt;Back to TeamCity, attach the VCS root that is used in CI to the build configuration under &lt;em&gt;Version Control Settings, &lt;/em&gt;click &lt;em&gt;edit checkout rules&lt;/em&gt; and add this:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;-:.
+:build
+:tools
&lt;/pre&gt;
&lt;p&gt;The first line says that TeamCity should exclude everything from the checkout. The next two lines add the &lt;em&gt;build&lt;/em&gt; folder and &lt;em&gt;tools&lt;/em&gt; folder respectively. If we save and run our build now you should get something similar to. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipCxCF3YjRjD67qgC2M-3UHcNlAuKXtnpe5SpjpkYxc67tCnZGKdDPnL0QxB2rP4A7kwWneE8w2BByqwcZXCHNp5AAQV1Z_dtn74Dj6v4ByFm4S8-EEojDDh2WyNpELcBFmqEw8l6-IxM/s1600-h/image%25255B16%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvMU7UGghdd-XtszKlHj3ZgnFSecjkuhKqRQ0Dayyq1R4l70VCtgTj8dEDrH4OkvPyEDIvVy-VKpyAWm8kmKmOSOYatEfWpVSXyECSvyfg222_QVcUvjmWYhNnV1biNm61J1PSS3lIK_4/?imgmax=800&quot; width=&quot;598&quot; height=&quot;388&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To add additional steps to the pipeline you could just publish the same downloaded binaries to the artifacts repository and make the next deployment dependent on “Deploy to Test”. Let’s say the next step is deployment to staging. Then you could say that the build that is deployed test has to be verified by QA before it’s deployed to staging by setting up a dependency where you get the &lt;em&gt;last pinned build&lt;/em&gt; from “Deploy to Test”. This feature in TeamCity is extremely useful for adding build verification to the process.&lt;/p&gt;
&lt;p&gt;Next time I will show you how to label the deployment builds with the build number from CI. See ya!&lt;/p&gt;
&lt;p&gt;Download the source code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/zipball/part5&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/6577227155167469341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6577227155167469341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6577227155167469341'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/11/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiixkzsnB6-6PRndhvSeqaY35-065g-qbseXnydIeibqAfatEyBgqTBKO7yoEjNns77XvJiItuVBf472FDiDnZq2fYaQMFqmy6WrNTblCxKEQ3gJ8gT7CflVDxFz5PHkAUjqmqVnHZCv0/s72-c?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-5869614010053545526</id><published>2011-10-14T10:12:00.001+02:00</published><updated>2011-10-14T10:12:07.893+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Artifacts"/><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Preparing for a pipeline</title><content type='html'>&lt;p&gt;In my previous three posts I have shown how you could set up a Continuous Integration build with &lt;a href=&quot;https://github.com/JamesKovacs/psake&quot;&gt;psake&lt;/a&gt; and &lt;a href=&quot;http://www.jetbrains.com/teamcity/&quot;&gt;TeamCity&lt;/a&gt; 6.5. This time I will show you how to prepare for continuous delivery where the artifacts from the CI build flows through several steps and environments that together form a pipeline of builds which culminates in deployment to production. It seems like this is developing into a series, so here are my previous installments:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build With psake, Part 1: Compiling&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;Creating a Local Build with psake, Part 2: Testing&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html&quot;&gt;Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;One of the core principles of continuous delivery is that the deployment process should be repeatable and reliable. To achieve this we have to make sure that every bit of the deployment process is automated and that we deploy in the same manner to every environment. I urge you to read &lt;a href=&quot;http://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912&quot;&gt;Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation&lt;/a&gt;. It’s a fantastic book!&lt;/p&gt; &lt;p&gt;The output produced from build is usually referred to as the build artifacts. This includes all the compiled binaries and other packages, for example installers and migration scripts for a database. It is very important that you compile you binaries only once and use the same binaries to deploy to each environment in the pipeline. To enable this the artifacts needs to be stored somewhere so that the deployment process can get it. TeamCity comes bundled with an artifact repository which can be configured in the Build Configuration. This feature allows us to associate the artifacts from a build to the build id and reuse them by setting up an artifact dependency between the different builds in the pipeline. By doing this we can say that the deployment build to for example test has a dependency on the CI build. Whenever the deployment-to-test build runs, TeamCity will automatically download the artifacts from the specific CI build you configure it to get it from, for example the last successful build of CI. In this manner we can chain or builds to create a full continuous delivery pipeline.&lt;/p&gt; &lt;p&gt;Let’s get on with it and configure our CI Build Configuration to publish artifacts. Open the Build Configuration and look for “Artifact paths”:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTDFzdQitKygbWiQYXLpyv0jYSZeLX3HcJtw9Tn3_fOK_0Ai5RSz4hRx4B91qAj3hySNhSwOWDfrC-8bcQoctQTNQS04BlIYILfsZUfn57QvJYcM4qMfeZXabmg83brQ4-IAMdFl8G9f8/s1600-h/image%25255B12%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVWlyGQtXqUTZ-20cYtCkjNj7ZEOWdJWQgwwXT-9pxc1MuTPPyrOA85vvzv9dZl4H7O3uuMNXNPx48YzlWnZ1yU9ckx1x_K7CC-b1Qz5efOYtrCoHtmqeDBxBPCGW4hRxjERpKqfpE_KM/?imgmax=800&quot; width=&quot;559&quot; height=&quot;103&quot;&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here you can specify files and folders that you want to publish to the artifact repository. For a detailed explanation of the format see TeamCity’s &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD65/Configuring+General+Settings#ConfiguringGeneralSettings-ArtifactPaths&quot;&gt;documentation&lt;/a&gt;. Let’s make TeamCity zip our WpfApplication so that we can deploy and distribute it in successive builds. Add the following to the “Edit artifact paths”:&lt;/p&gt;&lt;pre class=&quot;brush: ps;&quot;&gt;build_artifacts\Debug\ContinuousDelivery.WpfApplication =&amp;gt; app.zip!ContinuousDelivery.WpfApplication
&lt;/pre&gt;
&lt;p&gt;This statement takes all the files in the ContinuousDelivery.WpfApplication folder and zips it to a ContinuousDelivery.WpfApplication folder inside app.zip. If we now run the CI build we should see that an artifacts tab has appeared and that our zip-file is displayed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5ZKwbWAxkNi0SGpYjXIIX01XDIQPTJ6oNBTVOfmEEsGeDu4i6PEmCUE3bh3MZDx1VKrAZTF3fmMDbvSw-86xJBrkfHHySUduStE8cI0J5EO35kklTQLBYQqTeoK0hi0NiM-zXWKWUjH4/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7_jmtS4EZnmyvx5j2L6AVlUnhKmM5M6z9J4LP51RJUiBVh18vNghy3ps_9e6Ga6gCV1YZMbAfHOna062I2Ol9DY56qswc2pmNWnr5d0YJrFjH_uqKp-C24EhxQZzIjSfdYcbdxyWpsE4/?imgmax=800&quot; width=&quot;571&quot; height=&quot;111&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That concludes this post. Next time we will reuse the artifacts and setup a dependent build to deploy to a test environment.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/5869614010053545526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5869614010053545526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5869614010053545526'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/10/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Preparing for a pipeline'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVWlyGQtXqUTZ-20cYtCkjNj7ZEOWdJWQgwwXT-9pxc1MuTPPyrOA85vvzv9dZl4H7O3uuMNXNPx48YzlWnZ1yU9ckx1x_K7CC-b1Qz5efOYtrCoHtmqeDBxBPCGW4hRxjERpKqfpE_KM/s72-c?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-5399781212684728007</id><published>2011-09-16T00:00:00.001+02:00</published><updated>2011-09-21T08:45:31.007+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity"/><title type='text'>Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build</title><content type='html'>In my previous two posts I have shown how you can &lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot; target=&quot;_blank&quot;&gt;compile&lt;/a&gt; your solution and run your &lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html&quot;&gt;tests&lt;/a&gt; with psake, effectively creating a simple local build. Building upon my last two posts, this time we will reuse our local build script to create a CI build with &lt;a href=&quot;http://www.jetbrains.com/teamcity/&quot;&gt;TeamCity&lt;/a&gt; 6.5. Assuming that you have already installed TeamCity, create a new build configuration called CI and setup your VCS. I’ve set it up with Git:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9y16Hf8LYGGP1Of8b1aG8xcDl7-ajszU_4AmCrVMbP3uhrabOneQM3nrSRxa3VLE6lzFFjMehUnPI4KwyDJDOoXGhvM43E7CfpSmCghmRU1JboBrpotGyXa77Z3iosCuqOKG702cAm1o/s1600-h/image4.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;677&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0hqpm28hfOgOm4gRha93btX7HYp5VJpV3onvMwBU1TRpRviOBndxelHCtCWR7Yva2sjF89mK_BvPGvB0gpCGiGyhdM0aw9_J6aFjKb7O_-VE0WdxTzYUqUOrsNavrGPIVoEzjpQsspK4/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;562&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Add a Powershell build step:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizRrT8r9TvPAQgj4Bhjmt3v_FI-fr0DUUf8HkCGh5b12IX6XjBeU-ZB620Fd0LpQE4Y-WWMt_3aiQv9B3MwERoiGbuAHVHesb2e-rOkFMggUEmp99G5k0LTlc18y9jQgeJX-zSM_c_S3M/s1600-h/image%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;572&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9k9XMaTjoEPZrZc439SxFfodpiJNakJOEGl-Kwz9wWcnLMkPhzjwAaI8FMDp81glQjITGUIMjVnvreaeWqPHM7WqFOdLWr5KbPPIacxv34JICwXT6VhHbhaLyQ8wsZQauNR-EeWjBNX8/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;564&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Choose “Source code” and paste in this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: ps;wrap-lines: false&quot;&gt;&amp;amp; .\tools\psake\psake .\build\build.ps1
&lt;/pre&gt;
&lt;br /&gt;
It is also important to add&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: ps;wrap-lines: false&quot;&gt;-NoProfile -ExecutionPolicy unrestricted
&lt;/pre&gt;
&lt;br /&gt;
as “Additional command line parameters” because execution of PowerShell scripts are disabled by default. Now make sure that you have set up “Build Triggering” in TeamCity to “VCS Trigger”:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIAmn0LE6_Awl2XYgXccZ-arKjeuPzYCnEgZM9Qket2uXQdbBhmo8NOoUc86MWn4kpZIP8u-ZiNCrIM1jO6TowCsqISyXHcKlKnqTsC4ls6Gn6HgB8dXBAo-L2MUZ-C3wb8VCxFzym3eU/s1600-h/image%25255B11%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;490&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiZt9aiWMGCDJEmUuPJ_yeJBQP9RsK7aCtFwjqJNCB7-wXrGVGVrQUAWeLCOphg8aSCqoUpQjXXtiIS6a5PvyWMvrzd9FSwsDBx_59ONy3Fy4KnM4X1Sm9AhWSiGDSqxTdkjWXHGvOr1M/?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;448&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
If we now run our build we should get a green “Success”. &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM42dwVT92yQ9NK49srRhYuIxI0DydCWzD6S40VRjohWdvlAxoOH_L9vvpHleYRU7AMX3ZjtZHsaxBB1a-vn2lUgVitbJJZTiFzgNc8PGDtCGNxjHQXk7_tINW4Ls2-mOAjWCXhAFI25E/s1600-h/image%25255B13%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;72&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDMbONj6Tu21Ik7uEyrJJkGDoJSzj-nx2XOireAn-D0sNahKDn-YsQ1FUVa1kfpOjBfgM9FFF2yfVPm5kffEZ6HryqM_se13zgZGVEdp1sDsHIQjxYhvELBHThvoZXD0u2i_0gUux76SQ/?imgmax=800&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;249&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Since we have executed the tests as a part of the build script and not through TeamCity we are missing a test report. We can easily report the test results to TeamCity by using a &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity&quot; target=&quot;_blank&quot;&gt;Service Message&lt;/a&gt;. Add the following to&lt;br /&gt;
the exec function of the test task:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: ps;&quot;&gt;Write-Output &quot;##teamcity[importData type=&#39;nunit&#39; path=`&#39;$test_dir\tests_results.xml`&#39;]&quot;
&lt;/pre&gt;
&lt;br /&gt;
If the path to the test report is very long PowerShell will automatically wrap the service message and the message will not be picked up. To alleviate this problem we can increase the PowerShell UI buffer size. Replace the “&quot;Script source” in the Powershell build step in TeamCity with this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1}&lt;/pre&gt;
&lt;br /&gt;
Check in and watch the test being reported to TeamCity!&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1ydwtkVQWcGR8alkMbn9njMW6pZELxORAnpjd99ToGd5RY0KWaDaMFCXEnOIyCNn8cvP832o3kUN4DsorEmS3SJEDX15r-il7372zdTE2b3pPLn3Fr43lzFUNbGfSioqKH0EeyVv9rYg/s1600-h/image%25255B12%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;75&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjracthYkmA_kfRgXVEQB6dpCB56Sd-gOx4g8A1KaYd9rAJ6CIAEMX_p9KFOjZrsps2f3Trs9_NJGwdpD8hCf_E925xEGovJXE2shZW_VIRc3YG6DYxqU5t-TGurR6uzHiECySrmjDs__Q/?imgmax=800&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;301&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
At this point you should consider creating a &lt;em&gt;ci&lt;/em&gt; task that depends on compile and test. You probably want to add other tasks which &lt;em&gt;ci&lt;/em&gt; is dependent on, for instance swapping out the config file for your test project, migrating a database, deploying, etc., etc. Just add the &lt;em&gt;ci&lt;/em&gt; task as an argument to &lt;em&gt;build.ps1&lt;/em&gt; in TeamCity:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: ps;&quot;&gt;&amp;amp;  {$host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(512,50); .\tools\psake\psake .\build\build.ps1 ci}
&lt;/pre&gt;
&lt;br /&gt;
That’s all for now!&lt;br /&gt;
&lt;br /&gt;
Download the code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part3&quot;&gt;GitHub&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/5399781212684728007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5399781212684728007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5399781212684728007'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/continuous-delivery-with-psake-and.html' title='Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0hqpm28hfOgOm4gRha93btX7HYp5VJpV3onvMwBU1TRpRviOBndxelHCtCWR7Yva2sjF89mK_BvPGvB0gpCGiGyhdM0aw9_J6aFjKb7O_-VE0WdxTzYUqUOrsNavrGPIVoEzjpQsspK4/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4790208517726897501</id><published>2011-09-02T15:53:00.001+02:00</published><updated>2011-09-07T23:25:23.620+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Creating a Local Build with psake, Part 2: Testing</title><content type='html'>&lt;p&gt;In my last post &lt;a href=&quot;http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html&quot;&gt;Creating a Local Build with psake, Part 1: Compiling&lt;/a&gt; I showed how you could compile a solution with &lt;a href=&quot;https://github.com/psake/psake&quot;&gt;psake&lt;/a&gt;. This time we will expand our build script and include a task that will run all the tests in our solution using &lt;a href=&quot;http://www.nunit.org/?p=download&quot;&gt;NUnit 2.5.10&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;The output from building is often referred to as build artifacts. I like to configure the output of the projects in my solution so that they output to a folder called “build_artifacts”. In my example solution I have two projects. An WPF application and a test class library: &lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrhJ7bYri0DzodoMX8zJN9X-3iM5ZZWQEqXXozh-MNU-fU9VppFQ-9S-g8qdziNlFl2BJRX3e2eO1Rcp7PTLT7dMMHRXmaj46P2ss2JJ87ocVltM70sQIp5zbRnSJWt6XRDM873APJqis/s1600-h/image%25255B7%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQiVInVHDcW97DbGB9L-QwdpnLSaafo5W0wj-C4NZ-a0sSYwD7NZHpBcalDMXH3nZWGtApjqF6-6wyQyEzkE0gXaYJviDK1w4JgrLsaMevefO33_yE-HcE22EYdvqkQJgGV2VjHXGFZI/?imgmax=800&quot; width=&quot;275&quot; height=&quot;209&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I have configured them so that the output from building with Debug is output to the “build_artifacts”-directory:&lt;/p&gt; &lt;p&gt;‘&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQUxi8YdNEEZDBVEs8ZewulLP3zAU7f5BVHr3dcQZ0ibZ6AUjwENesZMS8dzvexY4pMXPVLonsy7ZwQuliPmmCLDBgAxy_ib6DvH-zQnMN_YpUFHbt_oLnf_5BMr0f4k53HzgZite-Kqg/?imgmax=800&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNEknWYsN3Nmp95AV55GOQvzUa6cOO9Aq_M5ebDy3wAL32Xs2DKzLuFD7bhVE0sYCA0s80lLYZt85WSWIMZ3ZAeLxTh4nIoA9JjgJAJzkC2lFjgOChtWL2rt4M8fymQ5WrtVFXfL7wJn0/?imgmax=800&quot; width=&quot;549&quot; height=&quot;377&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT5ud3B58TgjH7uD6skoOpAY5RL8YeiJiVX3E58DGb7YlUEYw0CnfXpb9RAhkYaqZ_sIKdbJoOkA40f2nghTeSOh97rEDyzsV3ji2JH5kOfEIRL6uvZI1fRno5Bd9FlX8ChdHNAJd0Fd8/s1600-h/image%25255B14%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtKQybE-G__DxdOILE-_iqvArSLA_gU3H62rhtxg9A9wuu-tIOI0QZyjPKRSBzHGRglOn0AJYlUe-PEa_vJi7H6S4HOhcysccz4JtL-YYay2rmk8_lbPqVwNrAN6zM83MdEyuKX2XZIJI/?imgmax=800&quot; width=&quot;552&quot; height=&quot;380&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Now that the compilation outputs to our build artifacts folder we can make a psake task that finds all the test assemblies in “build_artifacts\Debug\Tests” and runs them with NUnit:&lt;/p&gt;&lt;pre class=&quot;brush: ps;wrap-lines: false&quot;&gt;properties {
    $base_dir = resolve-path .\..
    $source_dir = &quot;$base_dir\src&quot;
    $build_artifacts_dir = &quot;$base_dir\build_artifacts&quot;
    $tools_dir = &quot;$base_dir\tools&quot;
    $config = &quot;Debug&quot;
    $test_dir = &quot;$build_artifacts_dir\$config\Tests&quot;
}

task test {    
    $testassemblies = get-childitem $test_dir -recurse -include *tests*.dll
    exec { 
        &amp;amp; $tools_dir\NUnit-2.5.10\nunit-console-x86.exe $testassemblies /nologo /nodots /xml=$test_dir\tests_results.xml; 
    }
}
&lt;/pre&gt;
&lt;p&gt;Here I have defined some extra properties to make the script more readable and maintainable. We now have to remember to make the “local” task dependent on “test”. Let’s also add a “clean” task that deletes the build artifacts folder and recreates it:&lt;/p&gt;&lt;pre class=&quot;brush: ps;wrap-lines: false&quot;&gt;task clean {
    rd $build_artifacts_dir -recurse -force  -ErrorAction SilentlyContinue | out-null
    mkdir $build_artifacts_dir  -ErrorAction SilentlyContinue  | out-null
}
&lt;/pre&gt;
&lt;p&gt;Our build script now loos like this:&lt;/p&gt;&lt;pre class=&quot;brush: ps;wrap-lines: false&quot;&gt;$framework = &#39;4.0&#39;

properties {
    $base_dir = resolve-path .\..
    $source_dir = &quot;$base_dir\src&quot;
    $build_artifacts_dir = &quot;$base_dir\build_artifacts&quot;
    $tools_dir = &quot;$base_dir\tools&quot;
    $config = &quot;Debug&quot;
    $test_dir = &quot;$build_artifacts_dir\$config\Tests&quot;
}

task default -depends local
 
task local -depends compile, test

task compile -depends clean {
    exec { msbuild  $source_dir\ContinuousDelivery.sln /t:Clean /t:Build /p:Configuration=$config /v:q /nologo }
}

task clean {
    rd $build_artifacts_dir -recurse -force  -ErrorAction SilentlyContinue | out-null
    mkdir $build_artifacts_dir  -ErrorAction SilentlyContinue  | out-null
}

task test {    
    $testassemblies = get-childitem $test_dir -recurse -include *tests*.dll
    exec { 
        &amp;amp; $tools_dir\NUnit-2.5.10\nunit-console-x86.exe $testassemblies /nologo /nodots /xml=$test_dir\tests_results.xml; 
    }
}
&lt;/pre&gt;
&lt;p&gt;If we run build.bat we now get the following output:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0xIew6LX0C073_UzwSI92wzxRwIrOmeF46hVGcNPb7tH4gqirt1Regt0iDe8eXBlhTuB8yG9TqED9U8xk_o8xMvlCB8u3ANjzj6v2UXSv0rZuO_eqCOZKh9-_BLfdvtZsEmb01tLqhNU/s1600-h/image%25255B19%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXBo-6oXcg8ANxGuCEY88D0CLso7Or3SrqQjxPx75sfAvrukW9qKJW5wlCucvngReXcX8TUYvkaHsyjbT5XgQd7iuXGRHijiTWfZy9DEwXFCqTBoVHzE3ywfu0STm1D_XmYrYoyVdfcGA/?imgmax=800&quot; width=&quot;531&quot; height=&quot;371&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We have now successfully run our tests with psake! This concludes how you can create a local build with psake. There might more to this than what I’ve shown, but I think this should be enough to get you going.&lt;/p&gt;
&lt;p&gt;You can download the source code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part2&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4790208517726897501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4790208517726897501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4790208517726897501'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-2.html' title='Creating a Local Build with psake, Part 2: Testing'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQiVInVHDcW97DbGB9L-QwdpnLSaafo5W0wj-C4NZ-a0sSYwD7NZHpBcalDMXH3nZWGtApjqF6-6wyQyEzkE0gXaYJviDK1w4JgrLsaMevefO33_yE-HcE22EYdvqkQJgGV2VjHXGFZI/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-9040645125566855564</id><published>2011-09-02T13:05:00.001+02:00</published><updated>2011-09-02T16:34:28.153+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Build"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Delivery"/><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell"/><category scheme="http://www.blogger.com/atom/ns#" term="psake"/><title type='text'>Creating a Local Build With psake, Part 1: Compiling</title><content type='html'>&lt;p&gt;Often there is more to building a solution than just compiling with Visual Studio. If you’re strict about your &lt;a href=&quot;http://en.wikipedia.org/wiki/Continuous_integration&quot;&gt;Continuous Integration&lt;/a&gt; process you’d probably want to make sure that the solution compiles, migration of the database doesn’t fail (if you have one), all the tests are green etc before you check in. For this reason I like to create a local build, something very similar to the build running on a CI server. My preferred choice for build automation is &lt;a href=&quot;https://github.com/psake/psake&quot;&gt;psake&lt;/a&gt;, a tool written in PowerShell. “It avoids the angle-bracket tax associated with executable XML by leveraging the PowerShell syntax in your build scripts.” Since PowerShell is a programming language in itself you can pretty much do everything you would possibly like, including integration with the .NET Framework. &lt;/p&gt; &lt;p&gt;Now, let’s compile our solution with psake. &lt;/p&gt; &lt;p&gt;Assuming that I have the following folder structure.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggrWcoJCtafZg4gMXZZpfYCTErMKyXOEt-uw_WHjBv_idwVpK9q-yN4uENVxYlbwY_cGhdjFX4Jln3MIrwaWDv7pN6v7yP8oewGFEVK5Adx6yCDQWRP3OdHklDi4KZKM9iZwadRC_AcsQ/s1600-h/image%25255B2%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-M7hGL-v6PRMYlRxKKaGZbagrfDVT4abtcmCDL8-zc7qLvUboFLtz7k3Tm6ddhapN-glgCfo4rXP0RWvsOzhQOzEl8t8ycaoRvpgUEH9EkAMBjfHFm1GcvBmOeD-0RcwYNGDe2rVBbSo/?imgmax=800&quot; width=&quot;123&quot; height=&quot;113&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Download psake from &lt;a href=&quot;https://github.com/psake/psake/zipball/master&quot;&gt;https://github.com/psake/psake/zipball/master&lt;/a&gt; and put the content (just the files) in \tools\psake\ . There is a bug in the current version of psake where it’s not possible to set framework version through $framework global variable in the build script. You therefore have to edit \tools\psake\psake.ps1 and set line 13 to:&lt;pre class=&quot;brush: ps;&quot;&gt;[string]$framework = &#39;4.0&#39;
&lt;/pre&gt;
&lt;p&gt;if you have a .NET 4.0 solution.&lt;/p&gt;
&lt;p&gt;Create a file called build.ps1 in the build folder and include this in the file:&lt;/p&gt;&lt;pre class=&quot;brush: ps;wrap-lines: false;&quot;&gt;$framework = &#39;4.0&#39;

properties {
    $base_dir = resolve-path .\..
    $source_dir = &quot;$base_dir\src&quot;
    $config = &quot;Debug&quot;
}

task default -depends local
 
task local -depends compile

task compile {
    exec { msbuild  $source_dir\ContinuousDelivery.sln /t:Clean /t:Build /p:Configuration=$config /v:q /nologo }
}
&lt;/pre&gt;
&lt;p&gt;With psake you can set up tasks with dependencies between them. If you run this with psake without specifying a task it will run the “default” task. As you can see I have created a task “local” in which “default” is dependent on. “local” is then dependent on the task “compile” where we call out to msbuild to actually do the compilation. The call is wrapped in an exec-function defined by psake. If the command line program we call out to fails, psake will automatically throw an exception and fail the build.&lt;/p&gt;
&lt;p&gt;To make it easier to run the build script I like to wrap the invocation in a simple bat-file called build.bat at the root of the project:&lt;/p&gt;&lt;pre class=&quot;brush: bash;wrap-lines: false;&quot;&gt;@echo off
powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command &quot;&amp;amp; { .\tools\psake\psake .\build\build.ps1 %*; if ($lastexitcode -ne 0) {write-host &quot;ERROR: $lastexitcode&quot; -fore RED; exit $lastexitcode} }&quot; 
pause
&lt;/pre&gt;
&lt;p&gt;Now, open a command line and navigate to your project directory and run build.bat:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi85v5xzCNL-zATXUNiYntQRNonUMhsl2aKO9Tq4EQaAlcBY8K6xR7M7RWwFtKozMxWKBtnYbUXw58z3SUapQNgoTV-bIzVdzKZOVWKGqW_V4D6z0If0ojjweInOZ1HFmSJ1_J0Zn3rYlI/s1600-h/image%25255B6%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_nuViZe9doQs7g3dLjjUsDrTgSisexRGelrd5fOMhOB3KND5KGfPIWyh7PEkZNYWLHO-8V_ErJCJX-CKadwyQScWHhbAg6Qj_fy_9vfgjlmsKN1GXyTmWK_z0pkULaKf6dW7jkWlpsgY/?imgmax=800&quot; width=&quot;555&quot; height=&quot;374&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You’ve compiled your solution with psake.&lt;/p&gt;
&lt;p&gt;You can download the source code from &lt;a href=&quot;https://github.com/kvarv/Continuous-Delivery/tree/part1&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/9040645125566855564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/9040645125566855564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/9040645125566855564'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2011/09/creating-local-build-with-psake-part-1.html' title='Creating a Local Build With psake, Part 1: Compiling'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-M7hGL-v6PRMYlRxKKaGZbagrfDVT4abtcmCDL8-zc7qLvUboFLtz7k3Tm6ddhapN-glgCfo4rXP0RWvsOzhQOzEl8t8ycaoRvpgUEH9EkAMBjfHFm1GcvBmOeD-0RcwYNGDe2rVBbSo/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-2643746838512265885</id><published>2010-03-29T15:18:00.005+02:00</published><updated>2011-09-01T19:46:52.519+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="BDD"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><title type='text'>A simple BDD “framework”</title><content type='html'>Last month I held a WPF presentation at work where I created a ViewModel class doing TDD. This got a little buzz because of the way I integrated BDD concepts in the tests. I have since then recieved a few question about how I actually did it. Let’s first have a look at what I did:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; highlight: [3,10,19,24,30];wrap-lines: false;&quot;&gt;namespace Specifications_for_customer_search
{
    [Scenario]
    public class When_user_searches_for_customers : ScenarioBase
    {
        private RhinoAutoMocker&amp;lt;CustomerSearchViewModel&amp;gt; _mocks;
        private List&amp;lt;Customer&amp;gt; _customers;
        private string _customerName;

        public override void Given()
        {
            _mocks = new RhinoAutoMocker&amp;lt;CustomerSearchViewModel&amp;gt;();
            _customerName = &quot;goran&quot;;
            _customers = new List&amp;lt;Customer&amp;gt; { new Customer(_customerName) };
            _mocks.Get&amp;lt;ICustomerRepository&amp;gt;().Stub(me =&amp;gt; me.FindCustomerByName(Arg&amp;lt;string&amp;gt;.Is.Anything)).Return(_customers);
            
        }

        public override void When()
        {
            _mocks.ClassUnderTest.SearchCommand.Execute(_customerName);
        }

        [Then]
        public void should_query_customer_repository_for_matching_customers()
        {
            _mocks.Get&amp;lt;ICustomerRepository&amp;gt;().AssertWasCalled(me =&amp;gt; me.FindCustomerByName(_customerName));
        }

        [Then]
        public void should_list_customers_found()
        {
            Assert.That(_mocks.ClassUnderTest.Customers, Is.EqualTo(_customers));
        }
    }
}&lt;/pre&gt;
This was all done by using the base class from my &lt;a href=&quot;http://gorankvarv.blogspot.com/2009/10/aaa-style-bdd-specification-base-class.html&quot;&gt;previous post&lt;/a&gt; and renaming &lt;em&gt;Arrange&lt;/em&gt; and &lt;em&gt;Assert&lt;/em&gt; to &lt;em&gt;Given&lt;/em&gt; and &lt;em&gt;When&lt;/em&gt;. In this example I used &lt;a href=&quot;http://www.nunit.org/&quot;&gt;NUnit&lt;/a&gt;, so I inherited from NUnit’s test attributes:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;public class ThenAttribute : TestAttribute{}
public class ScenarioAttribute : TestFixtureAttribute { }&lt;/pre&gt;
That was all. Happy testing! :)</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/2643746838512265885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2010/03/simple-bdd-framework.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/2643746838512265885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/2643746838512265885'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2010/03/simple-bdd-framework.html' title='A simple BDD “framework”'/><author><name>Gøran Sveia Kvarv</name><uri>http://www.blogger.com/profile/08537541145852324311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGILKj57Wt5vjlvT6aXTWTS1yZoW4FQZEyDrU730cKCbw9YN7uxpsXJV4eaF9Hlm6b4RhAmXcFS006fNeKYRS_btrX6mlfJQKh-tDLivti47PFPLxqq1poC60Dskp1Tg/s113/G%2525C3%2525B8ran%252BSveia%252BKvarv_jpg.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-3767131325844087091</id><published>2009-10-24T19:35:00.005+02:00</published><updated>2009-10-26T14:44:21.542+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="BDD"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>An AAA style BDD specification base class</title><content type='html'>&lt;p&gt;Lately I have written a lot of Arrange, Act, Assert style tests using &lt;a href=&quot;http://www.ayende.com/projects/rhino-mocks.aspx&quot;&gt;Rhino Mocks&lt;/a&gt;. I’ve also started to write more readable tests with a dash of BDD style naming like this:&lt;/p&gt;  &lt;pre class=&quot;brush: csharp; wrap-lines: false&quot;&gt;[Fact]
public void Should_find_projects_when_user_searches()
{
 //Arrange
 var projectRepository = MockRepository.GenerateMock&amp;lt;IProjectRepository&amp;gt;();
 var projects = new List&amp;lt;Project&amp;gt; { ProjectMother.CreateProject(&quot;project 1&quot;), ProjectMother.CreateProject(&quot;project 2&quot;) };
 projectRepository.Stub(me =&amp;gt; me.FindByName(null)).IgnoreArguments().Return(projects);
 var presentationModel = new ProjectSearchPresentationModel(projectRepository);
 //Act
 presentationModel.SearchCommand.Execute(&quot;&quot;);
 //Assert
 projectRepository.AssertWasCalled(me =&amp;gt; me.FindByName(&quot;&quot;));
 Assert.Equal(projects.Count, presentationModel.Projects.Count);
}&lt;/pre&gt;

&lt;p&gt;The scenario for this test is “When the user searches”. If we look closely we see that it have two asserts. When the user searches it should ask the repository for projects and the result should be “displayed” in a list. This feels a bit odd. I have to create a name for the test that captures everything that has to be done when the user searches. This is hard and I’m likely to loose some of the intent. The solution is to split the test in a test for every assert. However, this means that I have to set up each test in an equal manner and call the serach command. This is DRY! To solve this I’ve created a test base class called Specification that enables me to write the above test like this:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp; wrap-lines: false&quot;&gt;namespace Specifications_for_project_search_presentation_model
{
 public class When_user_searches_for_projects : Specification
 {
     private ProjectSearchPresentationModel _presentationModel;
     private List&amp;lt;Project&amp;gt; _projects;
     private IProjectRepository _projectRepository;

     public override void Arrange()
     {
         _projectRepository = MockRepository.GenerateMock&amp;lt;IProjectRepository&amp;gt;();
         _projects = new List&amp;lt;Project&amp;gt; { ProjectMother.CreateProject(&quot;project 1&quot;), ProjectMother.CreateProject(&quot;project 2&quot;) };
         _projectRepository.Stub(me =&amp;gt; me.FindByName(null)).IgnoreArguments().Return(_projects);
         _presentationModel = new ProjectSearchPresentationModel(_projectRepository);
     }

     public override void Act()
     {
         _presentationModel.SearchCommand.Execute(&quot;&quot;);         
     }

     [Fact]
     public void should_search_repository()
     {
         _projectRepository.AssertWasCalled(me =&amp;gt; me.FindByName(&quot;&quot;));         
     }

     [Fact]
     public void should_show_result()
     {
         Assert.True(_presentationModel.CanShowProjects);
     }

     [Fact]
     public void should_list_projects_found()
     {
         Assert.Equal(_projects.Count, _presentationModel.Projects.Count);
     }
 }
}&lt;/pre&gt;

&lt;p&gt;I have now set up the context and called the search command only once, but have a seperate test for each assert. I think these kind of tests read nicely. I have a test class for each scenario and tests that reads like the specification for the scenario. This also look very good in &lt;a href=&quot;http://www.jetbrains.com/resharper/&quot;&gt;ReSharper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEEvpq_D74onQ1OQ61EnK1-oY5r92JJguIcwvH6L7rHmUhgQGMFl-qA49OTWB7_exg9q-0L5KkGQ3eUVeHVr8fy1rIOsV5aCD4YVIK3RnhkpEnHdSjsQUc9Q7nlOLax-hjkNIlszqq1jJv/s1600-h/specifications%5B3%5D.png&quot;&gt;&lt;img style=&quot;border-width: 0px; display: inline;&quot; title=&quot;specifications&quot; alt=&quot;specifications&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge0vKP9jg_cwGYXBo3O_8HstxmR7fCfv6qYp0ZEkIWy4u5w4I5xxlpvFluMpj7jfmvl9KmdWYQ9DVJ14Tc0Fs-4KZUsPmMyPKXrurBYHwO0SjUd8b1dF8xeV9dRbDTzalZLd1ETFHpU_us/?imgmax=800&quot; border=&quot;0&quot; height=&quot;99&quot; width=&quot;450&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The base class is implemented like this for &lt;a href=&quot;http://www.codeplex.com/xunit&quot;&gt;xUnit&lt;/a&gt;:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp; wrap-lines: false&quot;&gt;public abstract class Specification
{
 protected Specification()
 {
     Arrange();
     Act();
 }

 public abstract void Arrange();
 public abstract void Act();
}&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/3767131325844087091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2009/10/aaa-style-bdd-specification-base-class.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/3767131325844087091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/3767131325844087091'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2009/10/aaa-style-bdd-specification-base-class.html' title='An AAA style BDD specification base class'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge0vKP9jg_cwGYXBo3O_8HstxmR7fCfv6qYp0ZEkIWy4u5w4I5xxlpvFluMpj7jfmvl9KmdWYQ9DVJ14Tc0Fs-4KZUsPmMyPKXrurBYHwO0SjUd8b1dF8xeV9dRbDTzalZLd1ETFHpU_us/s72-c?imgmax=800" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-8789471782215302914</id><published>2009-06-09T20:26:00.005+02:00</published><updated>2011-09-01T21:00:04.661+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Architecture"/><category scheme="http://www.blogger.com/atom/ns#" term="Client Architecture"/><title type='text'>.NET RIA Services is for RAD only!</title><content type='html'>&lt;p&gt;A bit late to comment, but .NET RIA Services was announced at MIX09. I recently spent some minutes to see what the fuzz was all about. &lt;/p&gt;  &lt;p&gt;.NET RIA Services is a framework proclaimed for Line of Business development which is supposed to make it easy to build N-tier application. The framework makes it easy to expose your domain logic on the server to the client, with validation, authorization, querying and so on. You do this by defining a DomainService like this (taken from the &lt;a href=&quot;http://code.msdn.microsoft.com/RiaServices/Release/ProjectReleases.aspx?ReleaseId=2420&quot;&gt;RIA Services Overview&lt;/a&gt;):&lt;/p&gt;  
&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;[EnableClientAccess()]
public class CityService : DomainService
{
  private CityData _cityData = new CityData();
  public IEnumerable&amp;lt;City&amp;gt; GetCities()
  {
      return _cityData.Cities;
  }
}&lt;/pre&gt;The EnableClientAccess attribute exposes proxies of your entities to the client by code generation. It also generates client access to your operations. &lt;p&gt;Sounds intriguing? Not really. I wouldn’t have an enterprise application rely so much on magic, but hey, it could maybe be done..&lt;/p&gt;&lt;p&gt;As you can see from the service, an entity called City is exposed to client:&lt;/p&gt;&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;public partial class City
{
  [Key]
  public string Name { get; set; }
  [Key]
  public string State { get; set; }
}&lt;/pre&gt;&lt;p&gt;Why is the class partial you wonder..? As I said the framwork lets you validate your domain logic both on the server and client. To be able to do this you have to create a metadata class, also known as a buddy class:&lt;/p&gt;&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;[MetadataType(typeof(CityMetadata))]
public partial class City
{
  internal sealed class CityMetadata
  {
      [Required]
      public string Name;

      [Required]
      [StringLength(2, MinimumLength = 2)]
      public string State;
  }
}&lt;/pre&gt;Metadata classes provide a way to attach metadata to an entity without actually modifying the corresponding members on the entity itself. When you generate the client proxy you also get the validation attributes.

Sounds intriguing? Not in my wildest dreams. To get validation you actually have to repeat every property of City. This is as DRY as it can possible get. Add the shared code functionality to the soup and you have yourself a maintainability nightmare.

.NET RIA Services is for RAD only; prototypes and applications that never reach a satisfactory production quality. I would never ever use this in a production system.</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/8789471782215302914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2009/06/net-ria-services-is-for-rad-only.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/8789471782215302914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/8789471782215302914'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2009/06/net-ria-services-is-for-rad-only.html' title='.NET RIA Services is for RAD only!'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-9106469272328881393</id><published>2009-02-12T13:33:00.010+01:00</published><updated>2011-09-01T21:03:34.408+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Client Architecture"/><category scheme="http://www.blogger.com/atom/ns#" term="Presentation Model"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>WPF and the Presentation Model Pattern</title><content type='html'>&lt;p&gt;Over the last 6 months I&#39;ve been working on a several projects where we have used &lt;a href=&quot;http://msdn.microsoft.com/en-us/netframework/aa663326.aspx&quot;&gt;Windows Presentation Foundation&lt;/a&gt; as our technology for creating GUI. When we started I began looking for presentation pattern that would best utilize the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms752347.aspx&quot;&gt;Data Binding&lt;/a&gt; capabilities in WPF and and at the same time could best interact with my domain model. In search for a suitable pattern I came across the &lt;a href=&quot;http://martinfowler.com/eaaDev/PresentationModel.html&quot;&gt;Presentation Model&lt;/a&gt; by &lt;a href=&quot;http://martinfowler.com/&quot;&gt;Martin Fowler&lt;/a&gt;.

The Presenation Model, aka Application Model, aka Model-View-ViewModel pattern pulls the state and behavior of the view out into a model class that is part of the presentation layer. Since the presentation model holds the data that the view is going to render, there needs to be some kind of synchronization between the two. Based on the behaviour of the view, the presentation model changes it&#39;s state and automatically updates the view through Data Binding. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5vZ-3F3lpVVfWsM2CNQ6bC1ZuNWKuSzcMf9Mrl3LJehTEmEuGZL0ZuP8ocOhL-do0khsWiXQvu73KdcowaEHhKbDqgnIcxJ-73DZRrdapE1duSm0FvQydNfEKnvAw1_dNIQq5Z6-z9Lga/s1600-h/guiarch%5B9%5D.png&quot;&gt;&lt;img title=&quot;guiarch&quot; style=&quot;border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;&quot; alt=&quot;guiarch&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoQ0DFN8rNoNJm2V_hdbds5uyF0LowGY3aigKXhIIpKw-c54eYX27oJn42NxGT7065gX4Sa-0cD_qV_DXzK50v9haq-aaTD5I6vHbmhyphenhyphenRi83zrEjeHFRxXiwP3a6D-ELrPbVXGs6sHFrGR/?imgmax=800&quot; border=&quot;0&quot; width=&quot;401&quot; height=&quot;547&quot; /&gt;&lt;/a&gt;
One can look at the view as a projection of the data in the Presentation Model. The Presentation Model has poperties for the information in the view and properties for state, typically disabling/enabling of buttons based on the current state of the view. The Presentation Model interacts with and updates the domain model through its properties. The following code illustates a typical presentation model for a project search view (in the context of my standard scrum application):&lt;/p&gt;  &lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;public class ProjectSearchPresentationModel : PresentationModel
{
private List&amp;lt;Project&amp;gt; mProjects = new List&amp;lt;Project&amp;gt;();
private DelegateCommand&amp;lt;string&amp;gt; mSearchCommand;

private DelegateCommand&amp;lt;Project&amp;gt; mSelectCommand;

public DelegateCommand&amp;lt;string&amp;gt; SearchCommand
{
 get
 {
     if (mSearchCommand == null)
         mSearchCommand = new DelegateCommand&amp;lt;string&amp;gt;(FindProjects);
     return mSearchCommand;
 }
}

public DelegateCommand&amp;lt;Project&amp;gt; SelectCommand
{
 get
 {
     if (mSelectCommand == null)
         mSelectCommand = new DelegateCommand&amp;lt;Project&amp;gt;(SelectProject);
     return mSelectCommand;
 }
}

public List&amp;lt;Project&amp;gt; Projects
{
 get { return mProjects; }
 set
 {
     mProjects = value;
     this.Notify(() =&amp;gt; Projects);
     this.Notify(() =&amp;gt; CanShowProjects);
 }
}

public bool CanShowProjects
{
 get { return Projects.Count() &amp;gt; 0; }
}

public void FindProjects(string searchText)
{
 var repository = IoC.Get&amp;lt;IProjectRepository&amp;gt;();
 Projects = repository.Query(project =&amp;gt; project.Name == searchText);
}


public void SelectProject(Project project)
{
 ApplicationController.Instance.SelectProject(project);
}

public override void Refresh()
{
}
}&lt;/pre&gt;
In the code behind of my view I instantiate a new ProjectSearchPresentationModel and set the DataContext of the view to my presentation model object:

&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;public partial class ProjectSearchView : IView
{
private PresentationModel mPresentationModel;

public void Init()
{
 InitializeComponent();
 mPresentationModel = new ProjectSearchPresentationModel();
 DataContext = mPresentationModel;
}
}&lt;/pre&gt;
The view now binds to the Projects property of the ProjectSearchPresentationModel and displays a list of Project objects based on the search criteria:

&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;&amp;lt;StackPanel&amp;gt;
&amp;lt;Label Content=&quot;Enter customer name&quot; /&amp;gt;
&amp;lt;StackPanel Orientation=&quot;Horizontal&quot;&amp;gt;
 &amp;lt;TextBox Name=&quot;searchText&quot; Width=&quot;100&quot; /&amp;gt;
 &amp;lt;Button Command=&quot;{Binding .SearchCommand}&quot; CommandParameter=&quot;{Binding Text, ElementName=searchText}&quot; Margin=&quot;5,0,0,0&quot; Content=&quot;Search&quot; /&amp;gt;
&amp;lt;/StackPanel&amp;gt;
&amp;lt;/StackPanel&amp;gt;

&amp;lt;ListView Grid.Row=&quot;1&quot; ItemsSource=&quot;{Binding .Projects}&quot; Visibility=&quot;{Binding .CanShowProjects, Converter={StaticResource boolConverter}}&quot;&amp;gt;
&amp;lt;ListView.View&amp;gt;
 &amp;lt;GridView&amp;gt;
     &amp;lt;GridViewColumn Header=&quot;Action&quot;&amp;gt;
         &amp;lt;GridViewColumn.CellTemplate&amp;gt;
             &amp;lt;DataTemplate&amp;gt;
                 &amp;lt;Label&amp;gt;
                     &amp;lt;Hyperlink Command=&quot;{Binding RelativeSource={RelativeSource AncestorType={x:Type Views:IView}}, Path=DataContext.SelectCommand}&quot; CommandParameter=&quot;{Binding .}&quot;&amp;gt;Select&amp;lt;/Hyperlink&amp;gt;
                 &amp;lt;/Label&amp;gt;
             &amp;lt;/DataTemplate&amp;gt;
         &amp;lt;/GridViewColumn.CellTemplate&amp;gt;
     &amp;lt;/GridViewColumn&amp;gt;
     &amp;lt;GridViewColumn Header=&quot;Name&quot;&amp;gt;
         &amp;lt;GridViewColumn.CellTemplate&amp;gt;
             &amp;lt;DataTemplate&amp;gt;
                 &amp;lt;Label Content=&quot;{Binding .Name}&quot; /&amp;gt;
             &amp;lt;/DataTemplate&amp;gt;
         &amp;lt;/GridViewColumn.CellTemplate&amp;gt;
     &amp;lt;/GridViewColumn&amp;gt;
 &amp;lt;/GridView&amp;gt;
&amp;lt;/ListView.View&amp;gt;
&amp;lt;/ListView&amp;gt;&lt;/pre&gt;
Note that I’m not using any event handlers in the code behind of the view. Instead I’m binding to Command properties defined in the ProjectSearchPresentationModel, which is hooked up to methods in the presentation model:

&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;&amp;lt;Button Command=&quot;{Binding .SearchCommand}&quot;
 CommandParameter=&quot;{Binding Text, ElementName=searchText}&quot;
 Margin=&quot;5,0,0,0&quot;
 Content=&quot;Search&quot; /&amp;gt;&lt;/pre&gt;&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;public DelegateCommand&amp;lt;string&amp;gt; SearchCommand
{
get
{
 if (mSearchCommand == null)
     mSearchCommand = new DelegateCommand&amp;lt;string&amp;gt;(FindProjects);
 return mSearchCommand;
}
}

public void FindProjects(string searchText)
{
var repository = IoC.Get&amp;lt;IProjectRepository&amp;gt;();
Projects = repository.Query(project =&amp;gt; project.Name == searchText);
}&lt;/pre&gt;
The generic DelegateCommand is a class that implements the ICommand interface and is similar to the DelegateCommand found in the &lt;a href=&quot;http://www.codeplex.com/CompositeWPF&quot;&gt;Prism framework&lt;/a&gt;. With commands I can keep the code behind of the view almost free from code.

In my opinion the Presentation Model pattern is extremely powerful in combination with WPF. I find it both effective and easy to work with and lets me seperate the view from the domain model in an elegant way, which in turn makes it easy to test the view. This is how I do it. Stay tuned for more!

&lt;iframe style=&quot;border: 1px solid rgb(221, 229, 233); margin: 3px; padding: 0px; width: 240px; height: 66px; background-color: rgb(255, 255, 255);&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; src=&quot;http://cid-4789d399860c57c7.skydrive.live.com/embedrowdetail.aspx/Code/ScrumApplication12022009.zip&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/9106469272328881393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2009/02/wpf-and-presentation-model-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/9106469272328881393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/9106469272328881393'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2009/02/wpf-and-presentation-model-pattern.html' title='WPF and the Presentation Model Pattern'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoQ0DFN8rNoNJm2V_hdbds5uyF0LowGY3aigKXhIIpKw-c54eYX27oJn42NxGT7065gX4Sa-0cD_qV_DXzK50v9haq-aaTD5I6vHbmhyphenhyphenRi83zrEjeHFRxXiwP3a6D-ELrPbVXGs6sHFrGR/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4193154792959041954</id><published>2008-12-21T20:23:00.043+01:00</published><updated>2011-09-01T20:50:19.709+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DSL"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Test Data Builder</title><content type='html'>&lt;p&gt;In every project you reach a point where you need test data for unit testing. Having a reasonably complex domain model can make this task &quot;difficult&quot; because testing an entity in many cases means that you also have to setup associations to other entities. Intializing objects per test is cumbersome and any changes to constructor arguments will break your tests. One of the solutions to this problem is to use the &lt;a href=&quot;http://martinfowler.com/bliki/ObjectMother.html&quot;&gt;Object Mother pattern&lt;/a&gt;. It&#39;s basically a class with factory methods that helps you setup an object for testing. The object creation code is moved out of the tests so that it can be reused and making the test data more maintainable. So if you are developing a scrum application and want to create a project with a sprint and a user story you would do something like this:
&lt;/p&gt;
&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;
public static class ProjectMother
{
 public static Project CreateProjectWithSprint()
 {
     Project project = new Project();
     Sprint sprint = new Sprint();
     UserStory userStory = new UserStory();
     userStory.Name = &quot;User story&quot;;
     userStory.StoryPoints = 8;
     sprint.AddUserStory(userStory);
     project.AddSprint(sprint);
     return project;
 }
}

Project project = ProjectMother.CreateProjectWithSprintAndUserStories();
&lt;/pre&gt;
However as time goes by you end up with a lot of factory methods for the slightest variation in the test data beacuse of the heavy coupling that exists since many tests use the same method. This make the Object Mother class hard to maintain. To solve this problem I usually write a fluent interface (embedded domain specific language) that I use to initalize my objects for testing. This is heavily based on the &lt;a href=&quot;http://martinfowler.com/dslwip/ExpressionBuilder.html&quot;&gt;Expression Builder pattern&lt;/a&gt;. For each class I want to test I write a builder for that class. So when I want to create a Project object I just write:
&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;
Project project = ProjectBuilder.Create.Project
              .WithName(&quot;Test Project&quot;)
              .WithSprint(SprintBuilder.Create.Sprint
                  .WithName(&quot;Sprint 1&quot;)
                  .WithUserStory(UserStoryBuilder.Create.UserStory
                      .WithName(&quot;Story 1&quot;)
                      .WithStoryPoints(13)
                      .WithTask(TaskBuilder.Create.Task
                          .WithName(&quot;Task 1&quot;)
                          .WithHours(3))));
&lt;/pre&gt;&lt;p&gt; &lt;/p&gt;Behind the scenes the ProjectBuilder takes care of everything adding sprints and so on. In each method the builder just returns itself after having done some setup on the private Project instance. The ProjectBuilder is finally casted to Project using an implicit cast operator which returns the private Project instance.

&lt;pre class=&quot;brush: csharp; wrap-lines: false;&quot;&gt;
public class ProjectBuilder
{
 private static Project mProject;

 public static ProjectBuilder Create
 {
     get { return new ProjectBuilder(); }
 }

 public ProjectBuilder WithName(string name)
 {
     mProject.Name = name;
     return this;
 }

 public ProjectBuilder Project
 {
     get
     {
         mProject = new Project { Name = &quot;Test Project&quot; };
         return this;
     }
 }

 public ProjectBuilder WithSprint(Sprint sprint)
 {
     mProject.AddSprint(sprint);
     return this;
 }

 public ProjectBuilder WithBacklog(Backlog backlog)
 {
     mProject.Backlog = backlog;
     return this;
 }

 public static implicit operator Project(ProjectBuilder builder)
 {
     return mProject;
 }

}
&lt;/pre&gt;

Still, I don&#39;t feel that the Object Mother and the Builder are mutually exclusive. If I have a lot of tests that use the same test data I often create an Object Mother with a factory method that uses the builders. When I need a specialized initialization of an object for a test I just use the builders directly in my tests. &lt;p&gt;I find this way of creating test data really useful and hopefully you do too! Feel free to download and use the code. The builders are located in the tests project.&lt;/p&gt;&lt;p&gt;Merry Christmas!!&lt;/p&gt;
&lt;iframe style=&quot;border: 1px solid rgb(221, 229, 233); margin: 3px; padding: 0px; width: 240px; height: 66px; background-color: rgb(255, 255, 255);&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; src=&quot;http://cid-4789d399860c57c7.skydrive.live.com/embedrowdetail.aspx/Code/ScrumApplication.zip&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4193154792959041954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/12/test-data-builder.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4193154792959041954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4193154792959041954'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/12/test-data-builder.html' title='Test Data Builder'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-1421040546413563378</id><published>2008-11-20T23:17:00.001+01:00</published><updated>2008-12-15T19:18:19.133+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Presentation at NNUG Vestfold</title><content type='html'>Last night I held a presentation at &lt;a href=&quot;http://www.nnug.no/Avdelinger/Vestfold/&quot;&gt;NNUG Vestfold&lt;/a&gt;. I primarily held demos showing usage of Dependency Properties, Attached Dependency Properties and ControlTemplates in WPF.

&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguQZ8umezyu1WFHChZD8KqK-o1cbUNcm244SpTOGcAg6UogbQjMy2pbJnk2RWoOZtP-Af0Wy_gtyk2noyq1KYJmLrAmWYKG9YqLuuHUaruzpBxtgKe9Tsp14IyOad-unJCYnYS8EiKt_wu/s1600-h/nnug.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 501px; height: 366px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguQZ8umezyu1WFHChZD8KqK-o1cbUNcm244SpTOGcAg6UogbQjMy2pbJnk2RWoOZtP-Af0Wy_gtyk2noyq1KYJmLrAmWYKG9YqLuuHUaruzpBxtgKe9Tsp14IyOad-unJCYnYS8EiKt_wu/s400/nnug.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5270885405498869426&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;iframe marginheight=&quot;0&quot; marginwidth=&quot;0&quot; style=&quot;border: 1px solid rgb(221, 229, 233); margin: 3px; padding: 0pt; width: 240px; height: 66px; background-color: rgb(255, 255, 255);&quot; src=&quot;http://cid-4789d399860c57c7.skydrive.live.com/embedrowdetail.aspx/Code/NNUGvestfold.zip&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/1421040546413563378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/11/presentation-at-nnug-vestfold.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/1421040546413563378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/1421040546413563378'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/11/presentation-at-nnug-vestfold.html' title='Presentation at NNUG Vestfold'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguQZ8umezyu1WFHChZD8KqK-o1cbUNcm244SpTOGcAg6UogbQjMy2pbJnk2RWoOZtP-Af0Wy_gtyk2noyq1KYJmLrAmWYKG9YqLuuHUaruzpBxtgKe9Tsp14IyOad-unJCYnYS8EiKt_wu/s72-c/nnug.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-5868108199767902587</id><published>2008-09-10T21:37:00.007+02:00</published><updated>2008-09-11T00:15:07.214+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Boo"/><category scheme="http://www.blogger.com/atom/ns#" term="SharpDevelop"/><category scheme="http://www.blogger.com/atom/ns#" term="Vista 64-bit"/><title type='text'>Making SharpDevelop compile and debug Boo programs on a 64-bit machine</title><content type='html'>Recently I&#39;ve started looking at Boo. As of now the only decent development tool for Boo is SharpDevelop. BooLangStudio, a Visual Studio plugin, recently came out in an alpha release. However, at the moment it&#39;s way too immature.

Back to SharpDevelop... I&#39;m running a 64-bit version of Vista which resulted in some problems compiling and debugging Boo programs. Since the compiler (booc.exe) is marked to run on AnyCPU it will start as a 64-bit process. SharpDevelop runs as 32-bit only. Therefore it will use the 32-bit version of MSBuild which in turn picks up a 32-bit version of System.dll and passes this version too booc.exe. Unfortunately this means that the 64-bit booc.exe process will crash when it tries to load the 32-bit System.dll.

A solution to this is to use CorFlags to mark booc.exe as 32-bit only. However, this breaks the strong name so you&#39;ll have to resign it. Do the following:

&lt;ol&gt;&lt;li&gt;Open Visual Studio Command Prompt and run &lt;code&gt;CorFlags &quot;path\SharpDevelop\3.0\AddIns\AddIns\BackendBindings\BooBinding\booc.exe&quot; /32BIT+ /Force&lt;/code&gt;.

&lt;/li&gt;&lt;li&gt;Download boo.snk from &lt;a href=&quot;http://svn.codehaus.org/boo/boo/trunk/src/&quot;&gt;http://svn.codehaus.org/boo/boo/trunk/src/&lt;/a&gt;. Still in VS Command Prompt run &lt;code&gt;sn -R &quot;path\SharpDevelop\3.0\AddIns\AddIns\BackendBindings\BooBinding\booc.exe&quot; &quot;path\boo.snk&quot;&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;You can now build your Boo programs!!

A new problem suddenly arises when you try to debug your program. The debugger crashes because your program is compiled to run on AnyCPU. So the 32-bit only compatible debugger will launch a 64-bit program and crash. SharpDevelop suggests that you set the target cpu of your program to 32-bit. This is not possible to do; The only option is AnyCPU. So we&#39;ll have to hack some more:

&lt;ul&gt;&lt;li&gt;Open the property page of your project and go to the Build Events tab. In the Post-build event command line text box type &lt;code&gt;&quot;path\Microsoft.NET\SDK\v2.0 64bit\Bin\CorFlags.exe&quot; &quot;$(TargetPath)&quot; /32BIT+&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;Now build and debug your program.

Voila!!</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/5868108199767902587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/09/making-sharpdevelop-compile-and-run-boo.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5868108199767902587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/5868108199767902587'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/09/making-sharpdevelop-compile-and-run-boo.html' title='Making SharpDevelop compile and debug Boo programs on a 64-bit machine'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-3412044882627554795</id><published>2008-07-28T22:54:00.009+02:00</published><updated>2008-07-29T00:10:01.858+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Mockups"/><category scheme="http://www.blogger.com/atom/ns#" term="Prototypes"/><title type='text'>Balsamiq Mockups: Taking the evilness out of prototypes</title><content type='html'>Everyone that has heard Odd Helge Gravalid&#39;s presentation &lt;a href=&quot;http://www.smidig.no/smidig2007/talks/83&quot; target=&quot;_blank&quot;&gt;&quot;Gui prototyper Onde&quot;&lt;/a&gt; (GUI Prototypes Are Evil) knows why prototypes are evil shit. The main point is that proptypes create expectations about the functionality in the GUI that may not be fully implemented or may not be present at all, but it seems like it is. So what&#39;s wrong about that? Well, as  I recently experienced; A couple of weeks after you presented the prototype, when you actually have implemented the functionality, the customer&#39;s project manager says: &quot;What have you guys really been doing lately? This is nothing more than you showed me two weeks ago&quot;. And then you are in trouble. So the moral is that you should never make a prototype that actually looks like it&#39;s really implemented. It will most certainly backfire! 

Last Friday I came across this great GUI mockup tool called &lt;a href=&quot;http://www.balsamiq.com/products/mockups&quot; target=&quot;_blank&quot;&gt;Balsamiq Mockups&lt;/a&gt;. The tool makes it really easy to create mockups by using the more than 60 pre-built controls. The cool thing is that it looks like they&#39;re actually drawn by hand, &quot;so that people don&#39;t get attached to “that pretty color gradient”&quot;. This can certainly help us out not going in that prototype trap and rather let us concentrate on the important aspect of prototyping: Discussing functionality! 

Check it out:

&lt;object width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/aJTuFRaIi_g&amp;hl=en&amp;fs=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/aJTuFRaIi_g&amp;hl=en&amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/embed&gt;&lt;/object&gt;

You can even try it out &lt;a href=&quot;http://www.balsamiq.com/demos/mockups/Mockups.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;!</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/3412044882627554795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/07/balsamiq-mockups-taking-evilness-out-of.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/3412044882627554795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/3412044882627554795'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/07/balsamiq-mockups-taking-evilness-out-of.html' title='Balsamiq Mockups: Taking the evilness out of prototypes'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4600986294267392660</id><published>2008-07-28T21:53:00.002+02:00</published><updated>2008-07-29T23:49:59.345+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>70-502:  WPF Exam</title><content type='html'>It&#39;s been a long time since I&#39;ve blogged. What have I been up to lately? For the most part I&#39;ve been working and tried to enjoy the summer as much as possible. I&#39;ve also managed to pass the &lt;a href=&quot;http://www.microsoft.com/learning/en/us/exams/70-502.mspx&quot; target=&quot;_blank&quot;&gt;70-502 - Microsoft .NET Framework 3.5 – Windows Presentation Foundation Application Development exam&lt;/a&gt;. For the last month and a half I&#39;ve been working on a WPF project and I would recommend everyone that has done some work with WPF to give the exam a shot. It&#39;s actually quite easy.</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4600986294267392660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/07/70-502-windows-presentation-foundation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4600986294267392660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4600986294267392660'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/07/70-502-windows-presentation-foundation.html' title='70-502:  WPF Exam'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-6658345363383565043</id><published>2008-04-23T23:42:00.014+02:00</published><updated>2008-12-02T16:01:27.857+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Refactoring"/><title type='text'>Refactoring: Later? Continuously!</title><content type='html'>A couple of days ago I attended a meeting about refactoring. Some of the attendants were unfamiliar or felt unsecure about refactoring. One of the questions that arose was; &quot;When is it time to refactor? Is it a joint descision in the developer team that it&#39;s time to refactor or is it an independent descision?&quot; There is NEVER a special time for refactoring. You don&#39;t create a task that says refactoring. Refactoring goes hand in hand with coding and should be performed CONTINUOUSLY. ALWAYS. You should always take into account refactoring when estimating a task, if not you&#39;re in deep shit. The customers generally don&#39;t care if you build a house with duct tape, as long as it looks good enough. And they will certainly not pay for later changes not visible from the outside. But as a professional developer you know that the house will fall apart when the rainy day comes. So ALWAYS refactor and estimate accordingly!</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/6658345363383565043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/04/refactoring-later-never.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6658345363383565043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6658345363383565043'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/04/refactoring-later-never.html' title='Refactoring: Later? Continuously!'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-6509233538242576828</id><published>2008-04-22T23:10:00.023+02:00</published><updated>2008-10-21T01:00:14.096+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight"/><title type='text'>DataGrid revisited</title><content type='html'>Today I held a little presentation at work showing off some of the DataGrid capabilities in Silverlight 2.0 beta. It&#39;s basically based upon my last post, but I added some new functionality that shows use of the DataGridCheckBoxColumn and the DataGridTemplateColumn.
&lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridCheckBoxColumn&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;Header&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;Is done&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;DisplayMemberBinding&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;{Binding IsDone, Mode=TwoWay}&quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;Header&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;Due date&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn.CellTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DataTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;TextBlock&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;{Binding DueDate, Mode=TwoWay}&quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DataTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn.CellTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn.CellEditingTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DataTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;SelectedDateFormat&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;Short&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;FirstDayOfWeek&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;Monday&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;SelectedDate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;{Binding DueDate, Mode=TwoWay}&quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DataTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn.CellEditingTemplate&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;Data:DataGridTemplateColumn&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;You can download the source code &lt;a href=&quot;http://gkvarv.googlepages.com/HandyScrum2.rar&quot;&gt;here&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/6509233538242576828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/04/yet-another-datagrid-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6509233538242576828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/6509233538242576828'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/04/yet-another-datagrid-app.html' title='DataGrid revisited'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-1425944969440850416</id><published>2008-03-30T23:36:00.001+02:00</published><updated>2008-12-13T00:00:41.330+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight"/><title type='text'>Silverlight 2.0: Two-way data binding with DataGrid</title><content type='html'>I&#39;ve written a little Master/Detail demo application using the DataGrid control in Silverlight 2.0 beta 1. The application shows usage of data binding, styles and definition of custom columns for the DataGrid control. You can download the source code &lt;a href=&quot;http://gkvarv.googlepages.com/HandyScrum.rar&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb5vJ45biKGCf8cPK7KFs0em93kLeyq26j8v1pbo4t7TySF8OvHBolqIiqhsBbp5j9iqfuWslAztDCG1jGfWBdDGtktd00WT52761TO2u6WWpC85GIel5dRRko2vkooeM9hGS9F-eK8ZUt/s1600-h/scrum.png&quot;&gt;&lt;img style=&quot;cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb5vJ45biKGCf8cPK7KFs0em93kLeyq26j8v1pbo4t7TySF8OvHBolqIiqhsBbp5j9iqfuWslAztDCG1jGfWBdDGtktd00WT52761TO2u6WWpC85GIel5dRRko2vkooeM9hGS9F-eK8ZUt/s400/scrum.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5183648301127611170&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following code fragment shows how to define your own columns for the data grid:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;xml&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;                &lt;data:datagrid name=&quot;lstTasks&quot; isreadonly=&quot;False&quot; headersvisibility=&quot;Column&quot; style=&quot;{StaticResource TaskList}&quot; selectionchanged=&quot;lstTasks_SelectionChanged&quot;&gt;&lt;br /&gt;                    &lt;data:datagrid.columns&gt;&lt;br /&gt;                        &lt;!--Title--&gt;&lt;br /&gt;                        &lt;data:datagridtextboxcolumn displaymemberbinding=&quot;{Binding Title, Mode=TwoWay}&quot;&gt;&lt;br /&gt;                            &lt;data:datagridtextboxcolumn.header&gt;&lt;br /&gt;                                &lt;textblock text=&quot;Title&quot;&gt;&lt;br /&gt;                            &lt;/Data:DataGridTextBoxColumn.Header&gt;&lt;br /&gt;                        &lt;/Data:DataGridTextBoxColumn&gt;&lt;br /&gt;&lt;br /&gt;                        &lt;!--Estimate--&gt;&lt;br /&gt;                        &lt;data:datagridtextboxcolumn displaymemberbinding=&quot;{Binding Estimate, Mode=TwoWay}&quot;&gt;&lt;br /&gt;                            &lt;data:datagridtextboxcolumn.header&gt;&lt;br /&gt;                                &lt;textblock text=&quot;Estimate&quot;&gt;&lt;br /&gt;                            &lt;/Data:DataGridTextBoxColumn.Header&gt;&lt;br /&gt;                        &lt;/Data:DataGridTextBoxColumn&gt;&lt;br /&gt;&lt;br /&gt;                        &lt;!--Backlog Name--&gt;&lt;br /&gt;                        &lt;data:datagridtextboxcolumn displaymemberbinding=&quot;{Binding Backlog.Name, Mode=TwoWay}&quot;&gt;&lt;br /&gt;                            &lt;data:datagridtextboxcolumn.header&gt;&lt;br /&gt;                                &lt;textblock text=&quot;Backlog Name&quot;&gt;&lt;br /&gt;                            &lt;/Data:DataGridTextBoxColumn.Header&gt;&lt;br /&gt;                        &lt;/Data:DataGridTextBoxColumn&gt;&lt;br /&gt;&lt;br /&gt;                    &lt;/Data:DataGrid.Columns&gt;&lt;br /&gt;                &lt;/Data:DataGrid&gt;&lt;/textarea&gt;</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/1425944969440850416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/03/silverlight-20-two-way-data-binding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/1425944969440850416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/1425944969440850416'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/03/silverlight-20-two-way-data-binding.html' title='Silverlight 2.0: Two-way data binding with DataGrid'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb5vJ45biKGCf8cPK7KFs0em93kLeyq26j8v1pbo4t7TySF8OvHBolqIiqhsBbp5j9iqfuWslAztDCG1jGfWBdDGtktd00WT52761TO2u6WWpC85GIel5dRRko2vkooeM9hGS9F-eK8ZUt/s72-c/scrum.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4930279255087763993.post-4028204846261370111</id><published>2008-03-04T01:48:00.005+01:00</published><updated>2008-03-09T22:38:55.321+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><category scheme="http://www.blogger.com/atom/ns#" term="DSL"/><category scheme="http://www.blogger.com/atom/ns#" term="Rule engine"/><title type='text'>The next generation rule engines are pure C#</title><content type='html'>The project I&#39;m currently working on is based on a rather narrow domain, but with a high density of business rules that comes along. Currently we are writing the rules directly in code, but there have been some pressure about using an in house created XML based rule engine. As the rule base becomes bigger and bigger the more the pressure.

As I see it there are two reasons for using a rule engine: &lt;ol&gt;&lt;li&gt;Separate the rules from the code so it can be edited without recompiling the application.&lt;/li&gt;&lt;li&gt;Let the rules be edited by a domain expert.&lt;/li&gt;&lt;/ol&gt;Does an XML based rule engine support this? Sure, a rule engine certainly separates the rules from the code and makes it editable. However, I don&#39;t really see how rules in XML are much better than rules written in code. Rules in XML can certainly become as complex syntactically as code and I would argue that as the rules get more complex, rules written in code actually get more easy to read and understand. So at my point of view a rule engine doesn&#39;t provide a domain expert much more support in editing rules than plain code.

Now comes the real pain with a rule engine; Testing. As the rules are written in XML it becomes real hard testing them incorporating your domain objects. Sure, the XML is often used to generate code, but I don&#39;t see how this improves the testability much. The generated code will normally be complex and hard to use as the XML and code generator tries to capture and provide functionality for general purpose problems and scenarios in non specific domains. Refactoring the code won&#39;t update the XML and suddenly you find yourself in a maintainability hell. This is why I would rather have my rules in code.

Now the problem with writing rules in code isn&#39;t that it is impossible to separate the rules from the rest code. Writing rules in code suffers in the same matter as rules written in XML in that it is extremely hard for a non technical domain expert to read, edit and verify rules. Lets not forget create new rules. I can understand those who argue that rules in XML are more maintainable for a non technical than rules in code, and the fact that there are some stakeholders driven against a XML based rule engine really got me thinking. As I most certainly want to keep my business rules in code for testability and maintainability I started thinking about an alternative way that could let us keep the rules in code and at the same time make them easy to edit, which in turn would satisfy all parties.

A couple of days ago, on my way to work, I was talking to a colleague who had attended a meeting at the &lt;a href=&quot;http://www.nnug.no/&quot;&gt;Norwegian .Net User Group (NNUG)&lt;/a&gt; where Anders Norås, a former employee at my company held at talk about fluent interfaces and domain specific languages. I immediately associated this concept with my rules problem and started digging around on the Internet. In my search I found at great &lt;a href=&quot;http://andersnoras.com/blogs/anoras/archive/2007/07/09/behind-the-scenes-of-the-planning-dsl.aspx&quot;&gt;article&lt;/a&gt; by Anders Norås where he shows an example of an DSL implementation. I would also recommend an &lt;a href=&quot;http://martinfowler.com/articles/languageWorkbench.html#Conclusions&quot;&gt;article&lt;/a&gt; by Martin Fowler where he discusses the pros and cons of internal and external DSLs.

Although external DSLs can be evaluated at runtime, which has made XML so popular, and the fact that internal DSLs are limited by the syntax of the language of choice, I would still go for an internal DSL. I don&#39;t have to learn a new language and I can take advantage of my existing skills. The idea of fluent interfaces seems very interesting. Writing a fluent interface would mean that the domain expert editing the rules could use IDEs and even get intellisense while he/she is typing the rules. Writing the rules in a language like Boo, which runs on the .Net CRL could even let the rules be evaluated runtime. However, I don&#39;t see this as an requirement for my problem. Writing a fluent interface in C# would probably satisfy all my needs. Extension methods would most certainly become handy. Still, I&#39;m a little bit concerned about the effort and cost of creating such a DSL.

Hopefully I soon will find the time to implement a little prototype and write a part 2 of this post. I&#39;ll keep you posted!</content><link rel='replies' type='application/atom+xml' href='http://gorankvarv.blogspot.com/feeds/4028204846261370111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gorankvarv.blogspot.com/2008/03/my-first-look-at-domain-specific.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4028204846261370111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4930279255087763993/posts/default/4028204846261370111'/><link rel='alternate' type='text/html' href='http://gorankvarv.blogspot.com/2008/03/my-first-look-at-domain-specific.html' title='The next generation rule engines are pure C#'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>