-
-
Notifications
You must be signed in to change notification settings - Fork 762
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 new --only-failures CLI option #1888
Conversation
I don't think we should write to this directory unless the users opt in, it'd pretty rude to just start writing to disk and I can think of a few scenarios where this would be undesirable (for example CI systems)
I think if we only write when told to it's ok to omit an error when we can't.
I like the alter idea.
Combine them, but we'd need to not blow away any existing cache at this point, I'd use this feature this way.
I think we should try, maybe hash the file contents? |
My hope was to make this feature usable w/o requiring the user to have the forethought to configure it. They could run That said, it makes it hard to report write errors w/o appearing to nag the user about something they haven't opted-in to, so I think I'm coming around to the idea of:
By "combine them" do you mean "take the intersection"? As for not blowing away the existing cache...I think it's confusing for us to only update the persisted failures sometimes but it's definitely desirable not to lose the state about other examples that weren't part of the run...which gives me an idea for a different direction we could take this feature that I think would work much, much better:
Problem is, the user is going to want to edit the spec file to address the failures, and then rerun them...which would produce a different checksum just like changing branches would. I think the best we could do is to store the example description w/ the id, and use that to as a signal to infer if the id refers to the same example as before or not. That would probably work better....but I'm concerned that it is simply a heuristic and may make this feature act in confusing, inconsistent ways. For example, the user may change the doc string to correct a typo and they would still consider it to be the same example. Ultimately, I think "is this the same example as before?" is a question that can only be answered by human judgement, and we're better off trying to avoid guessing. The downsides of running the wrong examples after changing branches aren't really that high -- it would just run some passing examples and skip some failed ones. We can always revisit if someone comes up with a way to detect this that we're satisfied with. Thoughts on the alternate direction I've proposed above? |
Yes
Yep, ok I'm ok with this, and when not said we should disable all of the below for performance.
And the last time it ran maybe? We could log a quick stat line
As long as we can turn all this off in case it adds a large performance overhead (which is what I mean by turn it off when
This makes more sense
Sure, that works :) We can just warn them when it changes or |
I'm thinking we may want to add more data like that but I'd rather wait to add that until we have a use for it. For now I just want to get a serialization format in place that will allow us to easily add that in the future. Or maybe I'll change my mind and add it now :). This does bring up a key question: how should we serialize this? JSON would be a natural choice but we'd like to avoid loading that stdlib, of course. We could vendor okjson, perhaps...although I'm interested in other ideas. A single JSON string in a file isn't terribly readable if you pop it open in an editor :(.
Or what? Anyhow, I advocate putting no effort into "example id references a different example than before" detection. Too many open questions, edge cases, etc. We can revisit in the future. |
Er, or not run them, not sure how that got truncated! |
I'd stick with something simpler, I mean one example per line a few values may as well be csv! |
That would probably work. I worry a bit about dealing with quoting/escaping (e.g. a file name that has a comma in it...or should we not support that?), though. To do proper CSV parsing with all the edge cases we'd probably have to load the CSV stdlib but maybe we can get away with a simple |
Well we don't have to use But I agree we should keep it as simple as possible so we can do a simple split! |
In my first pass I passed in the index but later changed to passing in an index provider and forgot to update the argument name.
- Stop memoizing `example`. It made it difficult to construct multiple different examples. - Explicitly create the examples where they are needed.
The result object is really just a value object, so why fake it out?
82258a0
to
a606314
Compare
OK, I've pushed what I've done so far for this. It's not quite done yet but I wanted to get Travis builds going and give people a chance to review what I have so far. Still TODO:
|
Oh my is this finally going to be there then 👯 |
/cc @JonRowe |
f749f79
to
312fd77
Compare
Loading ALL spec files when only a handful have failures is inefficient and could make the run take significantly longer. Note that we only do this if no file or directory arg is passed to `rspec`. If the user passes anything, we load what they tell us to load.
`configuration_spec.rb` is too huge. The API needs to remain large to support the configurability of RSpec, but we don’t need to keep all the specs in one file. I want to start breaking off different chunks into their own files. This is a first step towards that.
It’s easier to make this work by moving the `spec_files_with_failures` and the `last_run_statuses` methods off of `world` and over to `configuration.
It made more sense when these methods were on `world` as they were before but now they are on config so we want to avoid that.
It’s more appropriate there.
22b018d
to
85bcc85
Compare
Before, we only did so when no file or directory arg was passed to `rspec`, but it's better to take the intersection of files matching the provided args and files with failures.
This ensures that the value is consistent — before for an unknown case it could either be `nil` or `"unknown"`. We've also moved the constant into configuration, so that we can avoid the cost of loading `example_status_persister` (via constant access since it is setup to be autoloaded) if the user hasn't configured the feature.
eb6368e
to
1276b38
Compare
OK, this is ready for a review, @rspec/rspec. I've done all the stuff I planned to do. |
I've had two passes over this now, and can't fault it, but you know what they say about large PRs ;) |
7f78843
to
360910a
Compare
360910a
to
af8628f
Compare
Add new --only-failures CLI option
Thanks, @JonRowe. I guess I should have left some extra trailing blank lines on some files so you'd have something to point out? Anyhow, I got it green and merged it. |
I was referring to the saying:
:P |
Add new --only-failures CLI option
(Note: this PR has changed significantly compared to when it was first opened. See this comment for current status).
This is the start of the implementation of a new
--rerun-failures
CLI flag that runs just the failures from the last run. This leverages the new example IDs to ensure it selects the exact examples that failed the last time. My hope with this feature is that it "just works" the first time a user decides they want to run just the failures from the last run, w/o having to configure anything in advance to enable it.As part of the implementation, this creates a new
.rspec_last_run
directory in the users's home directory that persists the list of failures from the last run so we can use it on the next run. I can imagine us finding other uses for this directory in the future.There are a lot of open questions:
.rspec_last_run
? Specific cases I can think of where we may not want to:--fail-fast
-- in that case it's going to abort after one failure and the user may want to get all failures, and then use--rerun-failures --fail-fast
to repeatedly run just one of the remaining failing specs...but if we replaced the persisted failures with a single--fail-fast
spec it wouldn't support this workflow.--rerun-failures
is passed and there is no persisted failures from a prior run? Do we abort with an error or treat it like "all examples filtered out" and respect therun_all_when_everything_filtered
config option?--rerun-failures
and also specifies specific spec files to load, or locations/ids to run? Should we disallow that or try to combine them somehow? For example, maybe we could take the intersection of the two? Sorspec spec/models --rerun-failures
would run just the failures in the model specs. This situation may also relate to whether or not we update the persisted failures every time./cc @rspec/rspec