-
-
Notifications
You must be signed in to change notification settings - Fork 761
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
Example groups can override the default ordering #1025
Conversation
true | ||
end | ||
end | ||
end |
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.
Given ruby 1.9's well-known perf problems with require
, I think it's better to not split things into such small files. What do you think about defining each of these ordering strategies in-line in the ordering_registry.rb
file?
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.
Why don't we require the file only when it's set as the strategy, I mean we're not going to need all of them at once right?
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.
Why don't we require the file only when it's set as the strategy, I mean we're not going to need all of them at once right?
I think that would complicate things in the registry, where it registers the strategy by class -- it would need to always load a couple of files to be able to register the built-in orderings. Seems simpler to just put them all in the same file as the registry. There's no rule that says we have to limit a file to one class :).
|
||
it 'resets random number generation' do | ||
allow(Kernel).to receive(:srand) | ||
expect(Kernel).to receive(:srand).with(no_args) |
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.
Same here...
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.
I feel like I'm missing some context here.... (Same here as what?)
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.
Weird, I posted a comment on the example above and github ate it or something.
My comment was: why use allow
and expect
? Seems like you could use just expect
...
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.
Yeah you don't need the allow
on top of the expect
What weirdness are you referring to in particular? IMO, the main weirdness we had before was the use of an ordering module to extend onto arrays. You've gotten rid of that and I heartily approve :). |
singleton_class.send(:define_method, :order) { args.last[:order] } | ||
elsif parent && parent.order | ||
singleton_class.send(:define_method, :order) { parent.order } | ||
end |
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.
Rather than defining singleton methods like this, this feels like something that could be delegated to metadata (similar to described_class
and file_path
:
delegate_to_metadata :described_class, :file_path |
Thoughts?
Also, the singleton_class.send(:define_method, :order) { parent.order }
bit seems very odd to me; won't ruby's method dispatch cause it to use the parent class's implementation already, w/o a need to explicitly define it to delegate to the parent?
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.
Actually, perusing the code, I don't even see a place where this method gets used. Can you direct me to where this gets used? Maybe it's not even needed...
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.
all this code should go it's a leftover from my original solution that somehow made its way into this PR.
The mismatch between groups and examples, also a single |
@@ -405,9 +416,25 @@ def self.run(reporter) | |||
end | |||
end | |||
|
|||
# :order => MyStrategy.new | |||
# | |||
# :order => :my_stragegy |
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.
It's not clear what these :order => ...
lines are supposed to mean, given that this method takes no args.
Also, s/stragegy/strategy/
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.
Yeah I think this is in the wrong place
What is this in reply to, @samphippen? It's just floating there in the PR discussion view but I don't understand the context... |
@myronmarston I know you're AFK but when you get back, my floating comment was in reply to:
|
I'm going to try to rebase this and get this ready to merge, FWIW. I'll be force pushing the rebase shortly and then taking care of addressing the open issues above after that. |
BTW, I have more changes coming for this. Just wanted to push what I had so far :). |
I push some further updates. I expect the build to fail but wanted to push it to ensure it's backed up. I'll keep working on this this week. |
I've gotten this to a point that's (almost) ready to merge and I'd like feedback from others. There's still a few open issues/questions I have, though:
|
What is the difference, I'm not totally clued up on this. If there's no difference should we streamline them? Deprecate the old ones? Or will they be in widespread use?
If we're allowing 'custom global orderings' then we should have a cuke outlining how that works (in addition to the one for using a standard ordering). Edit Yup, we should cuke the custom block ordering, and possibly the identify one too? |
module Ordering | ||
# @private | ||
# The default ordering (defined order). | ||
class Identity |
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.
From the name of this it isn't clear to me how it's ordered.
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's a better name then? I like Identity
as it's a well-known mathematical concept for a function that returns the argument it is given...which is what this does.
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.
So it's the identity ordering, as in it leaves the thing in the same order. We were also thing about InPlace
if you like that better. Thoughts on the back of a github comment ❤️
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.
I like Identity
for exactly what @myronmarston said. It's what I would have called this class.
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.
My mathematical concepts must be rusty :P, I prefer @samphippen's InPlace
suggestion.
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.
I like Identity
much better than InPlace
, so let's stick with that. Honestly, it doesn't matter that much since this is an internal class that users won't need to deal with directly.
…rather than having special `set_global_ordering` and `global_ordering` methods. Also, simplify `Ordering::Registry#fetch`: - No need to handle `nil`; the caller can pass :global. - No need to handle callables; that's a bit of complexity we don't need. Callables can be registered. - No need to convert the ordering name `to_sym`; it wasn't spec'd and I'd rather require folks pass symbols.
- Don't have separate `groups`, `examples` and `groups_and_examples` methods. There are very few use cases for having separate logic for groups vs examples and it doesn't justify the added complexity to have separate APIs. If you need to order them separately, put a conditional in your ordering strategy that branches based on the type of the first item in the list. - Remove legacy `order_xyz` methods. These set the global ordering but didn't make that clear. Instead, the global ordering can be set by `register_ordering :global`.
`--default` was never a good name. (Consider that if we had made `--random` the default, `--default` would have been even more confusing).
Circling back around on this:
Done, in 57ab90a.
@shepmaster I like the idea of it accepting an ordering strategy object, so I added support for that in 69c12db. However, having separate example vs group methods is similar to what we already have and are trying to get away from--plus it seems inconsistent with the block ordering form. So I decided to make everything (examples and groups) go through one API (see 10aca90). Besides the fact that this radically simplifies the API and code in rspec-core, I think that @xaviershay is right that it's very rare that these will need to be treated differently. I'm also hoping that for the cases where people actually do need to call methods on the example groups or examples, it'll put positive design pressure on us to have a unified API for them so that for the user here they can effectively be treated uniformly. Keeping them separate does not put that kind of design pressure on us. @xaviershay I went back and forth between making the API
Thus, I thought that Anyhow, here's what I think is left for this feature:
|
Agree re global. |
OK, I think this is ready to merge. See my last commit for the added cukes. I opened #1092 to track the work to add the necessary deprecations to 2.99. |
Anyone want to do a final code review before this is merged? |
|
||
* Nested groups are always run from top-level to bottom-level in order to avoid | ||
executing `before(:all)` and `after(:all)` hooks more than once, but the order | ||
of groups at each level is randomized. | ||
|
||
You can also specify a seed | ||
You can also specify a seed: |
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.
Why the indentation change here?
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.
I didn't mean to or realize I did. I'll fix that.
Looks mostly good to me, although I'd like to see a better solution for checking wether the seed is used rather than passing configuration into the reporter. Especially as I think we use Reporter in some of our other specs with no args. |
Thanks for doing the review, @JonRowe.
I agree the "seed_used?" solution could be better but I think there are more important things for me to work on. I'll merge this PR as-is once it's green (now that I addressed your other two comments) and you're welcome to open another PR with the improvements you have in mind there. |
Yeah thats fair |
…oups Example groups can override the default ordering
Merged :). |
So ... is this even a good solution and good way to design it? 😄
There's a decent bit of weirdness around how ordering works right now
that we're trying not to break. If you see some weirdness in our code,
feel free to ask about it ... and we might decide to simply break it for
RSpec 3 to allow the solution to be cleaner.
Still outstanding if so:
OrderingRegistry
has some structural duplication betweengetting/setting ordering for examples vs. groups
OrderingRegistry
. Some of these methods might be@private
.@samphippen and I paired on this