TeamCity and running NUnit tests - nunit

In TeamCity, i need to state exact locations of assemblies that contain NUnit tests to be executed.
Is there an option to state a .SLN file so it will look up these test projects dynamically?

You can use wildcard expressions in the Run tests from box:
Source\\**\bin\\**\*Tests.dll
The above would run tests from any assembly under any bin folder under the Source folder which contains 'Tests' at the end of the assembly name.

Depending on whether you're using MSBuild or NAnt, you can add an entry to your build script like this:
<ItemGroup>
<TestAssemblies Include="tests\\test*.dll"/>
<TestAssemblies Include="tests.lib\\test*.dll"/>
</ItemGroup>
<Target Name="runTests">
<Exec Command="$(teamcity_dotnet_nunitlauncher) v2.0 x86 NUnit-2.5.0 %(TestAssemblies)" />
</Target>
In the example above, the two TestAssemblies lines point to your assemblies.
You can read more about this here: http://blogs.jetbrains.com/teamcity/2008/09/24/using-teamcity-nunit-launcher/

Related

Azure Function PostBuild File Copy being lost

I'm doing an MSBuild in Visual Studio of a C# Azure Function. Most of the content is placed in $(TargetDir)/bin. I need to copy the Api.dll from there to $(TargetDir) for Entity Framework Migration. eg:
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo copy /Y "$(TargetDir)bin\Api.dll" "$(TargetDir)"" />
</Target>
The copy appears to work, but is not there when the build is completed.
If I do the copy as a batch file with a directory listing before and after the file IS copied.
But its not there when I try to do add-migration
So I guess the project build is recreating the Target folder after PostBuildEvent ???
The Api project builds OK but when I run add-migration fist I get:
An assembly specified in the application dependencies manifest (Api.deps.json) was not found:
package: 'Api', version: '1.0.0'
path: 'Api.dll'
The dll is not in $(TargetDir) but one folder lower in $(TargetDir)bin
this is due to RemoveRuntimeDependencies task removes this assemblies. Add <_FunctionsSkipCleanOutput>true<_FunctionsSkipCleanOutput> to .csprojwithinPropertyGroup.

NuGet: Two packages with targets files lead to incorrectly copied DLLs

