Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for DoNotParallelize for MSTest V2 parallelism #996

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
<Compile Include="TestGenerator.cs" />
<Compile Include="TestGeneratorFactory.cs" />
<Compile Include="UnitTestConverter\IFeatureGeneratorProvider.cs" />
<Compile Include="UnitTestProvider\MsTestV2GeneratorProvider.cs" />
<Compile Include="UnitTestProvider\NUnit3TestGeneratorProvider.cs" />
<Compile Include="UnitTestProvider\UnitTestGeneratorProviders.cs" />
<Compile Include="UnitTestProvider\MbUnit3TestGeneratorProvider.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using TechTalk.SpecFlow.Utils;

namespace TechTalk.SpecFlow.Generator.UnitTestProvider
{
public class MsTestV2GeneratorProvider : MsTestGeneratorProvider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inherit from MsTest2010GeneratorProvider, so you can reuse much more code

{
private const string CATEGORY_ATTR = "Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make the fields on MsTest2010GeneratorProvider protected if you need them in this class

private const string OWNER_ATTR = "Microsoft.VisualStudio.TestTools.UnitTesting.OwnerAttribute";
private const string WORKITEM_ATTR = "Microsoft.VisualStudio.TestTools.UnitTesting.WorkItemAttribute";
private const string DEPLOYMENTITEM_ATTR = "Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute";
private const string DONOTPARALLELIZE_ATTR = "Microsoft.VisualStudio.TestTools.UnitTesting.DoNotParallelize";

private const string OWNER_TAG = "owner:";
private const string WORKITEM_TAG = "workitem:";
private const string DEPLOYMENTITEM_TAG = "MsTest:deploymentitem:";
private const string DONOTPARALLELIZE_TAG = "MsTest:donotparallelize";

public MsTestV2GeneratorProvider(CodeDomHelper codeDomHelper) : base(codeDomHelper)
{
}

public override UnitTestGeneratorTraits GetTraits()
{
return UnitTestGeneratorTraits.ParallelExecution;
}

public override void SetTestClassCategories(TestClassGenerationContext generationContext, IEnumerable<string> featureCategories)
{
generationContext.CustomData["featureCategories"] = GetNonMSTestSpecificTags(featureCategories).ToArray();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change the base class, this could be a simple base.SetTestClassCategories(generationContext, featureCategories).
No need to copy the whole function.


IEnumerable<string> ownerTags = featureCategories.Where(t => t.StartsWith(OWNER_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (ownerTags.Any())
{
generationContext.CustomData[OWNER_TAG] = ownerTags.Select(t => t.Substring(OWNER_TAG.Length).Trim('\"')).FirstOrDefault();
}

IEnumerable<string> workItemTags = featureCategories.Where(t => t.StartsWith(WORKITEM_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (workItemTags.Any())
{
int temp;
IEnumerable<string> workItemsAsStrings = workItemTags.Select(t => t.Substring(WORKITEM_TAG.Length).Trim('\"'));
if (workItemsAsStrings.Any())
{
generationContext.CustomData[WORKITEM_TAG] = workItemsAsStrings.Where(t => int.TryParse(t, out temp)).Select(t => int.Parse(t));
}
}

IEnumerable<string> deploymentItemTags = featureCategories.Where(t => t.StartsWith(DEPLOYMENTITEM_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (deploymentItemTags.Any())
{
IEnumerable<string> deploymentItemsAsStrings = deploymentItemTags.Select(t => t.Substring(DEPLOYMENTITEM_TAG.Length));
if (deploymentItemsAsStrings.Any())
{
generationContext.CustomData[DEPLOYMENTITEM_TAG] = deploymentItemsAsStrings;
}
}

IEnumerable<string> doNotParallelizeTags = featureCategories.Where(t => t.StartsWith(DONOTPARALLELIZE_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (doNotParallelizeTags.Any())
{
generationContext.CustomData[DONOTPARALLELIZE_TAG] = String.Empty;
}
}

public override void SetTestMethod(TestClassGenerationContext generationContext, CodeMemberMethod testMethod, string friendlyTestName)
{
base.SetTestMethod(generationContext, testMethod, friendlyTestName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above,
call base.SetTestMethod on MsTest2010GeneratorProvider

if (generationContext.CustomData.ContainsKey("featureCategories"))
{
var featureCategories = (string[])generationContext.CustomData["featureCategories"];
CodeDomHelper.AddAttributeForEachValue(testMethod, CATEGORY_ATTR, featureCategories);
}

if (generationContext.CustomData.ContainsKey(OWNER_TAG))
{
string ownerName = generationContext.CustomData[OWNER_TAG] as string;
if (!String.IsNullOrEmpty(ownerName))
{
CodeDomHelper.AddAttribute(testMethod, OWNER_ATTR, ownerName);
}
}

if (generationContext.CustomData.ContainsKey(WORKITEM_TAG))
{
IEnumerable<int> workItems = generationContext.CustomData[WORKITEM_TAG] as IEnumerable<int>;
foreach (int workItem in workItems)
{
CodeDomHelper.AddAttribute(testMethod, WORKITEM_ATTR, workItem);
}
}

if (generationContext.CustomData.ContainsKey(DEPLOYMENTITEM_TAG))
{
IEnumerable<string> deploymentItems = generationContext.CustomData[DEPLOYMENTITEM_TAG] as IEnumerable<string>;
foreach (string deploymentItem in deploymentItems)
{
var outputDirProvided = deploymentItem.Split(':').Any();
if (outputDirProvided)
{
CodeDomHelper.AddAttribute(testMethod, DEPLOYMENTITEM_ATTR, deploymentItem.Split(':'));
}
else
{
CodeDomHelper.AddAttribute(testMethod, DEPLOYMENTITEM_ATTR, deploymentItem);
}
}
}

if (generationContext.CustomData.ContainsKey(DONOTPARALLELIZE_TAG))
{
CodeDomHelper.AddAttribute(testMethod, DONOTPARALLELIZE_ATTR);
}
}

public override void SetTestMethodCategories(TestClassGenerationContext generationContext, CodeMemberMethod testMethod, IEnumerable<string> scenarioCategories)
{
IEnumerable<string> tags = scenarioCategories.ToList();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, base.SetTestMethodCategories on MsTest2010GeneratorProvider and only add the code you need


IEnumerable<string> ownerTags = tags.Where(t => t.StartsWith(OWNER_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (ownerTags.Any())
{
string ownerName = ownerTags.Select(t => t.Substring(OWNER_TAG.Length).Trim('\"')).FirstOrDefault();
if (!String.IsNullOrEmpty(ownerName))
{
CodeDomHelper.AddAttribute(testMethod, OWNER_ATTR, ownerName);
}
}

IEnumerable<string> workItemTags = tags.Where(t => t.StartsWith(WORKITEM_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);
if (workItemTags.Any())
{
int temp;
IEnumerable<string> workItemsAsStrings = workItemTags.Select(t => t.Substring(WORKITEM_TAG.Length).Trim('\"'));
IEnumerable<int> workItems = workItemsAsStrings.Where(t => int.TryParse(t, out temp)).Select(t => int.Parse(t));
foreach (int workItem in workItems)
{
CodeDomHelper.AddAttribute(testMethod, WORKITEM_ATTR, workItem);
}
}
CodeDomHelper.AddAttributeForEachValue(testMethod, CATEGORY_ATTR, GetNonMSTestSpecificTags(tags));

IEnumerable<string> doNotParallelizeTags = tags.Where(t => t.StartsWith(DONOTPARALLELIZE_TAG, StringComparison.InvariantCultureIgnoreCase)).Select(t => t);

if (doNotParallelizeTags.Any() && !generationContext.CustomData.ContainsKey(DONOTPARALLELIZE_TAG))
{
CodeDomHelper.AddAttribute(testMethod, DONOTPARALLELIZE_ATTR);
}
}

private IEnumerable<string> GetNonMSTestSpecificTags(IEnumerable<string> tags)
{
return tags == null ? new string[0] : tags.Where(t =>
(!t.StartsWith(OWNER_TAG, StringComparison.InvariantCultureIgnoreCase))
&& (!t.StartsWith(WORKITEM_TAG, StringComparison.InvariantCultureIgnoreCase))
&& (!t.StartsWith(DEPLOYMENTITEM_TAG, StringComparison.InvariantCultureIgnoreCase))
&& (!t.StartsWith(DONOTPARALLELIZE_TAG, StringComparison.InvariantCultureIgnoreCase)))
.Select(t => t);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ partial void RegisterUnitTestGeneratorProviders(ObjectContainer container)
container.RegisterTypeAs<MsTestGeneratorProvider, IUnitTestGeneratorProvider>("mstest.2008");
container.RegisterTypeAs<MsTest2010GeneratorProvider, IUnitTestGeneratorProvider>("mstest.2010");
container.RegisterTypeAs<MsTest2010GeneratorProvider, IUnitTestGeneratorProvider>("mstest");
container.RegisterTypeAs<MsTestV2GeneratorProvider, IUnitTestGeneratorProvider>("mstest.V2");
}
}
}