nant: best way to separate out nunit test dependency from production package - nunit

I have a nant project that builds my c# library, but has a dependency currently on nunit for building the test library portion of my project. Our users of the package have complained that they don't want this dependency in a production environment.
I'm new to nant configuration, so am looking for ways of making this dependency optional, or where you need to opt-in to it it for development building, perhaps as a target flag.

I don't think you can do so in Nant. But, since nant would work on the project files, you can add a condition to the project file like this -
<ItemGroup>
<MetaDataFile Condition="'$(Configuration)'=='Debug'" Include="$(BuildProjectFolderPath)/SubFolders/MyTestListFile.vsmdi">
<TestList>My Test List Name</TestList>
</MetaDataFile>
<TestContainer Condition="'$(Configuration)'=='Debug'" Include="$(OutDir)\MyTests.dll" />
Found this here.

Related

How to wrap a NUnit Engine Extension as a NuGet package?

I am working on a nunit engine extension which will be shipped as a nuget package.
Following the advises in How to implement NUnit's NUnit.Engine.ITestEventListener i was able to write the extension.
This solution is working as long as the project which contains the extension (the .cs file as well as the .addins file) is being imported to the target project which will perform the nunit tests.
As soon as I create a nuget package (following Quickstart: Create and publish a NuGet package using Visual Studio (.NET Standard, Windows only)) from the extension project and install this package to a test project, the extension doesn't work anymore.
I assume there is a problem with providing the .addins file within the nuget package so that the nunit engine in the target project can find the extension.
I already tried to ship the .addins file within the nuget package by adding the following lines to the .csproj file of the extension project.
<ItemGroup>
<Content Include="file.addins">
<Pack>true</Pack>
</Content>
</ItemGroup>
If I add the .addins file to the target project by hand, the engine extension starts working.
How can a nunit engine extension be shipped as a nuget package without any adjustments by hand?
Im using NUnit(3.13.2).
Im quite new to nunit, nuget and writing questions on stack overflow. So if I'm missing something obvious here, I'm sorry.
This is one of those areas where I wish things were less complicated, unfortunately. Since extensions are found through a relative path from the NUnit engine to the package content, it depends on where both the engine and runner are located and where the package is located on your machine.
Here are some initial guidelines...
How to structure the package itself... your extension assembly itself should be in the tools directory. If there are other assemblies with it, which it references, it's best to also include a .addins file in the same directory, which lists that assembly on a single line. That way, the NUnit engine will save time by only examining the extension assembly.
A NuGet extension package will automatically be found by the engine if the runner has been installed as a nuget package as well. This works no matter how the packages are installed on your machine, i.e. using packages.config or in a nuget cache, provided both packages were installed the same way. (That proviso is a real gotcha and it may be that a future version of the engine needs to actually understand nuget.) See the addins file provided with the the NUnit 3 console runner as an example of why this works.
The same thing is true if both the runner and the extension are installed as chocolatey packages, because they are both in the chocolatey cache. If you do provide one (which I recomend) it has to be a "native" package - one that includes the actual binaries. A chocolatey package that merely invokes the nuget package will not work. See the source for any of the NUnit-provided extensions for an example of how this this is done.
If the executing copy of the engine (usually in the same directory as the runner) is anywhere else, there is no automatic way for the extension to be found. This includes the case where you are building a runner yourself and want the extension to be available while you are developing. In that case, you need to fully understand how the engine finds extensions (see the docs) and manually create an addins file (next to any that was distributed with the engine) containing the proper relative path.
This is especially complicated if you are developing an extension for general release. Then you have to deal with various runners installed in different ways by different people. OTOH, if you are doing this for internal use in your company, you may only need to deal with one of them. If you add more specifics about your goal to the question, I'll edit this with some more specific suggestions.

Auto-increment NuGet package version

Is there a way to auto-increment the NuGet package version when using "Generate NuGetPackage on Build" in C#/.NET Standard 2.1?
If you build and publish the project by a build server, and manage the version by Git, you can try the MSBuild GitVersion task. For a similar issue, see here.
But if you just want a clean build and publish in local Visual Studio without using Git, then I'm afraid for now there isn't any Visual Studio option or MSBuild task to support this behavior. You can go to the Developer Community to suggest the feature because it's a meaningful idea, but currently it's not available.
Also, as from hints from Martin and Alexandre, you can add this script into xx.csproj:
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetPackageVersion</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetPackageVersion" DependsOnTargets="Build">
<PropertyGroup>
<!-- <PackageVersion>$([System.DateTime]::Now.ToString("yyyy.MM.dd.HHmmss"))</PackageVersion> -->
<!-- You can customize the format and the rule about how version increases here. -->
<PackageVersion>$([System.DateTime]::Now.ToString("1.MM.dd"))</PackageVersion>
</PropertyGroup>
</Target>
Then when you publish the package today, its version is 1.10.4. Tomorrow for 1.10.5, it works if you don't really need to publish different versions of one package in a day. Also you can customize the script to define your version-increasing rule.
If targeting multiple frameworks, see Build project with multiple targetframeworks in TFS as a NuGet package
This works when setting the assembly version to wildcard.
<Deterministic>false</Deterministic>
<AssemblyVersion>3.0.*</AssemblyVersion>
As of toDate with Visual Studio 2019 and .NET 5.0, what LoLance suggested about scripting the increment inside the .csproj file still works, and we now can use shell commands directly inside the package definition's PropertyGroup for multiple fields, as shown in the picture below:

