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

Introduce support for filtering packages #313

Closed
3 tasks done
sbrannen opened this issue Jun 18, 2016 · 4 comments
Closed
3 tasks done

Introduce support for filtering packages #313

sbrannen opened this issue Jun 18, 2016 · 4 comments

Comments

@sbrannen
Copy link
Member

sbrannen commented Jun 18, 2016

Status Quo

It is currently possible to select a package -- for example, for classpath scanning. However, it is not possible to filter packages.

See use case described in #534 for additional input.

Related Issues

Deliverables

  • Introduce include and exclude filter support for packages in a new PackageFilter class (similar to ClassFilter).
  • Introduce include and exclude filter support for packages in the Gradle JUnit Platform plugin.
  • Introduce include and exclude filter support for packages in the JUnitPlatform runner (e.g., @IncludePackages and @ExcludePackages).
@bechte
Copy link
Contributor

bechte commented Nov 12, 2016

When specifying filters for packages we have different options how to evaluate the filter rules:

  1. Use one filter that handles included and excluded packages (filter rules also apply for sub packages)
  2. Use one filter that handles included and excluded packages (filter rules only apply for their specified package)
  3. Use two different filters, one for included packages and one for excluded packages (filter rules also apply for sub packages)
  4. Use two different filters, one for included packages and one for excluded packages (filter rules only apply for their specified package)

The advantage of having one filter over two different filters is, that it could evaluate all filter rules allowing to specify more granulate filter rules. The advantage of having two separate filters is, that the filters itself are simpler and better to maintain. Therefore, we prefer option 4 in favor to option 2 in case of simplicity.

We can discuss the other options using the following example and see have the filter rule are applied and what the outcome is.

Example

Given the following filter rules:

No Package Filter Rule
1 org.junit.sample included
2 org.junit.sample.module1 excluded
3 org.junit.sample.module1.category1 included
4 org.junit.sample.module1.category2 excluded
5 org.junit.sample.module2 excluded
6 org.junit.sample.module3 included

Filtering with Option 1

Class Matching Rules Filter result Included in test run?
org.junit.outside.SampleTests - undefined
org.junit.sample.SampleTests 1 included ✔️
org.junit.sample.module1.SampleTests 1, 2 excluded
org.junit.sample.module1.category1.SampleTests 1, 2, 3 included ✔️
org.junit.sample.module1.category2.SampleTests 1, 2, 4 excluded
org.junit.sample.module1.category3.SampleTests 1, 2 excluded
org.junit.sample.module2.SampleTests 1, 5 excluded
org.junit.sample.module3.SampleTests 1, 6 included ✔️
org.junit.sample.module4.SampleTests 1 included ✔️

Note:

  • If the Filter does not find any matching rule and has at least one rule, if is undefined if the class should be included or excluded!

Filtering with Option 2

Class Matching Rules Filter result Included in test run?
org.junit.outside.SampleTests - undefined
org.junit.sample.SampleTests 1 included ✔️
org.junit.sample.module1.SampleTests 2 excluded
org.junit.sample.module1.category1.SampleTests 3 included ✔️
org.junit.sample.module1.category2.SampleTests 4 excluded
org.junit.sample.module1.category3.SampleTests - undefined
org.junit.sample.module2.SampleTests 5 excluded
org.junit.sample.module3.SampleTests 6 included ✔️
org.junit.sample.module4.SampleTests - undefined

Note:

  • If the Filter does not find any matching rule and has at least one rule, if is undefined if the class should be included or excluded!

Filtering with Option 3

Class Matching Rules Filter result Included in test run?
org.junit.outside.SampleTests - excluded
org.junit.sample.SampleTests 1 included ✔️
org.junit.sample.module1.SampleTests 1, 2 excluded
org.junit.sample.module1.category1.SampleTests 1, 2, 3 excluded
org.junit.sample.module1.category2.SampleTests 1, 2, 4 excluded
org.junit.sample.module1.category3.SampleTests 1, 2 excluded
org.junit.sample.module2.SampleTests 1, 5 excluded
org.junit.sample.module3.SampleTests 1, 6 included ✔️
org.junit.sample.module4.SampleTests 1 included ✔️

Note:

  • If the IncludeFilter does not find any matching rule and has at least one rule, it will decline the class
  • If the ExcludeFilter does not find any matching rule and has at least one rule, it will accept the class

Filtering with Option 4

Class Matching Rules Filter result Included in test run?
org.junit.outside.SampleTests - excluded
org.junit.sample.SampleTests 1 included ✔️
org.junit.sample.module1.SampleTests 2 excluded
org.junit.sample.module1.category1.SampleTests 3 included ✔️
org.junit.sample.module1.category2.SampleTests 4 excluded
org.junit.sample.module1.category3.SampleTests - excluded
org.junit.sample.module2.SampleTests 5 excluded
org.junit.sample.module3.SampleTests 6 included ✔️
org.junit.sample.module4.SampleTests - excluded

Note:

  • If the IncludeFilter does not find any matching rule and has at least one rule, it will decline the class
  • If the ExcludeFilter does not find any matching rule and has at least one rule, it will accept the class

Quick option comparison

Class Option 1 Option 2 Option 3 Option 4
org.junit.outside.SampleTests
org.junit.sample.SampleTests ✔️ ✔️ ✔️ ✔️
org.junit.sample.module1.SampleTests
org.junit.sample.module1.category1.SampleTests ✔️ ✔️ ✔️
org.junit.sample.module1.category2.SampleTests
org.junit.sample.module1.category3.SampleTests
org.junit.sample.module2.SampleTests
org.junit.sample.module3.SampleTests ✔️ ✔️ ✔️ ✔️
org.junit.sample.module4.SampleTests ✔️ ✔️

Conclusion

The most natural option would be Option 1. Its result seem to be the most obvious solution from a user perspective of the filtering. It allows to specify fine granulate rules and overriding on any level, e.g. org.junit.sample.module1.category1.SampleTests is included again. Still it requires a definition for cases that do not match any rule, e.g. org.junit.outside.SampleTests and it has a higher complexity than options 3 and 4.

Option 3 has a lower complexity and almost the same filter results. There is only one case org.junit.sample.module1.category1.SampleTests that differs. This is because the excluded and included are evaluated separately. Therefore, we cannot override a previously specified exclude rule. This also seems to be okay, if we say the rule is also being applied for sub packages.

Option 2 will lead to unexpected filter results if we define the outcome of the undefined cases to be included. Therefore, if should return exclude in these case, making the outcome of the filter evaluation exact equally with Option 4. We are in favour of option 4 in this case because of its simplicity over option 2.

Recommendation

One should go for Option 1 or Option 3, depending on whether or not one wants to be able to overrule previously defined exclude rules for sub packages. If JUnit should support this, then Option 1 is the best solution. If this is not required, Option 3 is the better solution, as it is much easier to implement, understand, and maintain.

@bechte
Copy link
Contributor

bechte commented Nov 16, 2016

Team decision: Follow the recommendation and start with option 3.

@bechte
Copy link
Contributor

bechte commented Nov 22, 2016

Merged into master with #570

@bechte bechte closed this as completed Nov 22, 2016
@sbrannen
Copy link
Member Author

Thanks, @bechte! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants