views:

238

answers:

1

Hi,

I'm trying to get TeamCity to run NUnit tests as set up in an NAnt script as follows:

<nunit2>
    <formatter  type="Xml"
                usefile="true"
                extension=".xml"
                outputdir="${BuildArea.ReportsDir}" />

    <test   assemblyname="${BuildArea.OutputDir}\Common.Tests.dll"
            appconfig="src\Common.Tests\Tests.config" />       
</nunit2>

Manually running the build script from the command line on the buildserver/agent machine runs the tests just fine so i know that there's no problem with the build script itself. However when a build runs from within TeamCity i always get the error:

"Could not locate the assembly nunit.Framework"

I've come across a related post (http://devnet.jetbrains.net/message/5211436#5211436) which recommends placing nunit.framework at the same location as the dll containings the tests but i was doing this already and i'm still getting the same error. Installing to the GAC is not an option.

Anyone has any idea how to fix this? I've spent hours trying to figure out what might be the problem but i can't see what i might be doing wrong.

Thanks

Exact error and stack trace follows:

[23:48:02]: Start TeamCity NUnit Test Runner

[23:48:02]:

NUnit Error: System.IO.FileNotFoundException: Could not load file or assembly 'nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77' or one of its dependencies. The system cannot find the file specified. File name: 'nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77'

Server stack trace: at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.Load(AssemblyName assemblyRef) at NUnit.Core.TestFramework.FromAssembly(Assembly assembly) at NUnit.Core.Builders.TestAssemblyBuilder.Load(String path) at NUnit.Core.Builders.TestAssemblyBuilder.Build() at NUnit.Core.Builders.TestAssemblyBuilder.Build(String testName) at NUnit.Core.TestSuiteBuilder.Build(String assemblyName, String testName) at NUnit.Core.SimpleTestRunner.Load(String assemblyName, String testName) at NUnit.Core.SimpleTestRunner.Load(String assemblyName) at NUnit.Core.ProxyTestRunner.Load(String assemblyName) at NUnit.Core.ProxyTestRunner.Load(String assemblyName) at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)

Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at NUnit.Core.TestRunner.Load(String assemblyName) at JetBrains.TeamCity.NUnitLauncher.NUnitRunner.LoadTest(String testAssembly, String testName, TestRunner runner) in c:\Agent\work\e34bdcb45e12f223\src\NUnitLauncher\src\NUnit-2.2\NUnitRunner.cs:line 33 at JetBrains.TeamCity.NUnitLauncher.AssemblyTest.LoadTestDomain() in c:\Agent\work\e34bdcb45e12f223\src\NUnitLauncher\src\AssemblyTest.cs:line 71 at JetBrains.TeamCity.NUnitLauncher.LoadTestDomainAction.Action(AssemblyTest test) in c:\Agent\work\e34bdcb45e12f223\src\NUnitLauncher\src\LoadTestDomainAction.cs:line 14 at JetBrains.TeamCity.NUnitLauncher.TryOneAssemblyTest.Action() in c:\Agent\work\e34bdcb45e12f223\src\NUnitLauncher\src\TryOneAssemblyTest.cs:line 18 at JetBrains.TeamCity.NUnitLauncher.TryOneAssembly.Do() in c:\Agent\work\e34bdcb45e12f223\src\NUnitLauncher\src\TryOneAssembly.cs:line 31

A: 

In your runner properties page, have you set Nant home to anything? We use %env.NANTHOME%. Be aware that it is case sensitive.

We also had to create a separate unit-test target for teamcity, so we call targets : clean compile run-unit-tests-teamcity.

Below is an extraction of our targets, tidied up a bit.

<target name="run-unit-tests">  
    <property name="test.executable" value="tools\nunit\nunit-console.exe"/>
    <property name="test.args" value="${test.assemblies} /xml=&quot;${build.fullpath}\test-reports\${prefix}_UnitTests.xml&quot; /nologo /exclude=WetTest" dynamic="true"/>     
    <call target="do-unit-tests"/>
</target>

<target name="run-unit-tests-teamcity"> 
    <property name="test.executable" value="${teamcity.dotnet.nunitlauncher}"/> 
    <property name="test.args" value="v2.0 MSIL NUnit-2.4.6 /category-exclude:WetTest ${test.assemblies}" dynamic="true"/>      
    <call target="do-unit-tests"/>
</target>

<!-- Run each of the unit tests in their own directory by project-->
<target name="do-unit-tests">

    <!-- Run the unit tests for component1 -->
    <property name="prefix" value="${prefix.component1}"/>
    <property name="test.assemblies" value="component1.Common.dll  component1.a.dll component1.b.dll component1.c.dll etc.dll"/>
    <property name="test.assembly.dir" value="${build.dir}\${prefix.component1}" />
    <call target="do-unit-test-single-project" />

    <!-- Run the unit tests for component2 -->
    <property name="prefix" value="${prefix.component2}"/>
    <property name="test.assemblies" value="component2.Common.dll  component2.a.dll component2.b.dll component2.c.dll etc.dll"/>
    <property name="test.assembly.dir" value="${build.dir}\${prefix.component2}" />
    <call target="do-unit-test-single-project" />

</target>

<target name="do-unit-test-single-project">

    <mkdir dir="${build.dir}\test-reports" />

    <!-- Ensure all tests have the default test config -->
    <copy file="${build.dir}\${prefix.component1}\Tests.config" tofile="${test.assembly.dir}\Tests.config" />

    <echo message="Starting NUnit code coverage run..."/>
    <property name="test.failed" value="false"/>

    <trycatch>
        <try>
            <ncover program="${path::get-full-path('tools\NCover\NCover.Console.exe')}"
                    commandLineExe="${test.executable}"
                    commandLineArgs="${test.args}"
                    workingDirectory="${build.dir}\${prefix}"
                    coverageFile="${build.fullpath}\test-reports\${prefix}_Coverage.xml"
                    logFile="${build.fullpath}\test-reports\${prefix}_coverage.log"
                    >
                    <assemblies basedir="${build.dir}\${prefix}">
                        <include name="${test.assemblies}"/> <!-- Only create the coverage for the specific project's assemblies -->
                    </assemblies>
            </ncover>
        </try>
        <catch property="failure">
            <echo message="At least one test failed: ${failure}"/>
            <property name="fail.message" value="${failure}"/>
            <property name="test.failed" value="true"/>
        </catch>
    </trycatch>

    <call target="create-coverage-report"/>
</target>

<target name="create-coverage-report">
    <ncoverexplorer program="tools\NCoverExplorer\NcoverExplorer.Console.exe"
                    projectName="NCoverExplorer"
                    reportType="4"
                    outputDir="${build.dir}\test-reports" 
                    xmlReportName="${prefix}_CoverageReport.xml"
                    htmlReportName="${prefix}_CoverageReport.html" 
                    mergeFileName="${prefix}_CoverageMerge.xml"
                    showExcluded="True"
                    satisfactoryCoverage="80" >
        <fileset basedir="${build.dir}\test-reports">
            <include name="${prefix}_Coverage.xml"/> <!-- Create a coverage report for each project group-->
        </fileset>
        <exclusions>
            <exclusion type="Namespace" pattern="*.Tests" />
        </exclusions>
    </ncoverexplorer>
</target>
Luke M