What is nuget props file and what is it for?

I have looked around and read a lot but couldn't find a definitive answer that would explain as to what the "nuget.props" file is and what is it used for.
Any explanation and maybe with some example?
Starting with some background information, .NET projects are built with MSBuild. A C# project's .csproj is just a MSBuild project file with a file extension that signals by convention that it's C# and not some other language, but to MSBuild it's just a project file. MSBuild has only a few base types, properties, items, targets and tasks. By convention, properties and items go in files with extension .props, while tasks and targets go in files ending in .targets. That's why if you look at old-style csproj files you'll see <Import Project="path\to\Microsoft.Common.CSharp.props" /> and <Import Project="path\to\Microsoft.Common.CSharp.targets" />. New, SDK style projects is basically syntactic sugar to do exactly the same thing.
Next, the MSBuild and .NET teams made the build system extensible. So, rather than being limited to what Microsoft built into the C# compiler/build system, you can replace parts of the build system, or add additional things into it. Without NuGet, the way to do this is to create your own .props and .targets file somewhere, then edit your .csproj and add <Import ... /> statements. This can work fine if your props and targets are in the same source code repository as what's using it, but editing your csproj and hardcoding the path to the props and targets files doesn't work so well otherwise.
NuGet can help with this. If you create a package with the appropriate conventions, NuGet will make sure the props and targets are discovered and used in the build. With projects using packages.config, NuGet will edit the csproj for you on install/upgrade/uninstall. Projects using PackageReference, NuGet will write a file to the intermediate directory (obj/ folder) named nuget.g.props and nuget.g.targets, which imports all the props and targets files from all the referenced NuGet packages, and the build system uses these files.
The first example I could think of why someone would want to do this is if you want to use a newer version of the .NET compiler than is installed on your system. Simply reference the Microsoft.Net.Compilers package, and the .props and .targets in the package will replace the compile targets/tasks in the system-installed build system, and use the one from the package instead. This allows you to use new language features before the compiler is installed on your system, or if you want to make sure all builds of your code use the same compiler, even if different developers or CI agents have different versions of things installed.
Another example may be pre-compiled scripts. If you have your own scripting language, create build tools that converts them into C# files, then write MSBuild props and targets that will run before the "real build" to convert your custom language into C#, save the generated .cs files into the intermediate folder, add MSBuild Compile items for these generated files, then the C# compiler will compile it with all the other .cs files in the project. You'll need a reasonable amount of knowledge of MSBuild and the .NET build system, but it's possible.

NuGet - only add post processed file to a web project

I have a nuget package that can be applied to any type of C# project.
It has a file that is added to the project as part of the package. The NuSpec looks like this:
<files>
<file src="Content\App_Start\StartUpCode.cs.pp" target="content\App_Start" />
I am using WebActivator to run the code in the file at application start.
I run into a problem when the nuget package is applied to several projects in the same solution. I get several instances of the StartUpCode.cs added, and as a result WebActivator runs the code several times.
How can I stop this code from being added to a project that is not web related? I.e. it's cool to add it to a WebAPI project, or a WebForms project, but not a class library.
I don't think there's anything in the Nuget spec that would allow you to do that easily. Maybe use a Powershell install script and detect the type of project it's being installed into and/or if the assembly has been referenced previously?
Personally, I'd split it into two Nuget packages. One with the business logic, and then another with the WebActivator dependency.

ScriptSharp compilation with NAnt script

We've recently added the excellent script# to our project. Currently we have it so that our VS build simply copies the compiled .js file from the output directory to the scripts directory of our web app.
We've decided to make it a permanent feature and so would like to make it so that the .js file gets generated as part of our web build NAnt script to ensure that it's always up to date. Is there any way to do this nicely or do I need to call MSBuild from my NAnt script specifying the .csproj file to run the compilation?
Thanks
Stu
This isn't likely the full answer (given I don't have experience with NAnt), but I'll offer it anyway, as it may help.
A script# csproj is very much like any other csproj relying on msbuild. If you've got some way to integrate other msbuild projects into your NAnt build script, the same model should ideally apply to script# projects as well.
In the version of script# that is in the github repository, a web project can add a reference to a script# project (thereby becoming dependent on the script# project), and include an msbuild deploy task, that will copy over scripts from the built script# project into the web project. You can see this in action in the Todo sample (https://github.com/nikhilk/scriptsharp/tree/cc/samples/Todo)