Mr Andersson

Pimping PsUnit with constraint based assertions

leave a comment »

Using PsUnit one can set up scripted “unit tests” for PowerShell scripts. I have sort of just started using PsUnit at work and right now I feel that a lot of the basic features of other test frameworks are missing.

PsUnit has one function for doing constraint based assertions. This may be familar to those who are using NUnit. Basically the syntax for this is:
<![CDATA[
$result = DoSomething
Assert-That $result { $ActualValue -eq "expected value" }
]]>

Using NUnit and this constraint based model, a simple assertion can look like this:
<![CDATA[
Assert.That( myString, Is.EqualTo("Hello") );
]]>

I quite don’t like the “barebone” scriptblock you need to write to use Assert-That in PsUnit, so here is what I came up with (using my example of above):
<![CDATA[
$result = DoSomething
Assert-That $result (IsEqualTo "expected value")
]]>

I also added another constraint which allows you to assert that some code throws something:
<![CDATA[
# The following assertion will always pass
Assert-That { throw "blah!" } (ThrowsException)
]]>
This complements the already built-in feature of PsUnit which allows you to add a parameter, $ExpectedException, to the test. If you have been using MSTest you would use the method attribute ExpectedException for this.

Here is another example which tweaks the constraint to a somewhat more specific type of exception:
<![CDATA[
# The following assertion will fail since throw in PowerShell creates a System.Management.Automation.ErrorRecord
Assert-That { throw "blah!" } (ThrowsException -Exception $([System.ArgumentException]))
]]>

A more usable test using the ThrowsException constraint could be:
<![CDATA[
Assert-That {
# The following web resource does not exist, thus an error should be the result
Get-Http "http://blogger.com/asdfg"
} (ThrowsException -Exception $([System.Net.WebException]))
]]>

The biggest improvement using these new constraints is the output in the test result.
While using PsUnit out-of-the-box…
<![CDATA[
$foo = "bar"
Assert-That $foo { $ActualValue -eq "foo" }
]]>
…results with “Assert-That returned false!” in the test result.
Using the constraint in this blog post…:
<![CDATA[
$foo = "bar"
Assert-That $foo (IsEqualTo "foo")
]]>
…results with “ActualValue ‘bar’ is not equal to expected value ‘foo’“.

The same level of detail is provided by the ThrowsException constraint, which may result in “No exception was thrown, expected exception of type ‘System.ArgumentException’“.

Any ideas, suggestions etc.? Please don’t hesitate to drop a comment!

Written by anderssonjohan

November 11, 2009 at 20:41

Posted in scripting

Tagged with ,

Integrating PsUnit and MSBuild

leave a comment »

The last month I have been digging into, adding new and refactoring the Powershell scripts we use in RemoteX Applications. We primarily use PowerShell to configure and deploy our product.

