-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Add Ordering, Orderable and @OrderWith #1130
Conversation
These APIs allow arbitrary ordernig of tests, including randomization.
cb5c609
to
00ec63f
Compare
Woah, nice! Beginning to dig in. Thanks for the work here. |
* | ||
* @since 4.13 | ||
*/ | ||
public final class GenericOrdering extends Ordering { |
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.
Name and comment here is a bit confusing. I might call it DelegatingOrdering?
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.
@dsaff I would rather not call it DelegatingOrdering
. It is specifically an Ordering
that is known not to be a Sorter
, and some of the core code depends on that. I'm open to other names and improved doc, of course.
Another thing potentially worth considering sooner-rather-than-later: I imagine that the request will come down the road for a --sort_with annotation to complement the existing --filter_with. If a class has OrderWith, and the command line has --order_with, who wins? (I assume we just say "command line" and move on, but if you have another idea?) |
Holding off on digging for further feedback while top-level issues settle down. Thanks again! |
Do we thing that we have many users that use the JUnit command line flags to run tests where it makes sense to add |
I do appreciate the feedback, and I'm open to looking for a more general concept there. I'm just pushing back because |
A couple non-exhaustive thoughts:
Put another way, I'd hate to give credence to the narrative "JUnit used to irrationally make it hard to order your tests so that they worked, but with 4.13, they added OrderWith, so now you can go ahead and write order-dependent tests, no more problems." (There's no action item on #3, just a warning that I may need to let this process a day or two before I'm ready to pull the trigger.) |
For the third point, although I agree that writing tests that depend on a specific ordering is a bad idea, we've been asked about this a number of times (as well as supporting shuffling tests) that we should consider some way to allow this, without baking into JUnit the particular strategy. If you want to explore the When I have some time, I'll explore splitting I wonder if we could attach One other concern: the way |
Change Orderable to no longer extend Sortable.
@dsaff I added two commits. The first one moves the handling of The second changes |
(I think you meant "moves the handling of @OrderWith to RunnerBuilder"). Now that I see it, I think that RunnerBuilder is one step too far up to move this: now it's possible to write a suite that doesn't respect @RunWith on its children (by replacing AllDefaultPossibilitiesBuilder), but not possible to not respect @OrderWith. I'm still not sure about making @OrderWith be on the same level of the call tree as @RunWith, but I'm pretty sure it doesn't make sense to put it above. What do you think? Re: Sorter doesn't extend Ordering: Note that now we have Sorter with a void apply(Object) method, and Ordering with a void apply(Object) method. One could create a [choosing random word] FooBox interface that has just this apply method, and cause OrderWith to accept any subclass of FooBox, thereby (I think) avoiding the need to wrap in many cases. However, at that point, we're awfully close (again) to RunRule, since FooBox basically can do anything it wants to the Runner it's passed, not just ordering: it could certainly filter, and we might even be able to finagle it to inject listeners or rules. So we'd either have to decide to arbitrarily hamstring OrderWith, or accept that very clever people will use OrderWith to do non-ordering things, or give it a different name at that point. I'm again tempted to go the fully generic route, since (a) we're almost there already, and (b) given the rather big (in percentage terms) addition here to top-level API, I'd feel much better about it if the features unlocked including more than ordering, which (as I've mentioned above) I'm worried may prove a mixed blessing. Don't feel a need to go change the code just yet; I'd love to hear your thoughts on the above (unless changing the code is the easiest way to do that). Thanks again! And I can work on a fork that shows what RunRule might look like, although today isn't necessarily looking conducive. |
@dsaff I actually think that I don't see any problems with third-party subclasses of I'm sorry, but I still don't quite follow how your |
|
||
@Override | ||
public void apply(Object runner) { | ||
if (runner instanceof Sortable) { |
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 was some of the ugly code that caused me to want to make Sorter
an Ordering
.
We currently allow Suites to ignore RunWith on their children, for example: This facility may be under-documented, but it already exists, and is used. As one extension that I think we'd want to allow, imagine a BackAndForthSuite runner that first runs its children in their native order, and then runs them again in the precise opposite direction, in order to rout out any order-dependent tests. I'll need to play with the code to see whether such a thing would be possible with the current implementation. |
@dsaff if you wanted to disable |
The current implementatiion makes sure the reordered children includes all original children exactly once. I could allow running tests multiple times, but I am not sure that we should. |
@marcphilipp had another ping on #1194 ... Should we get this pull submitted, find another solution, or close that issue? |
@kcooney Thanks for the ping! I think this PR looks promising, but there are still few things to be sorted out. Currently Why do we need |
/** | ||
* An ordering that internally uses a {@link Comparator}. | ||
*/ | ||
class ComparsionBasedOrdering extends Ordering { |
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.
There's a typo in the class name. How about ComparatorBasedOrdering
?
/** | ||
* Creates an {@link Ordering} from the given factory. | ||
* | ||
* @param factoryClass class to use to create the ordering |
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.
There's no factoryClass
parameter.
* compare() method--but the Liskov substitution principle demands that | ||
* we obey the general contract of Orderable. Luckily, it's trivial to | ||
* implement. | ||
*/ |
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 this method is protected, I'm wondering whether we shouldn't just throw an UnsupportedOperationException
. Thoughts?
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 it's trivial to implement, and Ordering defines the method, I think we should implement it. A future subclass or Sorter could decide to call this method.
} | ||
} | ||
|
||
boolean validateOrderingIsCorrect() { |
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 please add a comment to document what this method is used for?
Yes, that's why it was done. I'm not too worked about forcing
If you need to do a sort, calling |
Oh, and |
I renamed GeneralOrdering to Orderer and it no longer implements Ordering. Now Orderer has the logic for doing the ordering, calling the Ordering to order the items and then validating that there are no duplicates or removed items. I think it's much simpler than what I had before, though I'm not excited about the naming. |
@marcphilipp do my changes and comments address your concerns? |
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.
Yep, I think that looks good now, thanks! 👍
* Add Ordering, Orderable and @OrderWith. These APIs allow arbitrary ordering of tests, including randomization.
These APIs allow arbitrary ordering of tests, including randomization.