by Njål

Unit testing – Visual Studio 2012 Fakes in Team City

image

TeamCity only supports the MsTest testrunner for running MS Tests. This testrunner does not support the brilliant Fakes Framework.

 

 

http://msdn.microsoft.com/en-us/library/ms253138.aspx
image

 

If you run the tests with MsTest – you’ll get the legendary ShimNotSupportedException – which you can read more about here.

The Visual Studio 2012 Test Runner however supports Fakes – here’s how to make Team City use this runner instead of MsTest:

image

 

“C:Program Files (x86)Microsoft Visual Studio 11.0Common7IDECommonExtensionsMicrosoftTestWindowvstest.console.exe” /inIsolation UnitTest.dll

 

Note that this requires Visual Studio 2012 on the Build Agent machine. I know a lot of you don’t like this – so you can also just copy the files in the TestWindow folder to your Build Agent and use vstest.console.exe directly.

Another thing which is nice is that the VSTest is a lot faster than MsTest.

by Njål

TeamCity: Executing commands and programs on a remote machine using Powershell

Windows Sysinternals has a range of pretty neat tools. My favorite is PsExec – which lets me execute programs on a remote computer. It’s like Remote Desktop – but with the console. Or you could think of it as a Windows alternative of SSH – if you’re a *NIX guy.

It’s perfect when you need to restart a server where Remote Desktop Services is fubar.

 

I can execute

psexec \myWebServer cmd.exe

and I am now running a console window on the webserver.

It is also handy when scripting/automating tasks – such as building, deploying and making backups of software projects.

But invoking PsExec from TeamCity isn’t a walk in the park, to say the least. PsExec does some funky things with the standard input/output, and invoking this from Java (which TeamCity is built on) raises all kinds of problems and stability issues.

Luckily – Powershell takes care of business.

The script below stops an IIS 7 ApplicationPool on a remote server.

[string]$HostName = “myWebServer”
[string]$Cmd = C:WindowsSystem32inetsrvappcmd.exe stop apppool MyMainAppPool”
Invoke-WmiMethod –class Win32_process -name Create -ArgumentList ($Cmd) -ComputerName $HostName

Change $HostName and $Cmd in order to run other commands.

by thorhalvor

Powershell returns exitcode 0 instead of 1

I am currently setting up buildscripts in Teamcity for a website I am working on. I use Ctt.exe to transform my web.config files and this program is invoked through PowerShell. But my problem is that that Ctt.exe in some cases has an error or something else is wrong in my ps1-script but the Teamcity buildstep returns "Process exited with code 0" and the build Succeeds instead of failing.

Since this blogpost might be boring and badly written I will start with the solution:

$ErroActionPreference = ‘Stop’

My scenario is that I have a script, ConfigTransform.ps1, which is invoking the ctt.exe file. This script file takes one parameter which is the Environment (Test/Production). If an error occurs in the script I need the hole build to fail.

To force an error while testing I have set my script to invoke the file "DoesNotExist.exe" instead of the Ctt.exe.

My script (ConfigTransform.ps1)

param($Environment)
Write-Host Environment is $Environment
..DoesNotExist.Exe

 

In Teamcity there are many different alternatives for you to call the script.

Script=File and Executionmode = -FILE

Since I have a predefined powershell script with all the logic and I need to pass a parameter to it, – I first choose the PowerShell-runner with Script=File and Executionmode to –File. As you can see below the parameter is passed on but this process exits with code 0 and therefore the Build won’t fail.

[13:51:05][Step 1/5] Starting: (…)cmd.exe /c (…)powershell.exe -NonInteractive -File (…)
ConfigTransform.ps1 -Environment Test && exit /b %ERRORLEVEL%
[13:51:06][Step 1/5] Environment is Test
[13:51:06][Step 1/5] The term '..DoesNotExist.Exe' is not recognized as the name of a cmdlet, funct
[13:51:06][Step 1/5] ion, script file, or operable program. Check the spelling of the name, or if a
[13:51:06][Step 1/5] path was included, verify that the path is correct and try again.
[13:51:06][Step 1/5] At C:TeamCitybuildAgentwork7100e0a13f6ca7b6BuildToolsAndScriptsScriptsCo
[13:51:06][Step 1/5] nfigTransformConfigTransform.ps1:4 char:20
[13:51:06][Step 1/5] + ..DoesNotExist.Exe <<<<
[13:51:06][Step 1/5]     + CategoryInfo          : ObjectNotFound: (..DoesNotExist.Exe:String) [],
[13:51:06][Step 1/5]     CommandNotFoundException
[13:51:06][Step 1/5]     + FullyQualifiedErrorId : CommandNotFoundException
[13:51:06][Step 1/5]
[13:51:06][Step 1/5] Process exited with code 0

 