I have created two NuGet packages that contain Native Libraries. The first one has two subfolders (amd64 and x86) the second one includes the DLL flat under the build directory. The NativeLibraries of the the first package are supposed to be copied into subfolders of the OutputPath. The only DLL in the second package should be copied flat under the OutputPath. I used the following stackoverflow entry as a guide for creating the package: https://stackoverflow.com/a/30316946/4496150
The first NuGet package folder structure looks like this (amd64 and x86 subfolder under build):
build
amd64
DLL1.dll
DLL2.dll
x86
DLL1.dll
DLL2.dll
packagename.targets
First targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
<None Include="#(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory)** as NativeLibs Include and %(RecursiveDir) as part of Link attribute.
The second NuGet package structure looks like this (no subfolders under build):
build
DLL1.dll
packagename.targets
Second targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll" />
<None Include="#(NativeLibs)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory) (without **) as NativeLibs Include and missing %(RecursiveDir) in Link attribute.
If you reference both packages, the DLLs from the first package are additionally copied flat into the output folder, which is not desired. I suspect this is because the second include step also reads the DLLs from the first package, but then does not use %(RecursiveDir).
A workaround is to also include in the second package both.
and NativeLibs Include="$(MSBuildThisFileDirectory)***.dll" /> exactly as in the first package.
However, I would prefer to understand why the second package ensures that the DLLs from the first are copied flat.
If I read https://learn.microsoft.com/de-de/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2019 correctly, $(MSBuildThisFileDirectory) points to the folder in my NuGet cache where the targets file of the NuGet package is located. So actually everything would be correct. But still (probably) wrong DLLs are copied.
Edit
I added the following snippet in both targets files to get some output:
<Target Name="OutputPackage1NativeLibs" BeforeTargets="Build">
<Message Text="Package1 %(NativeLibs.Identity)" Importance="high"/>
</Target>
For the seconds targets file I changed the target name to OutputPackage2NativeLibs and started the text Output with Packag2.
When I clean my NuGet Package Cache and rebuild the solution everything is fine. But after the third or forth rebuild operation the DLLs of the first package are copied flat under the Output path and I get the following output:
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
So NativeLibs are added from the other NuGet package apparently after the third or fourth rebuild.
I think you are using Packages.config nuget package format with non-sdk net framework projects. If so, that could be explained.
For packages.config nuget management format, it imports the target files directly under csproj file. In my side, I created two nuget packages called flat 1.0.0 and faltt 1.0.0 nuget packages.
You can check my csproj file:
If so, the first import targets file flat.targets file is the same as your first nuget package's targets file:
It includes the x86 and amd64 folder files into output folder\x86 and output folder\amd64 folder, that is right as we excepted.
However, under pakckages.config, since the two targets file are in the same csproj file, they can access each other(they have the same life cycle in the same CSProj), when msbuild reads faltt.targets file after flat.targets file, also you did not change NativeLibs item for the second targets file, itself has the file:
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll2.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
When reads the flatt.targets file, it also includes C:\Users\xxx\source\repos\flat\packages\flatt.1.0.0\build\x86\Dll1.dll,
So it has five files under NativeLibs item.
And then it executes <Link>%(FileName)%(Extension)</Link>, the first nuget package's dlls will be executed under the second nuget packages's node, output to the output root folder.
Because of the special nature of Packages.config import targets files, they are interlaced.
You should note that
Under PackageReference nuget management format, the import targets files are stored under obj\xxx.csproj.nuget.g.targets file, like this:
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets" Condition="Exists('$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets')" />
<Import Project="$(NuGetPackageRoot)flat\1.0.0\build\flat.targets" Condition="Exists('$(NuGetPackageRoot)flat\1.0.0\build\flat.targets')" />
</ImportGroup>
Since the content is not in csproj file and the particularity of the file xxx.csproj.nuget.g.targets, it will read the targets files in each nuget package separately. Each file is a separate life cycle, so it does not Will affect each other. This is also one of the advantages of the latest PackagesReference nuget management format.
Sorry for not telling you at the beginning that I was using packagesReference and I didn't notice packages.config.
So if you want to get the right behavior to separate them, try the two approaches:
1) do not change the two nuget packages, right-click on the packages.config file of the main project which installs the two nuget packages-->click Migrate packages.config to PackageReference option
After that, click Rebuild option to get that.
2) modify the nuget packages--> change the NativeLibs item's name to another for the second nuget package targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs1 Include="$(MSBuildThisFileDirectory)*.dll" />
<None Include="#(NativeLibs1)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
When re-pack your project, uninstall them first, delete all cache files under C:\Users\xxx\.nuget\packages. And then re-install the packages again.

Run a command in ccnet.config

I am trying to run the nuget command that I would normally set in the projects post build $(ProjectDir)nuget\pack.bat $(ProjectDir) $(TargetDir) $(ConfigurationName) $(SolutionDir) to run instead in the ccnet.config on a successful build. What I have does not seem to be running at all.
<exec>
<Target>
<executable>cmd</executable>
<buildArgs>/C c:\build\project\nuget\pack.bat c:\build\project\ c:\build\project\bin\nuget\ Nuget c:\build\project\ /M</buildArgs>
</Target>
</exec>
Edit
Figured it out partially. Needed to make sure I was pointing to <executable>c:\Windows\System32\cmd.exe</executable> and not using cmd.

NuGet - install.ps1 does not get called

I'm trying to create my first NuGet package. I don't know why my install.ps1 script does not get called. This is directory structure
--Package
|
- MyPackage.nuspec
- tools
|
- Install.ps1
- some_xml_file
I build package using this command line
nuget.exe pack MyPackage.nuspec
When I Install-Package from VS Package Manager Console install.ps1 does not get called.
I thought that maybe I had some errors in script and that's the reason so I commented out everything but
param($installPath, $toolsPath, $package, $project)
"ECHO"
But I don't see ECHO appearing in Package Manager Console. What can be wrong?
Install.ps will only be invoked if there is something in the \lib and/or \content folder, not for a "tools only" package, though. See here:
The package must have files in the content or lib folder for Install.ps1 to run. Just having something in the tools folder will not kick this off.
Use the Init.ps1 instead (however, this will be executed every time the solution is opened).
Install.ps1 (and Uninstall.ps1) are no longer called in v3, but you can use Init.ps1. See here:
Powershell script support was modified to no longer execute install
and uninstall scripts, but init scripts are still executed. Some of
the reasoning for this is the inability to determine which package
scripts need to be run when not all packages are directly referenced
by a project.
An alternative to the install script can sometimes be a package targets file. This targets file is automatically weaved into the project file (csproj, ...) and gets called with a build.
To allow Nuget to find this targets file and to weave it in, these two things are mandatory:
the name of the targets file must be <package-name>.targets
it must be saved in the folder build at the top level of the package
If you like to copy something to the output folder (e.g. some additional binaries, like native DLLs) you can put these binaries into the package under folder binaries and use this fragment in the targets file for the copying:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyBinaries" BeforeTargets="BeforeBuild">
<CreateItem Include="$(MSBuildThisFileDirectory)..\binaries\**\*.*">
<Output TaskParameter="Include" ItemName="PackageBinaries" />
</CreateItem>
<Copy SourceFiles="#(PackageBinaries)"
DestinationFolder="$(OutputPath)\%(RecursiveDir)"
SkipUnchangedFiles="true"
OverwriteReadOnlyFiles="true"
/>
</Target>
</Project>

