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

WIP Issue497 filter #522

Closed
wants to merge 14 commits into from
Closed

WIP Issue497 filter #522

wants to merge 14 commits into from

Conversation

OsirisTerje
Copy link
Member

@OsirisTerje OsirisTerje commented Jun 22, 2018

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.

@OsirisTerje OsirisTerje requested review from rprouse and jnm2 June 22, 2018 18:11
@CharliePoole
Copy link
Contributor

@OsirisTerje Re our email issues... I did get an email that you asked for my review of this.

@OsirisTerje
Copy link
Member Author

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());
Copy link
Contributor

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
Copy link
Contributor

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.

Copy link
Member Author

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.

src/NUnitTestAdapter/NUnit3TestExecutor.cs Outdated Show resolved Hide resolved
@@ -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));
Copy link
Contributor

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);
Copy link
Contributor

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);
Copy link
Contributor

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)
Copy link
Contributor

@jnm2 jnm2 Jun 29, 2018

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;
Copy link
Contributor

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");
}
Copy link
Contributor

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")]
Copy link
Contributor

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?

build.cake Outdated Show resolved Hide resolved
@CharliePoole
Copy link
Contributor

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.

@OsirisTerje
Copy link
Member Author

OsirisTerje commented Jun 30, 2018

@CharliePoole Yep, more tests are needed.
The VSTest filter language us very simple, and looks more or less like a subset of the NUnit TSL, which is why I thought just converting it to TSL was a simple way to go. What is not included above is the " contains " ( ~ ) operator, but that should convert into a simple regex (vstest ' ~ ' operator => TSL ' =~' operator.
The logical operators are the same.

@OsirisTerje
Copy link
Member Author

@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.
So, there are a few options, and some of these can be selected through feature flags:

  1. Keep the translator as a simple option, which will cover most cases
  2. Add , under a featureflag, the possibility of dropping in TSL directly. This would make the VSTest filter expressions idewntical to the nunit console filter expressions, and the syntax is not that different from the current vstest syntax. It also is richer, adding more possibilities.
    or
  3. Write a new parser, like the current TestSelectionParser, but just for the VSTest filter language. Just observe that we then still have the same impedance mismatch wrt to FQN, and as the adapter also presents properties to VSTest to use, we are still in a mixed world.

@CharliePoole
Copy link
Contributor

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.

@OsirisTerje
Copy link
Member Author

If I use an invalid operator, an exception is thrown from the parser;
image

Invalid rhs will be handled as it always have been, that is, if it is not a valid test artifact, it will be ignored.

@CharliePoole
Copy link
Contributor

Sounds OK then.

@OsirisTerje OsirisTerje changed the title Issue497 filter WIP Issue497 filter Oct 27, 2020
@OsirisTerje OsirisTerje closed this Jul 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants