-
Notifications
You must be signed in to change notification settings - Fork 105
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
WIP Issue497 filter #522
WIP Issue497 filter #522
Conversation
…flag in runsettings #497
@OsirisTerje Re our email issues... I did get an email that you asked for my review of this. |
Ok, then that part works at least, but if you didnt get any emails from the mentions today, something is wrong with github. |
if (tfsFilter!=null && settings.UseTestCaseFilterConverter) | ||
{ | ||
var nunitfilter = new VsTest2NUnitFilterConverter(tfsFilter.TfsTestCaseFilterExpression.TestCaseFilterValue); | ||
filterBuilder.SelectWhere(nunitfilter.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there is no error detection, It seems like there is an underlying assumption here that the converter will always produce a valid where clause. Do we know that's true for all possible values of the original filter?
bool UseTestCaseFilterConverter { get; } | ||
} | ||
|
||
public class FeatureFlags : IFeatureFlags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this alternate implementation of IFeatureFlags public by design, or can it be private and maybe even a struct?
I have to think about why both AdapterSettings and FeatureFlags implement IFeatureFlags and where in the codebase FeatureFlags might be used versus AdapterSettings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This FeatureFlags class is used for the runsettings, so that we can separate out this block of settings. Since the other ones are options, so to speak, I find the featureflags different, and therefore easier to have them in a separate block. In the code though, it is enough that we can see them in the adaptersettings, therefore the interface is implemented there too, and implementation just passed down.
@@ -136,7 +130,7 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame | |||
var assemblyPath = Path.IsPathRooted(assemblyName) ? assemblyName : Path.Combine(Directory.GetCurrentDirectory(), assemblyName); | |||
|
|||
var filterBuilder = CreateTestFilterBuilder(); | |||
var filter = filterBuilder.MakeTestFilter(assemblyGroup); | |||
var filter = filterBuilder.MakeTestFilter(assemblyGroup,new TfsTestFilter(runContext)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crazy nitpick: space after comma?
#else | ||
return new NUnitTestFilterBuilder(TestEngine.Services.GetService<ITestFilterService>()); | ||
return new NUnitTestFilterBuilder(TestEngine.Services.GetService<ITestFilterService>(),Settings,TestLog); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces after commas?
} | ||
|
||
public TestFilter ConvertTfsFilterToNUnitFilter(TfsTestFilter tfsFilter, List<TestCase> loadedTestCases) | ||
{ | ||
var filteredTestCases = tfsFilter.CheckFilter(loadedTestCases); | ||
var testCases = filteredTestCases as TestCase[] ?? filteredTestCases.ToArray(); | ||
//TestLog.Info(string.Format("TFS Filter detected: LoadedTestCases {0}, Filterered Test Cases {1}", loadedTestCases.Count, testCases.Count())); | ||
return MakeTestFilter(testCases); | ||
return MakeTestFilter(testCases,tfsFilter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after comma?
{ | ||
var nunitfilter = new VsTest2NUnitFilterConverter(tfsFilter.TfsTestCaseFilterExpression.TestCaseFilterValue); | ||
filterBuilder.SelectWhere(nunitfilter.ToString()); | ||
if (settings?.Verbosity>4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of putting spaces around the >
operator and the !=
operator above?
Apologies for the nitpickiness today!
Is Verbosity > 4
different from skipping the if
and using logger.Debug
?
{ | ||
get { return TfsTestCaseFilterExpression == null || TfsTestCaseFilterExpression.TestCaseFilterValue == string.Empty; } | ||
} | ||
public bool IsEmpty => TfsTestCaseFilterExpression == null || TfsTestCaseFilterExpression.TestCaseFilterValue == string.Empty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these lines get pretty long...
One option for long getters would also be
{
get => TfsTestCaseFilterExpression == null || TfsTestCaseFilterExpression.TestCaseFilterValue == string.Empty;
}
public VsTest2NUnitFilterConverter(string vstestfilter) | ||
{ | ||
NUnitFilter = vstestfilter.Replace("TestCategory", "Category"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might just be personal preference but doing the heavy lifting of the class doesn't feel very "constructory" to me.
The name is Converter
but once you have an instance, you can't convert things with it. You can only access a conversion result.
What would you think of introducing a static string (string)
method?
public class VsTest2NUnitFilterConverterTests | ||
{ | ||
[TestCase("TestCategory!=Whatever", "Category!=Whatever")] | ||
[TestCase("TestCategory=Whatever","Category=Whatever")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add FullyQualifiedName = SomeNamespace.TestCategory.SomeMethod
?
What else should we add from https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md?
It's a clever idea to use text conversion rather than parsing, changing the text representation of the VS filter to the text representation of an NUnit filter. It should work if the languages are sufficiently close. That's my area of doubt. The alternative, of course, is to create a grammar of VS filters - maybe Microsoft has that already - and parse it, generating NUnit filters directly without the intermediate step of TSL. My general feeling is that if you want to go this way you need to throw a lot more tests at it, including some invalid input and non-translatable input if you can come up with examples. Currently, the code assumes no error will ever occur. |
@CharliePoole Yep, more tests are needed. |
@CharliePoole The simple filters are easy to just translate this way, but when it comes to terms like Name and ClassName, I start to worry a bit about these terms also being part of the RHS clauses. The translator doesn't separate between those. Since there is a difference in NUnit between the term Testname and methodname, these terns doesn't really make that much sense to translate. I have rarely seen them in filter expressions too.
|
Of course, 3 was what I originally proposed to you. The impedance mismatch will always exist but some approaches make it easier than others to give a precise error message. What happens if you use a non-supported rhs element? What happens if you use invalid syntax, say a bad operator or unbalanced parentheses? I'll try to make up some test cases later at my computer. |
Sounds OK then. |
WIP *** DO NOT MERGE ***
Changed test case filter to use NUnit Filter.
Added a featureflag for testing purposes, have now left it default true, but keep open the possibility of defaulting to false if further tests show it is not stable. Local tests so far looks good.