MSBuild.exe not accepting either /p:DefineConstants nor /p:PreprocessorDefinitions

I've been through quite a number of articles on Stack Overflow that answered the question "How do I pass preprocessor definitions to the compiler from the MSBuild command line," and they all responded with some variation of:
MSBuild.exe /p:DefineConstants=THING_TO_BE_DEFINED
I have tried every variation that I could come up with:
MSBuild.exe "/p:DefineConstants=THING_TO_BE_DEFINED"
MSBuild.exe /p:DefineConstants="THING_TO_BE_DEFINED"
MSBuild.exe "/p:DefineConstants=THING_TO_BE_DEFINED=1"
MSBuild.exe /p:DefineConstants="THING_TO_BE_DEFINED=1"
...and dozens of others. I've also flirted with overriding PreprocessorDefinitions in similar ways. All of them triggered the #error below:
#include "stdafx.h"
#if !defined(THING_TO_BE_DEFINED)
#error "THING_TO_BE_DEFINED is not defined"
#endif
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
I've been trying this with the simple command-line application above, as well as with a huge game project that I have here. I can only guess that Visual Studio (I'm seeing this with 2005 and 2008) has some default set deep in its bowels that is preventing my command line argument from being applied, but I've found no evidence to support this hypothesis.
Any ideas on how I can get this to work? Why in the name of FSM didn't they stick with good ol' -D THING_TO_BE_DEFINED?
If you are calling MSBuild on the command line you cannot specify the value for DefineConstants. But if you are building a .csproj, or another MSBuild script, then you can specify it. If you create a msbuild file to "replace" your solution file then you can use that an specify the value for that when you build your projects. For example:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Default value here -->
<DefineConstants Condition=" '$(DefineConstants)'==''" >DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Projects Include="one.csproj" />
<Projects Include="two.csproj" />
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(Projects)"
Properties="DefineConstants=$(DefineConstants)"/>
</Target>
</Project>
Then you can use msbuild.exe buid.proj /p:DefineConstants="YourValue;Debug;Trace"
Note the usage of the quotes on the command line.
I have written a blog post a while back about something related to this at http://sedodream.com/2008/05/07/MSBuildBuildingTheSameProjectMultipleTimes.aspx.
If you want to define TRACE & DEBUG Constants this should work:
msbuild mysln.sln /t:Rebuild /p:Configuration=Release /p:DefineConstants="DEBUG;TRACE"
The below are needed modification to the vcxproj for the /p to work.
put
<DefineConstants>< /DefineConstants>
under the <PropertyGroup Label=Globals >
<PreprocessorDefinitions>$(DefineConstants);WIN32;_DEBUG;_CONSOLE;UNIT_TEST_SIM;%(PreprocessorDefinitions)
This way MSBuild will know that for the preprocessor it needs to use the values from the DefineConstants which come from the Globals PropertyGroup unless provided from the command line by the /p:DefineConstants="MY_DEFINE"
For completeness, this is what I found worked when I wanted THING_TO_BE_DEFINED="VALUE WANTED", for VB.NET, and msbuild version 3.5.30729.1, in a batch file:
#msbuild /t:Rebuild /p:Configuration=Release;Platform="Any CPU";
DefineConstants="THING_TO_BE_DEFINED=\"VALUE WANTED\"" mysln.sln
(all on one line of course)