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

Enable to open rspec result from emacs #306

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

uk-ar
Copy link
Contributor

@uk-ar uk-ar commented Dec 15, 2014

This PR add feature to open rspec result from emacs. And this feature is enabled only when test fail.
guard-emacs

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.1%) when pulling df2ec70 on uk-ar:add_emacs_option into 76249c3 on guard:master.

@e2
Copy link
Contributor

e2 commented Dec 15, 2014

This is VERY cool!

I can't accept this PR only because it isn't generic enough (other editors and tools would benefit too).

If you're looking for a quick solution, you may want to try the new :cmd_additional_args parameter of Guard::Rspec. It allows you to do e.g.

guard :rspec, cmd_additional_args: '|tee results.txt'

Months ago I actually tried to get this working with Vim, but I put it aside because the final step was to remove the colors from the RSpec output (I see you don't use colors in RSpec - probably for the same reason).

(I tried to use various options with RSpec, but as far as I remember, there's no way to keep color output and have a text-only formatter.)

I gave up because I found a another plugin that worked for me (vim-dispatch).

If have time and you want to create a PR, then the best solution would be to add an option to Guard::RSpec to copy the results file (because it's deleted as soon as the child process running RSpec returns).

So the only way (that I know of) is to modify Guard::RSpec::Runner so it copies the results file before deleting the original.

The deleting happens here:

File.delete(formatter_tmp_file) if File.exists?(formatter_tmp_file)

If you don't want to create a PR, just create a new issue and link this PR to it, so you're automatically notified if I ever get to implementing this.

@webhat
Copy link

webhat commented Dec 16, 2014

Thanks for the pointer to vim-dispatch!

@uk-ar
Copy link
Contributor Author

uk-ar commented Dec 17, 2014

@e2 Thank you for reviewing and suggestion!

I agree that it isn't generic enough for other tools. In addition, I think that this feature is useful other guard plugin, e.g. guard-rubocop.

So, I'm considering that guard plugins using console output should hold it output like Guard::Sheller, and notifier can use these output.

My design is below.

module Guard
  class ShellPlugin < Plugin
    attr_reader :status,:stdout,:stderr
    ...
  end
end

How about this proposal?

@e2
Copy link
Contributor

e2 commented Dec 17, 2014

@uk-ar - thanks, I never would have thought of doing something like that.

Personally, I like streams and pipes and queues. In this case, when we're running tools, it's better for things to be "atomic".

Like if RSpec output was in JSON, you wouldn't wan't "half a JSON file". Just as RSpec does doesn't use streams as inputs and just as we don't edit files as streams of text.

It makes sense for logging, but I don't think it makes sense for results.

Also, since Guard listens to files, having the output written to a file could trigger all sort of "jobs" in parallel in the future (e.g. rubocop, yard, coverage reports, etc.).

Instead I planned on adding support for "events" in plugins, so that plugins can "talk" to each other, and respond to each other's events - without Guard having to understand the API between them.

So instead of streaming output, it would be better for the Guard::RSpec formatter to "notify" a listening emacs plugin every time there is a new result - it would be much better than pipe'ing and you wouldn't need a defined interface between guard and the plugins - except for handling events, but this could be trivial.

This also means inheritance in Ruby isn't a good idea - even with the current Guard plugins it caused too many problems and provided no benefit. Mixins and modules are much better for Ruby. Or even just respond_to?. Classes mean requiring files and API compatibility - even when behavior doesn't change, so it's a cost for everyone and no benefit. (Inheritance interferes also very much with testing - and makes more sense in compiled languages).

But until we get to events/signals/actions, using actual files is the next best thing. Files are also good, because they are persistent storage, and you could do cool things like "continuing" with work where you left off (unfinished tests, repository status, workflows).

So using files right now for "data exchange" is the best way to go - especially since we can listen to them for changes and respond.

I'm just sharing a general direction and your PR really shows the need for some asynchronous communication. For this purpose, sockets are much better than streams. But until we get the architecture for Guard ready, files+Listen are the easiest way to start moving in that direction.

What do you think?

@uk-ar
Copy link
Contributor Author

uk-ar commented Dec 25, 2014

@e2 - I'm sorry for late reply. I was in vacation.

I agree "atomic" result is more important than stream in this case. And I intended stdout is not File object but String of whole output.

Thank you for your suggestion that this PR feature should implement as Guard plugin using files+Listen. But I still have one question. I want to show result "only" when test failed. And if guard execute plugin in pallarel, how do I get status code of RSpec(and another tools)?

2014/12/18 4:46�$B!"�(BCezary Baginski notifications@github.com �$B$N%a%C%;!<%8�(B:

@uk-ar - thanks, I never would have thought of doing something like that.

Personally, I like streams and pipes and queues. In this case, when we're running tools, it's better for things to be "atomic".

Like if RSpec output was in JSON, you wouldn't wan't "half a JSON file". Just as RSpec does doesn't use streams as inputs and just as we don't edit files as streams of text.

It makes sense for logging, but I don't think it makes sense for results.

Also, since Guard listens to files, having the output written to a file could trigger all sort of "jobs" in parallel in the future (e.g. rubocop, yard, coverage reports, etc.).

Instead I planned on adding support for "events" in plugins, so that plugins can "talk" to each other, and respond to each other's events - without Guard having to understand the API between them.

So instead of streaming output, it would be better for the Guard::RSpec formatter to "notify" a listening emacs plugin every time there is a new result - it would be much better than pipe'ing and you wouldn't need a defined interface between guard and the plugins - except for handling events, but this could be trivial.

This also means inheritance in Ruby isn't a good idea - even with the current Guard plugins it caused too many problems and provided no benefit. Mixins and modules are much better for Ruby. Or even just respond_to?. Classes mean requiring files and API compatibility - even when behavior doesn't change, so it's a cost for everyone and no benefit. (Inheritance interferes also very much with testing - and makes more sense in compiled languages).

But until we get to events/signals/actions, using actual files is the next best thing. Files are also good, because they are persistent storage, and you could do cool things like "continuing" with work where you left off (unfinished tests, repository status, workflows).

So using files right now for "data exchange" is the best way to go - especially since we can listen to them for changes and respond.

I'm just sharing a general direction and your PR really shows the need for some asynchronous communication. For this purpose, sockets are much better than streams. But until we get the architecture for Guard ready, files+Listen are the easiest way to start moving in that direction.

What do you think?

�$B!=�(B
Reply to this email directly or view it on GitHub.

@e2
Copy link
Contributor

e2 commented Dec 25, 2014

@e2 - I'm sorry for late reply. I was in vacation.

Nothing to apologize for - no rush at all!

And I intended stdout is not File object but String of whole output.

Yes - and I suggest using a file name instead of output - so you can read the file in your code yourself. So in the future, you will get a filename with the results whenever an RSpec run finishes.

I want to show result "only" when test failed.

I don't know exactly what you mean by "show". If you implement the results file in guard-rspec, you'll know by the file contents (see below). See the guard-rspec formatter source code for how the guard-rspec results file looks like.

And if guard execute plugin in pallarel, how do I get status code of RSpec(and another tools)?

That will happen in the future. Currently, Guard will run all tasks synchronously from the main thread. Don't worry about parallel - if it's ever implemented, it will be transparent.

If you want to get this working now, just submit a PR that would get this code working:

require 'guard/compat/plugin'
module Guard
  class Emacs < Plugin
    def run_on_modifications(results_files)
      failures = extract_failures(results_files.first)
      open_emacs(failures)
    end

    def extract_failures(file)
      # (...) - you need to implement this based on how guard-rspec reads it's output file
    end

    def open_emacs(failures)
      # (...) - code from your PR
    end
  end
end

guard :emacs do
  watch('tmp/rspec_results.txt')
end

guard :rspec, results_file: 'tmp/rspec_results.txt' do
  # (...)
end

This means:

  1. adding an option to guard-rspec telling it where to save the results
  2. implementing the extract_failures method
  3. (optional) - you can put the above plugin in a new gem called e.g. guard-emacs-rspec

and that's it.

I think it was a mistake to include Launchy in guard-rspec - it shouldn't be there (I'll probably throw it away into a new gem once this PR is merged).

Let me know if you need help with anything (I'm working on other issues, so I won't be able to work on this myself right now).

@e2
Copy link
Contributor

e2 commented Jun 26, 2015

In case someone's interested, I've added a feature request to create a "failures file" here: #333

If such a file is created on failures, is should be possible to watch for that file in the Guardfile, and load the errors into editors/tools from there.

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.

4 participants