XUnit doesn't work during MSBuild - c#

I'm a newcomer to Xunit and I'm trying to run it via MSBuild. Following the documentation, here is my build script so far:
<UsingTask AssemblyFile="..\packages\xunit.runner.msbuild.*\build\*\xunit.runner.msbuild.dll"
TaskName="Xunit.Runner.MSBuild.xunit"/>
<Target Name="Test">
<xunit Assemblies="bin\$(Configuration)\Core.dll"/>
</Target>
When I run MSBuild on the .csproj, however, it gives me the following error:
error MSB4127: The "Xunit.Runner.MSBuild.xunit" task could not be instantiated from the
assembly "C:\Users\James\libvideo\tests\Core\packages\xunit.runner.msbuild.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.runner.msbuild.dll".
Please verify the task assembly has been built using the same version of the Microsoft.Build.Framework
assembly as the one installed on your computer and that your host application is not missing
a binding redirect for Microsoft.Build.Framework. Unable to cast object of type
'Xunit.Runner.MSBuild.xunit' to type 'Microsoft.Build.Framework.ITask'.
I've checked that the path it's looking for exists, and I've also followed the steps here. No luck, however. What can I do to resolve this?

This error is normally due to a mismatch in your MSBuild Tools Version. This is defined in the <Project> root element. The tools version you are running is from a version of the ITask interface different from that of the xunit runner so without an assembly binding redirect, it cannot cast between the different versions of ITask.
https://msdn.microsoft.com/en-us/library/bb383796.aspx

Related

Error: Could not load file or assembly 'Microsoft.Win32Registry' from .NET Standard Library Consumed by .NET Framework Console App