More often or too many times – with our latest releases – our fellow collegues at Customer Operations have been telling us “The xyz powershell script doesn’t work anymore, what have you done to it???”
I could have answered: “- We don’t have automated tests on those scripts, so what do you expect? Manual testing? Pfffff…”, but for obvious reasons I didn’t :) .
So it was time to add some automated tests for those scripts so I could get this guy at Customer Operations back to work.
All compiled code (C#) is automatically tested in our Continuous Integration builds when someone checks in, but until now we haven’t had automated tests for our PowerShell scripts. With “automated” I mean that a test runner executes a test suite during a build.
In order to test our PowerShell scripts I have started using PsUnit. Since we are using Team Foundation Server and MSBuild for our CI builds, I needed to integrate PsUnit with MSBuild somehow.
There are several ways to invoke Powershell from an MSBuild script – we have chosen the Exec task which invokes powershell.exe.
First of all I created a separate build target which invokes PsUnit:

<![CDATA[
<PropertyGroup>
<CoreTestDependsOn>$(CoreTestDependsOn);RunPsUnit</CoreTestDependsOn>
<RunPsUnitDependsOn>CoreRunPsUnit</RunPsUnitDependsOn>
</PropertyGroup>

<Target Name="RunPsUnit" DependsOnTargets="$(RunPsUnitDependsOn)"/>
<Target Name="CoreRunPsUnit" Condition=" '$(RunTest)'!='false' ">
<Exec Command="$(PowerShell) -Command &quot;&amp;{ .\runpsunit.ps1 -PsUnitTestFile %(PsUnitTest.FullPath) }&quot;"/>
</Target>
]]>
Using this batch target, all that needs to be done is to add PsUnitTest items to the build script. Just like the way we set up TestContainer items for use with MSTest:
<![CDATA[
<ItemGroup>
<PsUnitTest Include="$(SolutionRoot)\Scripts\Tests\*.Test.ps1"/>
<PsUnitTest Include="$(SolutionRoot)\References\PsUnit\*.Test.ps1"/>
</ItemGroup>
]]>
So far so good, but when tests are failing, the build is successful. This is because the Exec task only reports a build error when the executed command returns an exit code other than zero (0×0). So I started looking into the test runner of PsUnit (PsUnit.Run.ps1) and discovered that it didn’t send any output nor produced some other exit code than 0×0. The only output PsUnit will send you is some nice colorful information written to the PowerShell host.

So I ended up with the following:
1. this tiny tweak at the end of PsUnit.Run.ps1:

<![CDATA[
$TestResults
]]>
This makes PsUnit.Run.ps1 send the test results along the pipeline.

2. A small wrapper for the test runner which returns some exit code other than 0×0 to the Exec task in MSBuild:

<![CDATA[
$results = Invoke-Expression "$psUnitRun -PsUnitTestFile $PsUnitTestFile"
$results | % {
if( $_.Result -eq "FAIL" ) {
throw "Test run failed: $($_.Test) - $($_.Reason)"
}
}
]]>
This makes the Exec task report a build error if we find any failing test in the test result from PsUnit – and last but not least – the name of the failing test and the reason ends up nicely in the MSBuild log file.

So now when somebody checks in a change to compiled code, which affects the result of our setup scripts, we will be able to detect errors ASAP! Yay!

Written by anderssonjohan

November 11, 2009 at 19:50

Posted in scripting

Tagged with , ,

Yay, PowerShell v2 is finally RTMed!

leave a comment »

PowerShell v2 is finally RTMed for the rest of us who still has a couple of boxes not running Windows 2008 Server R2 or Windows 7.

Downloads and info for Windows Server 2003, Windows Server 2008 (R1), Windows Vista and Windows XP.

Written by anderssonjohan

November 9, 2009 at 16:01

Posted in scripting

Tagged with

Timjankyckling med rotsakspytt

leave a comment »


Mor och far brukar göra en grymt god rotsakspytt som passar bra på hösten. Jag kör en repris av kyckling och parmigiano-reggiano som en avslutning på höstlovet/vecka som gräsänkling.

PS. Det är inte utan viss längtan efter den beställda HTC HD2 luren man publicerar detta. Bilderna tagna med min HTC Tytn II är verkligen hur suddiga som helst. DS.

Ingredienser
  • Kycklingfiléer
  • Potatis
  • Kålrot
  • Vitkål
  • Morötter
  • Lök (gärna purjolök och charlottenlök)
  • Ost (gärna med lite smak)
  • Timjan
  • Paprika(krydda)
  • Peppar
  • Smör, olja
Lägg kycklingfiléerna i en ugnssäker oljad form. Krydda med paprika, timjan och peppar. Sätt in i förvärmd ugn på 175 grader i c:a 60 minuter. Tärna upp potatisen i lagom små delar. Värm en stekpanna med smör i. Lägg i potatisen. Hacka löken och tillsätt i pannan när potatisen har hunnit gotta till sig lite i smöret. Tärna upp/hacka kålroten, morötterna och vitkålen och lägg i pannan. Låt stå och puttra med lock ett tag. Tillsätt mer smör vid behov. Riv osten och tillsätt när kycklingen har c:a 15 min kvar. Ät och njut!

Written by anderssonjohan

October 31, 2009 at 18:52

Posted in food

Tagged with

PowerTip of the day – Variable descriptions

leave a comment »

I just got this in my inbox from Powershell.com:
Add Descriptions to Variables

Keeping track of a variable’s purpose can be accomplished by assigning a clear text description:

$ip= '10.10.10.10'
Set-Variable ip -description 'Server IP or Name'

When you now list your variables, you can output the variable description as well:

dir variable:ip | Format-Table Name, Value, Description

Playing around a little I found out that you easily can get the same information about system/environment variables using Get-Variable and Format-Table:

gv | ft Name, Description
Name                                    Description
----                                    -----------
$
?                                       Execution status of last command.
^
_
args
bla                                     Bla bla bla
ConfirmPreference                       Dictates when confirmation should be...
ConsoleFileName                         Name of the current console file.
DebugPreference                         Dictates action taken when an Debug ...
Error
ErrorActionPreference                   Dictates action taken when an Error ...
ErrorView                               Dictates the view mode to use when d...

Written by anderssonjohan

October 29, 2009 at 14:54

Posted in scripting

Tagged with

Switching component implementations in Castle Windsor

leave a comment »

Problem: Test suite for a system for which I need to replace (inject) the behavior of a certain component. The system is using Castle Windsor with an XML configuration file.

In this system integration test I want to use the real container configuration except that I want to switch out a component that does authorization using a database.

The replacement for the real component is as simple as:

public bool IUsernamePasswordVerifier.VerifyPasswordFor( string username, string password ){    return true;}
Solution: Tried this, which failed on me. But with a little help from a tiny facility used by the test suite I can now “re-wire” service implementations in the container.
There are probably several other solutions on how one could accomplish the same thing, but this one worked out very well for me.

ComponentRewriterFacility.cs:

using System;using System.Collections.Generic;using Castle.Core;using Castle.Core.Configuration;using Castle.MicroKernel;

namespace ServiceTests.Service{    public class ComponentRewriteFacility : IFacility    {        readonly IDictionary<Type, Type> _rewrites;

        public ComponentRewriteFacility()        {            _rewrites = new Dictionary<Type, Type>();        }

        public void AddRewrite<I, T>() where T : I        {            _rewrites.Add( typeof(I), typeof(T) );        }

        public virtual void Init( IKernel kernel, IConfiguration facilityConfig )        {            if( kernel == null )                throw new ArgumentNullException( "kernel" );            kernel.ComponentRegistered += ComponentRegistered;        }

        public void Terminate()        {        }

        void ComponentRegistered( string key, IHandler handler )        {            if( !ShouldRewrite( handler.ComponentModel ) )                return;            handler.ComponentModel.Implementation = _rewrites[handler.ComponentModel.Service];        }

        protected virtual bool ShouldRewrite( ComponentModel componentModel )        {            return _rewrites.ContainsKey( componentModel.Service );        }    }}

And in our test suite initializer we add the “re-write rule” like this:

IWindsorContainer container = new WindsorContainer();container.AddFacility<ComponentRewriteFacility>( f => f.AddRewrite<IUsernamePasswordVerifier, AnythingGoesUsernamePasswordVerifier>() );container.AddFacility<WcfFacility>();container.Install( Castle.Windsor.Installer.Configuration.FromXmlFile( "Windsor.xml" ) );

Like it? Not? Have a better solution? Please let me know!

Written by anderssonjohan

October 28, 2009 at 19:34

Posted in programming

Tagged with , , , ,

Het pastapanna (swedish)

leave a comment »


Mitt enkla hopkok till gräsänklingsmiddag @ 2009-10-28, en het pastapanna med inspirerad av luncherna på Tutto Italia i Sickla. De brukar ha en gör-go salamitallrik som det är rätt bra fart i. Då salamin flaggade med sin frånvaro idag fick sambalburken hoppa in som ersättare.

Ingredienser
  • Ekologisk Gnocchi (ICA)
  • Kycklingfilé
  • 500 g krossade tomater med vitlök (ICA)
  • Ett gäng soltorkade tomater i olivolja
  • 1 dl blandade ekologiska oliver (ICA)
  • Svartpeppar
  • Sambal
  • Ekologisk buljong utan jäst och socker (Biofood)
  • Ekologisk italiensk olivolja (Coop, Änglamark)
  • Parmigiano-Reggiano

Koka pastan. Tärna upp kycklingen och bryn i smör i en stekpanna. När den är genomstekt tillsätter du de krossade tomaterna, buljong och peppar. Dela de soltorkade tomaterna i två delar och lägg i pannan. Tillsätt sambal efter eget tycke. Låt reduceras något. Tillsätt oliver och olivolja och låt puttra i 5 min. Riv en rejäl dos parmigiano-reggiano över vid servering. Ät och njut!

Written by anderssonjohan

October 28, 2009 at 18:56

Posted in food

Tagged with , , ,

PowerShell Scripting Guidelines

leave a comment »

Lately I have been doing some work related to how we automate the process of how we install, configure and deploy our product into a server environment. Since our pre-requisites are Windows Server 2008 and Windows 7, we can totally go crazy with PowerShell scripts. Next thing to sort out after upgrading to Windows Server 2008 R2 is of course PowerShell Remoting.. :)

