Loren Halvorson's Blog

If your only tool is a hammer...

Config files and NUnit tests

A comment left on my last post about TestDriven.NET asked how to tell NUnit to use an application configuration file.

This is easy, just have a configuration file with the same name as your test assembly + ".config" sitting next to your assembly and NUnit automatically picks it up. This is NUnit's built-in behavior and has nothing to do with TestDriven.NET, so it works for any way you invoke NUnit such as NUnit GUI, NUnit console, or TestDriven.NET.

So if you have a test assembly named "MyUnitTests.dll", just have a post build step that takes a config file and copies it to the output folder making sure it is named "MyUnitTests.dll.config".

The simplest way to do this using VS.NET is to add a post build event to your project that does something like this:

copy /Y "$(ProjectDir)app.config" "$(TargetPath).config"

Path Substitution

Sometimes config files have to contain fully-qualified paths to other files. (Preferably they are relative paths, but we've run into some strange cases where they needed to be fully qualified...don't ask). For example:

<configuration>
  <appSettings>
    <add key="path.to.some.file"
         value="C:\Some\Fully\Qualified\Path\SomeFile.xml"/>
  </appSettings>
</configuration>

When test are run from different locations (developer 1 works on his C: drive, developer 2 works on his D: drive, the build server builds under a dated build directory etc...) It may be necessary to get a little fancier with this post build step and actually do text replacement step to fix up the paths to represent the current build location.

There are lots of ways to solve this, but one way is to change the post build event to call a batch file which in turn calls a vbscript that does a text replacement something like this:

Post Build Event:

"$(ProjectDir)\PostBuild.cmd" "$(ProjectDir)" "$(TargetPath)"

--app.config--

<configuration>
  <appSettings>
    <add key="path.to.some.file"
         value="{PATHPLACEHOLDER}\SomeFile.xml"/>
  </appSettings>
</configuration>

--PostBuild.cmd--

copy /Y "%1app.config" "%2.config"
cscript.exe //nologo "%1strrepl.vbs" "%2.config" "{PATHPLACEHOLDER}" "%1"

--strrepl.vbs--

Option Explicit

Dim oFSO, oFile, strFilename, strData, strPattern, strReplace

Const ForReading = 1
Const ForWriting = 2

If (WScript.Arguments.Count <> 3) Then
    WScript.Echo "Usage: strrepl %filename% %searchstring% %replacestring%"
    WScript.Quit
End If

strFileName = WScript.Arguments(0)
strPattern  = WScript.Arguments(1)
strReplace  = WScript.Arguments(2)

' Get File
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.OpenTextFile(strFileName, ForReading)
strData = oFile.ReadAll
oFile.Close

strData = Replace(strData, strPattern, strReplace)

' Write File
Set oFile = oFSO.OpenTextFile(strFileName, ForWriting)
oFile.Write strData
oFile.Close

 

 

Comments

Guy S. said:

Hi Loren,

I see that using the post-build command is suggested as first choice. I add my nunit config file to the solution root and I find that all the child project folder can use it without the need to copy it to the TargetPath.
Am I missing something?
Does this method I'm using is better?

In addition - when using config files of ebtLib I also locate them in the solution root folder and my tests which are part of the solution child folder/s projects can use it without the need to copy the files.

So my question is when we need to use the copy/postBuild mechanism?
Guy
# May 20, 2005 12:12 PM

Lorenh said:

Guy,
So if I understand what you are doing, you just have a config file in the solution root and it is still picked up by NUnit. What is your config file named? In my experience, the config file has to be named {nameOfTestAssembly}.dll.config and has to be sitting next to the assembly itself for NUnit to find it. I played around with this a little and removed it from next to the assembly and moved it up a couple folders and it didn't work. I guess I'd like a little more information on what you are doing.
# May 20, 2005 12:48 PM

Lorenh said:

Darell,
I just edited the post to hopefully be a little more clear on the motivation behind the more complex path substitution hack. Thanks for pointing out that I was less than clear.

Again, just use relative paths in your config file and you don't need the second hack at all, of course it's going to be relative from where the test assembly is running in bin\Debug or bin\Release.
# May 20, 2005 2:23 PM

Guy S. said:

I add the nunit config file to the solution root folder above all the other project folders and name it with the same name of my solution. The Tests files located as part of the different project/s (of type Class Library) in my solution and not as dedicated test project/s.

I find that by using this configuration I don't need to copy the config file to the specific project I'm testing.
# May 20, 2005 3:23 PM

Lorenh said:

Guy,
Is that specifically when running the tests through TestDriven.NET? Because I can't see how that would work when invoking the tests through NUnit GUI and NUnit Console. How could NUnit know anything about the name of the solution?
# May 20, 2005 3:43 PM

Guy S. said:

I'm not sure why this is working so I only give more details on what I did.
I know we should copy our config files to the $TragetProject folder when we try to activate a Windows Application or Console Application. But when using Class Libraries projects then what I did was enough.

I'm working with NUnit GUI 2.2 and the configuration is as follow -

I created a blank solution which is name and physical folder called - CompanyName.DepartmentName.ProjectName

I created NUnit file with the name
CompanyName.DepartmentName.ProjectName.nunut

I added a new Class Library project called
CompanyName.DepartmentName.Common

I added the reference to NUnit frame work and
a folder called TESTS
Beneath the TESTS folder a added a test class
for keeping part of my project testing.

I added the assembly of the common dll to the NUnit file

On that stage I could open the NUnit config file using the NUnit GUI and see my tests within the Common->TESTS folder

As you see, I don't use a special test project for each project I wanted to test. My tests are part of the existing projects.

# May 21, 2005 11:00 AM

Mark said:

I have no trouble running the unit-tests for my individual projects. When I want to run tests for several projects however it fails to pick up the .config file.

I'd prefer to be able to do this from withing VS but even from the command-line I'd be happy. Is it possible at all?

If it is possible, what would the command-line look like? I tried things like the following:

nunit-gui UnitTestSet.nunit /config="some-config-file"

However the assemblies that I added to my unit-test configuration don't pick up any .config file and therefore fail.
# June 10, 2005 9:38 AM

mel said:

Great tip, helped me solve my problem right quick.

# August 9, 2007 4:09 PM

Brian Hartsock said:

Money.  Thanks a bunch.

# December 31, 2007 4:10 PM