The Problem
The Microsoft.Win32.Registry nuget package is giving me a lot of issues . We had .NET Framework 4.7.2 library that had a helper class that used that package and worked fine from a .NET Framework 4.7.2 unit test project. We recently converted the library to target .NET Standard 2.0, and now this class breaks when used with the following error:
ERROR: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at NetStandardRegistryLib.RegistryUtil..ctor(String remoteMachineName)
at NetStandardRegistryLib.Program.Main(String[] args) in C:\src\Microsoft.Win32.Registry-IssueRepro\FrameworkRegistry\RegistryEditor\Program.cs:line 21
When I look at output of the Console project, I don't see the Microsoft.Win32.Registry.dll in the output.
Using ILSpy and loading my .exe - it seems it would try to resolve the .dll from my dotnet core installation, which wouldn't work since it's a .NET Framework app.
To Reproduce
I've created a repo that reproduces for me on my Windows 2010 machine. You can find it here: https://github.com/TylerNielsen/Microsoft.Win32.Registry-IssueRepro
Clone the repo, then open and build the RegistryEditor project.
Using Powershell or your favorite editor - call the tool with three required arguments [remoteMachineName] [Environment variable name to set] [Value to set on the environment variable] **
** Note, this actually requires a remote machine you can reference by IP address. For some reason using 127.0.0.1 doesn't work for me, but I'm unsure why. The use case for this utility is for accessing remote machine environment variables.
Other Notes
When I create a .NET Framework Class Library to use for unit tests and reference the same .NET Standard Library - the Microsoft.Win32.Registry package is included and the utility runs just fine.
In your repo, if you look into both csproj files you'll see they are quite different. The NetStandardRegistryLib.csproj is the new format, the RegistryEditor.csproj is the old one.
Your problem is that old style projects do not resolve dependencies transitively. RegistryEditor will not copy dependencies of its own dependency NetStandardRegistryLib.
There are at least two ways to solve your problem:
Just add Microsoft.Win32.Registry Nuget package to RegistryEditor project explicitly. That'll make the Microsoft.Win32.Registry.dll to appear in the RegistryEditor build folder.
Convert the RegistryEditor.csproj to new format. It's not limited to netstandard builds, you can use it for builds targeting .Net Framework versions as well. And it does resolve dependencies transitively!
Here's a long guide for how to do the conversion in general https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/
Since your project is quite simple, I've converted it for you. Just replace the content of RegistryEditor.csproj with the code below. It's still targeting net472.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>RegistryEditor</AssemblyName>
<RootNamespace>RegistryEditor</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NetStandardRegistryLib\NetStandardRegistryLib.csproj" />
</ItemGroup>
</Project>
Note that several properties that used to be in AssemblyInfo.cs file are provided by csproj file properties now, so you need to remove them from AssemblyInfo.cs to fix compilation errors:
[assembly: AssemblyTitle("RegistryEditor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RegistryEditor")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Running DotNet Build Causes Microsoft.Build.Tasks.CodeAnalysis.dll Assembly Conflict

I'm having an issue trying to build a dotnet core project from command line that has these references:
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.6.1" />
<PackageReference Include="Microsoft.Net.Compilers" Version="2.6.1" />
For whatever reason it keeps saying Microsoft.Build.Tasks.CodeAnalysis.dll assembly has already been loaded. Here is the exact error message:
C:\Users.nuget\packages\microsoft.net.compilers\2.6.1\tools\Microsoft.CSharp.Core.targets(84,5):
error MSB4062: The "Microsoft.CodeAnalysis.BuildTasks.Csc" task could
not be loaded from the assembly
C:\Users.nuget\packages\microsoft.net.compilers\2.6.1\build..\tools\Microsoft.Build.Tasks.CodeAnalysis.dll.
Assembly with same name is already loaded Confirm that the
declaration is correct, that the assembly and all its dependencies are
available, and that the task contains a public class that implements
Microsoft.Build.Framework.ITask.
When I go to that project directory and run dotnet build It has no issues building the project, but when I run dotnet build against the solution that's when I get this error. If I build the solution from Visual Studio it also has no issues building. Really strange behavior, not quite sure how to get around it.

How to determine the version of MSBuild an assembly was built with?

I'm trying to run my first xUnit.net tests via MSBuild and I'm following the documentation here. Here is my project file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build;Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\xunit.runner.msbuild.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.runner.msbuild.props"
Condition="Exists('..\packages\xunit.runner.msbuild.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.runner.msbuild.props')" />
<!--Extra lines omitted for brevity-->
<UsingTask AssemblyFile="xunit.runner.msbuild.dll"
TaskName="Xunit.Runner.MSBuild.xunit"/>
<Target Name="Test">
<xunit Assembly="bin\$(Configuration)\Core.dll"/>
</Target>
</Project>
When I run MSBuild, however, it gives me the following error:
C:\Users\James\libvideo\tests\Core\Core\Core.csproj(85,5):
error MSB4127: The "xunit" task could not be instantiated from the assembly "C:\Users\James\libvideo\tests\Core\packages\xunit.runner.msbuild.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.runner.msbuild.dll".
Please verify the task assembly has been built using the same version of the Microsoft.Build.Framework assembly as the one installed on your computer and that your host application is not missing a binding redirect for Microsoft.Build.Framework.
Unable to cast object of type 'Xunit.Runner.MSBuild.xunit' to type 'Microsoft.Build.Framework.ITask'.
I've checked that the spelling is correct, however it's still giving me this error. The xUnit.net documentation says nothing about this (or at least from where I've looked), so I'm stuck at what to do now. It tells me that I can check the version of MSBuild the assembly was built with, but how do I do that? Is MSBuild even required to build an assembly?
(MSBuild says it's version 14.0.23107.0, I have VS2015 if that's important.)
Thank you!
MSBuild is based on tasks and targets. You can see what it looks like in a .csproj, usually at the end. The task object is defined in the version of MSBuild you are using, located in, for example, C:\Program Files (x86)\MSBuild\12.0\Bin.
Version of MSBuild typically follows the .NET framework like this:
version 1.0: 2006
version 2.0:
version 3.5: 2011
You probably miss the right version of MSBuild. Or you can try with a different version than ToolsVersion="14.0".

NuGet Pack -Build does not seem to understand c# 6.0

I have just went through one of my projects and used a bunch of the new c# 6 features like the null propagation operator handler?.Invoke(null, e), which builds in Visual Studio. However, when I run my script to publish out the NuGet packages, I get compilation errors saying:
EventName.cs(14,66): error CS1056: Unexpected character '$'
EventName.cs(69,68): error CS1519: Invalid token '=' in class, struct, or interface member declaration
EventName.cs(69,74): error CS1520: Method must have a return type
It would appear NuGet is using an older version of the compiler, but I was wondering if anyone knew a work around or configuration that could be set to resolve the issue.
Looks like you have also found this bug in the Nuget which is still not resolved:
https://github.com/NuGet/Home/issues/1107
You can use the following workaround:
Modify the script to build your project using correct version of MSBuild - just call MSBuild.exe yourself, supply the path to the csproj or sln file and build your project in a correct configuration yourself.
Create a nuspec file that describes your package (https://docs.nuget.org/create/nuspec-reference). You can use the Nuget Package Explorer app. Use DLLs produced in step 1.
Use nuget pack mypackage.nuspec to build the package.

How to Configure Bamboo to Build NUnit Tests?

I am working on setting a project to use bamboo for CI testing, but have hit a hitch when attempting to compile unit tests. We are using the .NET framework 4.5 and NUnit v2.6.3.13283. When I am in bamboo, I have set up the specific job to check out the source code when a new commit is pushed, and then use MSBuild to build the code. Unfortunately, when it reaches this second step, it decides that it no longer understands what NUnit is.
I have the nunit.framework.dll in the same directory (bin\Debug) as the class .dll, so I'm definitely confused as to how I should go about having MSBuild work out building the NUnit tests.
Any help would be appreciated.
EDIT: Error log for those not faint of heart.
c:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig
/nowarn:1701,1702 /nostdlib+ /platform:AnyCPU /errorreport:prompt
/warn:4 /define:DEBUG;TRACE
/reference:c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll
/reference:C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll
/reference:"C:\build-dir\UCL-UNL-JOB1\Unit Class
Library\bin\Debug\Unit Class Library.dll" /debug+ /debug:full
/filealign:512 /optimize-
/out:obj\Debug\UnitClassLibraryNUnitTests.dll /target:library
AngleNUnitTests.cs
"C:\Users\Bamboo\AppData\Local\Temp.NETFramework,Version=v4.5.AssemblyAttributes.cs"
AngleNUnitTests.cs(5,7): error CS0246: The type or namespace name
'NUnit' could not be found (are you missing a using directive or an
assembly reference?)
[C:\build-dir\UCL-UNL-JOB1\UnitClassLibraryNUnitTests\UnitClassLibraryNUnitTests.csproj]
AngleNUnitTests.cs(12,10): error CS0246: The type or namespace name
'Test' could not be found (are you missing a using directive or an
assembly reference?)
[C:\build-dir\UCL-UNL-JOB1\UnitClassLibraryNUnitTests\UnitClassLibraryNUnitTests.csproj]
etc.
You need to use a previous task to MSBuild one (Maybe you could consider to use the VisualStudio Task it works like a charm).
This previous task is a Command Task, it will update the Dlls related to the NuGet Package, in order to achieve it:
Create a New Executable on Bamboo, pointing to the nuget.exe file (if you don't have it you could download from https://www.nuget.org/
Create a New Command Task with the executable your created on the previous step.
On the Argument field: "restore YourSolution.sln"
In my approach I am using a VisualStudio task and after this one a MSTest Runner task.
When using Nuget with a source code repository, you have a couple of options.
1) check in your nuget executable to source code and create a bamboo command task that calls that location relative to the build directory, ${bamboo.build.working.directory}\tools\Nuget.exe.
2) Install the Nuget exe directly on the build server. Then you can create a new executable on Bamboo that you can reference in any task.
To create a new executable for use in tasks, use this - https://confluence.atlassian.com/display/BAMBOO/Defining+a+new+executable+capability
I guess you are using NuGet?
If so, you need to enable NuGet Package restore, because MSBuild does not know how to resolve these NuGet packages. This will create a .nuget directory in your solution which needs to be pushed the repository bamboo uses for the build.
Second problem I encountered when configuring the NUnit test runner with bamboo: the nunit-console.exe uses .NET Framework 3.5 which was not installed on my build server.

Categories