However, using quite an amount of PowerShell scripts, we need some guidelines to structure them. This to complement our guidelines covering OO design and C# code style.

So I have started out with the following draft and I’m looking for some tips and comments about this and what you (yes, you!) believe is a good rule of thumb to use when developing and maintaining a bunch of PowerShell scripts.

(Sorry for the ugly formatting. Code was pasted from PowerGUI to a word doc and then to blogger :) )

1 Scripting Guidelines

When there is a need of a script, use your mighty PowerShell skills!
Here is a couple of guidelines which should be followed to speed up development, maintenance and usage of PowerShell scripts.

Apply the above mentioned principles when applicable.

1.1 Function files

Package common functions into function files and dot-source them in the script which needs them.
Example:
. ..\DB\Common.ps1

1.2 File names

Name PS1 files using standard verbs like get, set, remove, new etc., or a verb that fits the purpose or the script. Do not use verbs in file names for files that have generic purpose, like a function library file. Also consider using PowerShell v2 modules when applicable.

Scripts that are to be called from the prompt are easier to understand if they are named in such way that no “usage” or get-help is needed when invoking the script. Like add-user.ps1, remove-database.ps1 and so on.

Avoid complex scripts with multiple purposes which becomes complex with parameter sets (get-help about_functions_advanced_parameters)