Script=File and Executionmode = -Command

Then I try setting the Executionmode to "-Command". The exit code is now correct and the Build is not failing but it is not possible to pass on script parameters.

[13:51:07][Step 1/5] Starting: (…)cmd.exe /c (…)powershell.exe -NonInteractive -Command (…)
ConfigTransform.ps1 && exit /b %ERRORLEVEL%
[13:51:07][Step 1/5] Environment is
[13:51:07][Step 2/5] The term '..DoesNotExist.Exe' is not recognized as the name of a cmdlet, funct
[13:51:07][Step 2/5] ion, script file, or operable program. Check the spelling of the name, or if a
[13:51:07][Step 2/5] path was included, verify that the path is correct and try again.
[13:51:07][Step 2/5] At line:1 char:20
[13:51:07][Step 2/5] + ..DoesNotExist.Exe <<<<
[13:51:07][Step 2/5]     + CategoryInfo          : ObjectNotFound: (..DoesNotExist.Exe:String) [],
[13:51:07][Step 2/5]     CommandNotFoundException
[13:51:07][Step 2/5]     + FullyQualifiedErrorId : CommandNotFoundException
[13:51:07][Step 2/5]
[13:51:07][Step 2/5] Process exited with code 1

 

Script=Source code and Executionmode = -Command

Since executionmode –File does not return correct errorcode I need to use "-Command" but also pass on my parameter. This can be done PowerShell-runner with Script=Source code. In the Script Source field I am now adding the full path to my script including my parameter.

The output is:

[13:51:05][Step 1/5] Starting: (…)cmd.exe /c (…)powershell.exe -NonInteractive -Command (…)
powershell3439435836265.ps1 && exit /b %ERRORLEVEL%
[13:51:06][Step 1/5] Environment is Test
[13:51:06][Step 1/5] The term '..DoesNotExist.Exe' is not recognized as the name of a cmdlet, funct
[13:51:06][Step 1/5] ion, script file, or operable program. Check the spelling of the name, or if a
[13:51:06][Step 1/5] path was included, verify that the path is correct and try again.
[13:51:06][Step 1/5] At C:TeamCitybuildAgentwork7100e0a13f6ca7b6BuildToolsAndScriptsScriptsCo
[13:51:06][Step 1/5] nfigTransformConfigTransform.ps1:4 char:20
[13:51:06][Step 1/5] + ..DoesNotExist.Exe <<<<
[13:51:06][Step 1/5] + CategoryInfo : ObjectNotFound: (..DoesNotExist.Exe:String) [],
[13:51:06][Step 1/5] CommandNotFoundException
[13:51:06][Step 1/5] + FullyQualifiedErrorId : CommandNotFoundException
[13:51:06][Step 1/5]
[13:51:06][Step 1/5] Process exited with code 0

My script is runtime wrapped in a temporary ps1-file "powershell3439435836265.ps1 ", the parameter Environment is Test BUT exit code is now 0 again! So what now…

Solution:

Powershell is by default continuing when "minor" error occurs. I guess the Powershell-runner has done something with that and therefore it works using the –Command switch. I also guess they have forgotten that errorhandling when creating the –File switch. When setting Script=SourceCode all the code is wrapped in a temporary script and you have to take care of the errors yourself. One solution that at first glance worked for me was to wrap my script in a try catch and then just have a ‘throw’ in my errorhandling. What was not so good about this is that the exception itself was suppressed and therefore not visible in the build output.

So the best solution I found is to add the following code (see the first line) in Team City’s Source Code-field:

$ErrorActionPreference = ‘Stop’

(…)/ConfigTransform.ps1 –Enviroenment Test

And then finally everything worked as I wanted. I got exit code 1 in the examples above. Smile