├── .gitignore ├── .travis.yml ├── Gemfile ├── Guardfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── guard-elixir.gemspec ├── lib └── guard │ ├── elixir.rb │ └── elixir │ ├── templates │ └── Guardfile │ └── version.rb ├── spec ├── lib │ └── guard │ │ └── elixir_spec.rb └── spec_helper.rb └── test └── test_helper.exs /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | branches: 3 | only: 4 | - master 5 | rvm: 6 | - 1.9.3 7 | - 2.0.0 8 | notifications: 9 | recipients: 10 | - pat@codeofhonor.com 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in guard-elixir.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :rspec do 2 | watch(%r{^spec/.+_spec\.rb}) 3 | watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" } 4 | watch('spec/spec_helper.rb') { "spec" } 5 | end 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Patrick Wyatt 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Guard::Elixir 2 | [![Gem Version](https://badge.fury.io/rb/guard-elixir.png)](http://badge.fury.io/rb/guard-elixir) 3 | [![Build Status](https://travis-ci.org/webcoyote/guard-elixir.png?branch=master)](https://travis-ci.org/webcoyote/guard-elixir) 4 | 5 | Guard::Elixir is a [Guard](https://github.com/guard/guard) plugin that automatically runs tests for the [Elixir](http://elixir-lang.org/) language using "mix test". 6 | 7 | 8 | ## Installation 9 | 10 | 11 | ### Manual installation 12 | 13 | ```bash 14 | gem install guard-elixir 15 | ``` 16 | 17 | ### Installation using [Bundler](http://gembundler.com/). 18 | 19 | Add Guard::Elixir to your `Gemfile`: 20 | 21 | ```ruby 22 | group :development do 23 | gem 'guard-elixir' 24 | end 25 | ``` 26 | 27 | and install it by running Bundler: 28 | 29 | ```bash 30 | $ bundle 31 | ``` 32 | 33 | 34 | ## Configuration 35 | 36 | Add guard definition to your Guardfile by running the following command: 37 | 38 | ```bash 39 | guard init elixir 40 | ``` 41 | 42 | Run guard to automatically run your Elixir tests 43 | 44 | ```bash 45 | bundle exec guard start 46 | ``` 47 | 48 | 49 | ### Standard Guardfile when using Guard::Elixir 50 | 51 | ```ruby 52 | guard :elixir do 53 | watch(%r{^test/(.*)_test\.exs}) 54 | watch(%r{^lib/(.+)\.ex$}) { |m| "test/#{m[1]}_test.exs" } 55 | watch(%r{^test/test_helper.exs$}) { "test" } 56 | end 57 | ``` 58 | 59 | ## More information 60 | 61 | Please read [Guard usage doc](http://github.com/guard/guard#readme) 62 | 63 | 64 | ## Contributing 65 | 66 | 1. Fork it 67 | 2. Create your feature branch (`git checkout -b my-new-feature`) 68 | 3. Commit your changes (`git commit -am 'Add some feature'`) 69 | 4. Push to the branch (`git push origin my-new-feature`) 70 | 5. Create new Pull Request 71 | 72 | 73 | # Author 74 | 75 | Author:: [Patrick Wyatt](https://github.com/webcoyote) (pat@codeofhonor.com) 76 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rspec/core/rake_task' 5 | RSpec::Core::RakeTask.new(:spec) 6 | task :default => :spec 7 | 8 | require 'rbconfig' 9 | namespace(:spec) do 10 | if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i 11 | desc "Run all specs on multiple ruby versions (requires pik)" 12 | task(:portability) do 13 | %w[193 200].each do |version| 14 | system "cmd /c echo -----------#{version}------------ & " + 15 | "pik use #{version} & " + 16 | "bundle install & " + 17 | "bundle exec rspec spec" 18 | end 19 | end 20 | else 21 | desc "Run all specs on multiple ruby versions (requires rvm)" 22 | task(:portability) do 23 | travis_config_file = File.expand_path("../.travis.yml", __FILE__) 24 | begin 25 | travis_options ||= YAML::load_file(travis_config_file) 26 | rescue => ex 27 | puts "Travis config file '#{travis_config_file}' could not be found: #{ex.message}" 28 | return 29 | end 30 | 31 | travis_options['rvm'].each do |version| 32 | system <<-BASH 33 | bash -c 'source ~/.rvm/scripts/rvm; 34 | rvm #{version}; 35 | ruby_version_string_size=`ruby -v | wc -m` 36 | echo; 37 | for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done 38 | echo; 39 | echo "`ruby -v`"; 40 | for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done 41 | echo; 42 | bundle install; 43 | bundle exec rspec spec -f doc 2>&1;' 44 | BASH 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /guard-elixir.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'guard/elixir/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "guard-elixir" 8 | spec.version = Guard::ElixirVersion::VERSION 9 | spec.authors = ["Patrick Wyatt"] 10 | spec.email = ["pat@codeofhonor.com"] 11 | spec.description = "Guard::Elixir automatically runs Elixir 'mix' tests" 12 | spec.summary = "Guard gem for Elixir language" 13 | spec.homepage = "https://github.com/webcoyote/guard-elixir" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | spec.required_ruby_version = ">= 1.9.3" 21 | 22 | spec.add_dependency 'guard' 23 | 24 | spec.add_development_dependency "bundler" 25 | spec.add_development_dependency "rake" 26 | spec.add_development_dependency 'rspec' 27 | spec.add_development_dependency 'guard-rspec' 28 | end 29 | -------------------------------------------------------------------------------- /lib/guard/elixir.rb: -------------------------------------------------------------------------------- 1 | require 'guard' 2 | require 'guard/guard' 3 | require 'guard/watcher' 4 | require 'guard/notifier' 5 | 6 | module Guard 7 | class Elixir < Guard 8 | def initialize(watchers=[], options={}) 9 | super 10 | @options = { 11 | all_on_start: true, 12 | dry_run: false, 13 | }.update(options) 14 | end 15 | 16 | def start 17 | run_all if @options[:all_on_start] 18 | end 19 | 20 | def run_all 21 | files = Dir.glob("**/*.*") 22 | targets = Watcher.match_files(self, files) 23 | run_on_change targets 24 | end 25 | 26 | # Called on file(s) modifications 27 | def run_on_change(paths) 28 | if @options[:dry_run] 29 | paths.each { |path| UI.info "Dry run: #{path}" } 30 | return 31 | end 32 | 33 | total = 0 34 | failures = 0 35 | duration = 0 36 | run_command("mix test #{paths.join(' ')}") do |line| 37 | puts line 38 | if /Finished in ([0-9.]+) seconds/.match(line) 39 | duration = Regexp::last_match[1] 40 | elsif /([0-9]+) tests, ([0-9]+) failures/.match(line) 41 | total = Regexp::last_match[1].to_i 42 | failures = Regexp::last_match[2].to_i 43 | end 44 | end 45 | 46 | Notifier.notify( 47 | guard_message(total, failures, duration), 48 | :title => "Elixir results", 49 | :image => guard_image(failures), 50 | :priority => guard_priority(failures) 51 | ) 52 | end 53 | 54 | private 55 | 56 | def run_command(cmd) 57 | UI.debug "+ #{cmd}" 58 | IO.popen(cmd, :err => [:child, :out]).each do |line| 59 | if block_given? 60 | yield line 61 | else 62 | puts line 63 | end 64 | end 65 | Process.wait 66 | $?.success? 67 | end 68 | 69 | def guard_image(failures) 70 | if failures > 0 71 | :failed 72 | else 73 | :success 74 | end 75 | end 76 | 77 | def guard_priority(failures) 78 | if failures > 0 79 | 2 80 | else 81 | -2 82 | end 83 | end 84 | 85 | def guard_message(total, failures, duration) 86 | "#{total} tests, #{failures} failures\nin #{duration} seconds" 87 | end 88 | 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/guard/elixir/templates/Guardfile: -------------------------------------------------------------------------------- 1 | guard :elixir do 2 | watch(%r{^test/(.*)_test\.exs}) 3 | watch(%r{^lib/(.+)\.ex$}) { |m| "test/#{m[1]}_test.exs" } 4 | watch(%r{^test/test_helper.exs$}) { "test" } 5 | end 6 | -------------------------------------------------------------------------------- /lib/guard/elixir/version.rb: -------------------------------------------------------------------------------- 1 | module Guard 2 | class ElixirVersion 3 | VERSION = "0.0.2" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/lib/guard/elixir_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require "guard/watcher" 3 | require "guard/ui" 4 | 5 | describe "Guard-Elixir" do 6 | 7 | before(:each) do 8 | @subject = Guard::Elixir.new 9 | @paths = [ "foo.ex", "dir1/dir2/dir3/bar.ex" ] 10 | end 11 | 12 | describe "initialize" do 13 | it "should start with default options" do 14 | @subject.options[:all_on_start].should be true 15 | @subject.options[:dry_run].should be false 16 | end 17 | 18 | it "should be possible to overwrite the default options" do 19 | @subject = Guard::Elixir.new([],{ 20 | all_on_start: false, 21 | dry_run: true 22 | }) 23 | @subject.options[:all_on_start].should be false 24 | @subject.options[:dry_run].should be true 25 | end 26 | end 27 | 28 | describe "start" do 29 | describe "all_on_start" do 30 | it "should run all tests if all_on_start is true" do 31 | @subject = Guard::Elixir.new([],{ dry_run: true }) 32 | @subject.should_receive(:run_all) 33 | @subject.start 34 | end 35 | it "should not run all tests on start if all_on_start is false" do 36 | @subject = Guard::Elixir.new([],{ all_on_start: false, dry_run: true }) 37 | @subject.should_not_receive(:run_all) 38 | @subject.start 39 | end 40 | end 41 | end 42 | 43 | describe "run_on_change" do 44 | describe "dry run" do 45 | it "should not perform a conversion on a dry run" do 46 | @subject = Guard::Elixir.new([],{ dry_run: true }) 47 | Kernel.should_not_receive(:exec) 48 | Guard::UI.should_receive(:info).exactly(@paths.count).times 49 | @subject.run_on_change(@paths) 50 | end 51 | end 52 | end 53 | 54 | describe "run_all" do 55 | it "should call run_on_change for all matching paths" do 56 | @subject = Guard::Elixir.new([],{ dry_run: true }) 57 | Dir.should_receive(:glob).with("**/*.*").and_return(@paths) 58 | Guard::Watcher.should_receive(:match_files).with(@subject, @paths).and_return(@paths) 59 | @subject.should_receive(:run_on_change).with(@paths) 60 | @subject.run_all 61 | end 62 | end 63 | 64 | end 65 | 66 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'guard/elixir' 2 | ENV["GUARD_ENV"] = 'test' 3 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start 2 | --------------------------------------------------------------------------------