1.3 Script and function parameters

Use built-in support to handle function and script parameters. Avoid index-based unnamed parameters using $args.

Reference: get-help about_arguments; get-help about_functions; get-help about_functions_advanced_parameters
MSDN:
http://msdn.microsoft.com/en-us/library/ms714433(VS.85).aspx

Example, testme.ps1:

param(

[Switch] $ver = [Switch]::Present

)

Write-Host $args

Write-Host “Testing!”

if( $ver )

{

Write-Host “Testing even more!”

}

Output:

PS > .\testme.ps1 –ver
PS > .\testme.ps1 -ver:$false

1.4 Decorate function parameters appropriately using validation rules

Decorate your parameters with validation rules and help messages to avoid tedious work on custom “script usage” functions. Your script users will be able to use “get-help yourscript.ps1”, or the equivalent “yourscript.ps1 -?” to get script usage information. Users will also be prompted if mandatory parameters are left out blank.

Get-help will also print out common parameters (get-help about_commonparameters).

Example:

param(

[Switch] $ver = [Switch]::Present,

[Parameter(mandatory=$true, helpmessage="Your name")]

[ValidateNotNullOrEmpty()]

[string] $name = “John Doe”

)

Write-Host $args

Write-Host “Hello $name!”

if( $ver )

{

Write-Host “Your name is $($name.Length) characters long”

}

Output:

PS > get-help .\testme.ps1

testme.ps1 [-name] [-ver] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-ErrorVariable ] [-WarningVariable ] [-OutVariable ] [-OutBuffer ]

1.5 Document script usage using PowerShell comment based help

