Specify MSTest parameters in MSBuild - msbuild

I'm trying to prevent certain (MSTest) unit tests from being run on our build server. I'd really like to just add a TestCategory, and then specify:
/category:"!RequiresLoginCredentials"
But I'm not sure how to indicate that in the msbuild project file.
The relevant section of the build file currently has:
<ItemGroup>
<!-- TEST ARGUMENTS
If the RunTest property is set to true then the following test arguments will be used to run
tests. Tests can be run by specifying one or more test lists and/or one or more test containers.
To run tests using test lists, add MetaDataFile items and associated TestLists here. Paths can
be server paths or local paths, but server paths relative to the location of this file are highly
recommended:
<MetaDataFile Include="$(BuildProjectFolderPath)/HelloWorld/HelloWorld.vsmdi">
<TestList>BVT1;BVT2</TestList>
</MetaDataFile>
To run tests using test containers, add TestContainer items here:
<TestContainer Include="$(OutDir)\HelloWorldTests.dll" />
<TestContainer Include="$(SolutionRoot)\TestProject\WebTest1.webtest" />
<TestContainer Include="$(SolutionRoot)\TestProject\LoadTest1.loadtest" />
Use %2a instead of * and %3f instead of ? to prevent expansion before test assemblies are built
-->
<TestContainer Include="$(OutDir)\UnitTests.dll" />
</ItemGroup>
I'm guessing this is a simple addition, but I know very little about msbuild.
Thanks!

I did a quick search for the answer and I think there are two possible solutions:
From what you described, looks like you're trying to run the tests using the TestToolTask task of MSBuild. Unfortunately, I don't think you can pass MSTest arguments directly to this task. To accomplish what you want, you need to specify the tests you want to run in a test list, and pass the test list to this task. You need to use the MetadataFile property as shown in the example in your post.
You can invoke MSTest.exe directly using the Exec task of MSBuild. This way you have the freedom to pass in the arguments you want.

Related

Why is it called response file

MBuild can use response files to save and run commands. But why is it called response file? What is it responding to?
(Also in an MsBuild file the task elements are called Target. What is 'target' refering too?)
A target represents a collection of things you want to do. In an msbuild file, it is represented by an xml element that can have various child xml elements called tasks.
Conceptually it looks like this:
<Target Name="Foo">
<Task />
<AnotherTask />
</Target>
The target you want to execute can be passed in as a command line parameter to msbuild. There are other ways to execute the target of your choice, but you will need to read the docs for that:
https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild?view=vs-2019
In other build systems, a target can be called a goal.
Note:
Some build systems use a very rigid convention, where files have to be in certain places. MSBuild is not like that. It relies on configuration, where you can configure it any way you like. The only convention's really are the xml syntax and schema that you have to follow.
As for the response file name. Who knows and who cares anyways? It's just an extra place to put more command line parameters. I don't rely on it, and neither should you. If you know what you are doing you can stick all that stuff in a proper msbuild xml file and just invoke msbuild to kick off a build.

Target not running when using BeforeTargets="Build" on Build Server

I have a custom .targets file which I import into my C# MVC web application's project file. I've added custom targets to this like so:
<Target Name="CopyFiles" BeforeTargets="Build"></Target>
This works fine when building under Visual Studio, but when I use TeamCity to build it, the target never gets run, and I can't work out why.
If I change my target to use BeforeTargets="Compile" then it runs. Alternatively, if I add an additional target with the name Build to the .targets file
<Target Name="Build" />
then it will run, but doing so overrides the existing Build target and thus my application doesn't build. I can't quite make out the logic to this - it doesn't make sense. I'm using the Compile target for now, but if someone could explain why trying to execute it before the Build task doesn't work I'd really appreciate it.
'Build' is a special built-in target, so doesn't really work the same way as most other targets. It definitely can't be safely overridden.
The most relevant documentation is here: https://msdn.microsoft.com/en-us/library/ms366724.aspx
If you want something to run before build, the standard approach (as recommend by the comments in a newly-created .csproj file) is to override the BeforeBuild target (as documented above).
However, this isn't the most robust solution. As noted in the documentation above:
Overriding predefined targets is an easy way to extend the build process, but, because MSBuild evaluates the definition of targets sequentially, there is no way to prevent another project that imports your project from overriding the targets you already have overridden.
It's better (and only slightly more complex), to override the BuildDependsOn property and extend the default value of this property to include the target you want to run (this is also documented in the link above).
Another approach would be to leave BeforeBuild empty and use BeforeTargets="BeforeBuild", which feels a bit odd but is quite simple and will still work even if the BeforeBuild target gets overridden.
As to why BeforeTargets="Build" doesn't work, I can't find a reference for this in the documentation, but I think it's to do with its special nature. It doesn't work the same as ordinary targets and it's probably better not to think of it as a target at all.