When it is necessary to document how a script can be used, or when you want to provide more information about your script’s parameters than just the name, document it using the PowerShell help syntax. This can be compared to using XML comments in languages such as C#/VB or javadoc tags in Java.

See “get-help about_comment_based_help” for more information.

Example:

<#

.Synopsis

Synopsis text here

.Description

Usage description here

.Parameter ver

Enabling this switch prints out the length of the given name

.Parameter name

The name to say hello to

#>

param(

[Switch] $ver = [Switch]::Present,

[Parameter(mandatory=$true, helpmessage="Your name")]

[ValidateNotNullOrEmpty()]

[string] $name = “John Doe”

)

Write-Host $args

Write-Host “Hello $name!”

if( $ver )

{

Write-Host “Your name is $($name.Length) characters long”

}

Output:
PS> get-help -full .\testme.ps1

NAME
C:\temp\testme.ps1

SYNOPSIS
Synopsis text here

SYNTAX
C:\temp\testme.ps1 [-ver] [-name] []

DESCRIPTION
Usage description here

PARAMETERS
-ver []
Enabling this switch prints out the length of the given name

Required? False
Position? Named
Default value
Accept pipeline input? False
Accept wildcard characters?

-name
The name to say hello to

Required? True
Position? 1
Default value
Accept pipeline input? False
Accept wildcard characters?


This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer and OutVariable. For more information, type,
“get-help about_commonparameters”.

INPUTS

OUTPUTS

RELATED LINKS

1.6 Use validation rules to perform parameter input validation

PowerShell has several built-in validation rules for input validation. Use them as long as they add more value than doing custom validation using if-statements.

The built-in validation rules are: AllowNull, AllowEmptyString, AllowEmptyCollection, ValidateCount, ValidateLength, ValidatePattern, ValidateRange, ValidateScript, ValidateSet, ValidateNotNull, ValidateNotNullOrEmpty
See “
get-help about_functions_advanced_parameters” for further reference.

1.7 Putting the right stuff on the pipeline

· Use write-host for console information with fancy colors

· Use write-output to be able to pipe your script/function to another script/function.
Example pipeline scenario, sending a user from add-user to new-guestbookentry:
. .\guestbooks-functions.ps1;
add-user “foo” “password” | new-guestbookentry “Welcome to our guestbooks.com!”

· Avoid unwanted objects on the pipeline using termination with $null assignments or piping the output to NULL, example:
add-user “foo” “password” # put the added user on the pipeline
$null = add-user “foo” “password” # added user object “terminated”
add-user “foo” “password” | out-null # added user object piped to NULL instead of the output

Written by anderssonjohan

October 21, 2009 at 12:57

Posted in scripting

Tagged with

Food, Code, Time and Quality

leave a comment »

Being an enthusiastic software developer is not without its battles. As an metaphor I would like to illustrate this particular (kind of) battle I think of, with some of my own experience as a parent and a bit of a cooking “enthusiast”.

Ok, so you come home late with the kids and you have just had a great time in the park playing around all afternoon. The kids are happy and you feel you have a nice quality moment in life. You also feel quite satisfied with your big dinner plans. Tic-tac-tic-tac. Time flies and you hurry to get home in time for..
Next stop: Dinner.
You: Really enthusiastic about good cooking, nutricious food etc.
Time: Just too late. There is no time to prepare a nice meal of food from the ground up with hungry kids running around, soon screaming and beaten up by each other..
Solution: What was the phone number to that near by pizza/burger/salad/indian/china restaurant again?

If you think of situations like this but with defect software in production, you might have taken one of the following paths what regards the “solution” part:

“- Hey, let’s solve this by increasing the disk space for now so that Windows Error Reporting doesn’t fill up the system volume with error logs”

“- Request timeout? Let’s add another web node so we can continue with our big deployment. Let’s investigate the timeout issue later.”

Depending on your current situation you may right now feel “yeah, what’s wrong with all that?” or “Stop procrastinate! I would ever never do such things – fix the real problem instead”.
Of course you want to start from the ground up and build quality in, but when the shit already have hit the fan, what would YOU do?
I’m not saying that eating fast food or cutting corners in systems development are good things to do all the time. However, there are differences of having a failing/defect system in production and when you are in “experimentation mode” (a.k.a building new features).

For both cases of experimenting/developing with cooking and doing software development, you don’t know for how long you need to experiment to get it “feature completed”. What you DO know is that you for sure want to “get it right”, but again, not necessarily “feature complete”. Therefore you have to do timeboxing to deliver on time without any loss in quality.

To avoid being in the park with the kids too long in the afternoon I can easily add some more automated tests. I can set up my mobile phone to buzz a sound. I could also check the azimuth of the sun, look at the clock tower, use a wrist watch and what not to get a signal when it is time to get started with the dinner.
But even though these tests are valuable and can reveal defects, they are no good if I just ignore to use them.
As I said before, it’s probably not a problem if this happens one or two times. But if you continue doing this you will have a quite dissatified customer (the family).

Or would you? Really?
It certainly depends on how you define what quality time with your family is about.
(yes, believe me when I say my own and my common-law spouse’s definition of “quality” DO differ when the shit already hit the fan in terms of cooking dinner in the weekdays :) )

The same goes for computer systems running in production. You and your team may have a higher tolerance (for what some people would call) defects in production.
Maybe you aren’t a “timebox” person and maybe you define quality in other means than the number of automated tests / automated test coverage percentage.

When development tools mature, people changes their minds and/or gets replaced, the definition of describing “good quality” of a particular system may also change alot during the lifetime of the system.
The challange is not just about more automated tests. It’s about developers and managers (a.k.a. people), LOCs, test coverage, tools, time and process.

Further reading:
* The engineering manager’s lament
* Choose Two – The Project Triangle
* We Need More Automated Tests

Written by anderssonjohan

September 15, 2009 at 20:42

Posted in programming, software

Note to self: Windows is getting sensitive with the IIS PowerShell provider

leave a comment »

Today I have struggled with some of the most basic automation tasks with the new IIS 7 web server; Creating a web site, application pool and application using a PowerShell script.

Starting out with this tutorial I managed to use the following sample to accomplish my task:

New-Item IIS:\Sites\DemoSite -physicalPath C:\DemoSite -bindings @{protocol=”http”;bindingInformation=”:8080:”}

Set-ItemProperty IIS:\Sites\DemoSite -name applicationPool -value DemoAppPool

New-Item IIS:\Sites\DemoSite\DemoApp -physicalPath C:\DemoSite\DemoApp -type Application

Set-ItemProperty IIS:\sites\DemoSite\DemoApp -name applicationPool -value DemoAppPool

Everything worked fine with the samples and I started to setup a testing environment on my machine. That involved setting up a local IIS 7, creating some directories in the file system for my test website etc.
All tasks seemed to work, but I repeatedly got the following error when trying to assign the correct application pool to the application:

Set-ItemProperty : Value cannot be null.
Parameter name: path
At C:\.....\WebSetup.ps1:37 char:17
+ Set-ItemProperty <<<< IIS:\Sites\DemoSite\Server -name applicationPool -value DemoAppPool

I tried to use other cmdlets to change the application pool setting, but with no success. I also tried to change all paths, the name of the web site etc. according to the sample. The sample code worked, but the error remained when executing Set-ItemProperty in my script.
I doubled checked the documentation, the sample, the value given to the parameter -Path – but it still failed.
I was just going to post a question about this matter in some forums when I figured it all out.

The name of the directories I created in the file system was using lowercase characters, but not the entries in the IIS configuration!

The cause of this must be the code in either the file system provider or the IIS provider for PowerShell. Some part of the code which is executed when invoking the Set-ItemProperty cmdlet is doing some case sensitive work..
The lesson and recommendation after this experience is that I will try to create both my entries in the file system and in the IIS configuration from the same script. :)

Windows is definitely getting more and more sensitive these days…

Written by anderssonjohan

August 20, 2009 at 19:47

Posted in scripting

Tagged with ,

Follow

Get every new post delivered to your Inbox.