TeamCity MSTest and TestList?

In order to automate unit tests on TeamCity I had to create a test list in my vsmdi configuration file indicating that every test is part of a list I called CompleteCoverage. I dislike this a lot because in order to auto-run new tests I'll have to remember to include them on this list.
Is there some way to run every test in the solution using TeamCity and MSBuild (other than explicitly referencing the path to the output test assembly)?
Should I just drop MSTest and go for NUnit?
I'm using NUnit instead of MSTest, but this should work for you, too:
I've named all my test assemblies to include .NUnit in their name, e.g. Basic.NUnit.dll. In the build step performing the tests, I've declared **/*.NUnit.dll as the assemblies to run. To make sure that they are run in the right location, I've added **/obj/**/*.NUnit.dll to the exclude list. Together with test categories to in- or exclude, I've got perfect control over which tests to run on a purely declarative level without to name the individual tests.

Dividing work of MSBuild into projects

I'm starting to create a MSBuild scripts for my products, and I've encounter a dilema.
The code is divided into around 25 projects, some wll require obfuscation, some will require strong-name signing; others will require linking into a single file.
All these projects should result in 3 products, with 3 setups.
The question at hand is as follow: How do I divide the MSBuild scripts to make most sense?
Do I create a script for each product? do I create a script for each project? Do I have one script for building, another for obfuscation and so on?
I think this is good idea to have script per product.
To minimaze dublication create reusable "sub-scripts" and import them to main script (this could be done with Import directive).
<Import Project="..\Steps\Step1.proj" />
Script per product sounds like the way to go. You may want to consider having any number of shared or base scripts too, to import common build steps. Like Mike Chaliy already mentioned you can then use Import in your product's build script:
<Import Project="..\Shared\Base.proj" />
Another thing you might also want to take advantage of is target and property overriding. It's akin to overriding virtual methods in a .Net class. See the documentation and the MSBuild Team Blog for more details. I know I've taken advantage of this quite often by setting defaults in the included scripts then overriding them as necessary in the product build script in order to customize build behaviour. For instance I often have generated files that are required before the build so I hook those targets into the BuildDependsOn property group. This way my generated files are generated whenever I do an F5 from the IDE, call the build target from the command line or otherwise build the project or solution. Obviously if you have any build steps that run long or only need to be run in special circumstances (like building installers), you'll want to take care about exactly what gets hooked in.

Ant equivalent of Maven profiles?

Is there an Ant equivalent to the 'profile' concept in Maven?
I'd like to be able to specify a different set of targets to build (out of one Ant file) depending on an argument. So in Maven I can specify a profile and then activate it like so: mvn groupId:artifactId:goal -Denvironment=test
So say my build.xml contains:
<target name="profile1">...</>
and
<target name="profile2">...</>
How could I specify at compile time which I want to execute?
You can pass arguments to ant when you invoke it
ant -DProfile=foo
Then ${Profile} will substitute for foo
This is a sucky workaround but it should be able to pass arguments via the command line if that is your goal.
You can read properties from files using the property or loadproperties tasks.
Depending on exactly what you're trying to replicate this might do.
For the first case: "ant profile1". The second case is left as an exercise.
Seriously, the list of targets you want to execute is already an argument to ant. I think you need to make your example a little more explicit.