├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── Guardfile ├── LICENSE ├── README.md ├── RELEASE.md ├── Rakefile ├── gemfiles ├── Gemfile.minitest-4 └── Gemfile.minitest-5 ├── guard-minitest.gemspec ├── lib ├── guard │ ├── minitest.rb │ └── minitest │ │ ├── inspector.rb │ │ ├── notifier.rb │ │ ├── reporter.rb │ │ ├── reporters │ │ └── old_reporter.rb │ │ ├── runner.rb │ │ ├── runners │ │ └── old_runner.rb │ │ ├── templates │ │ └── Guardfile │ │ ├── utils.rb │ │ └── version.rb └── minitest │ └── guard_minitest_plugin.rb └── spec ├── fixtures └── bundler │ └── Gemfile ├── lib └── guard │ ├── minitest │ ├── inspector_spec.rb │ ├── notifier_spec.rb │ ├── runner_spec.rb │ └── utils_spec.rb │ └── minitest_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/* 2 | *.gem 3 | .bundle 4 | .DS_Store 5 | .rvmrc 6 | .rbx/* 7 | Gemfile.lock 8 | coverage/ 9 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | AllCops: 4 | Exclude: 5 | - Guardfile 6 | - Rakefile 7 | - guard-minitest.gemspec 8 | - lib/guard/minitest/templates/Guardfile 9 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by `rubocop --auto-gen-config` 2 | # on 2015-01-15 02:26:14 +0100 using RuboCop version 0.28.0. 3 | # The point is for the user to remove these configuration records 4 | # one by one as the offenses are removed from the code base. 5 | # Note that changes in the inspected code, or installation of new 6 | # versions of RuboCop, may require this file to be generated again. 7 | 8 | 9 | # Offense count: 4 10 | Metrics/AbcSize: 11 | Max: 23 12 | 13 | # Offense count: 1 14 | # Configuration parameters: CountComments. 15 | Metrics/ClassLength: 16 | Max: 190 17 | 18 | # Offense count: 1 19 | Metrics/CyclomaticComplexity: 20 | Max: 11 21 | 22 | # Offense count: 79 23 | # Configuration parameters: AllowURI, URISchemes. 24 | Metrics/LineLength: 25 | Max: 199 26 | 27 | # Offense count: 4 28 | # Configuration parameters: CountComments. 29 | Metrics/MethodLength: 30 | Max: 20 31 | 32 | # Offense count: 2 33 | # Configuration parameters: CountKeywordArgs. 34 | Metrics/ParameterLists: 35 | Max: 6 36 | 37 | # Offense count: 1 38 | Metrics/PerceivedComplexity: 39 | Max: 11 40 | 41 | # Offense count: 1 42 | # Configuration parameters: EnforcedStyle, SupportedStyles. 43 | Style/ClassAndModuleChildren: 44 | Enabled: false 45 | 46 | # Offense count: 3 47 | Style/ClassVars: 48 | Enabled: false 49 | 50 | # Offense count: 10 51 | Style/Documentation: 52 | Enabled: false 53 | 54 | # Offense count: 1 55 | Style/EachWithObject: 56 | Enabled: false 57 | 58 | # Offense count: 1 59 | # Configuration parameters: EnforcedStyle, SupportedStyles. 60 | Style/FormatString: 61 | Enabled: false 62 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | bundler_args: --without development -j4 3 | rvm: 4 | - 1.9.3 5 | - 2.0.0 6 | - 2.1 7 | - jruby-19mode 8 | - rbx 9 | matrix: 10 | allow_failures: 11 | - rvm: rbx 12 | gemfile: 13 | - gemfiles/Gemfile.minitest-4 14 | - gemfiles/Gemfile.minitest-5 15 | 16 | # use Travis AUFS containers 17 | sudo: false 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Moved to [GitHub releases](https://github.com/guard/guard-minitest/releases) page. 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute to Guard::Minitest 2 | 3 | ## File an issue 4 | 5 | You can report bugs and feature requests to [GitHub Issues](https://github.com/guard/guard-minitest/issues). 6 | 7 | **Please don't ask question in the issue tracker**, instead ask them on at Stack Overflow and use the 8 | [guard](http://stackoverflow.com/questions/tagged/guard) tag and/or [guard-minitest](http://stackoverflow.com/questions/tagged/guard-minitest). 9 | 10 | Try to figure out where the issue belongs to: Is it an issue with Guard::Minitest itself or with Guard? 11 | 12 | When you file a bug, please try to follow these simple rules if applicable: 13 | 14 | * Make sure you've read the README carefully. 15 | * Make sure you run Guard with `bundle exec` first. 16 | * Add debug information to the issue by running Guard with the `--debug` option. 17 | * Add your `Guardfile` and `Gemfile` to the issue. 18 | * Make sure that the issue is reproducible with your description. 19 | 20 | **It's most likely that your bug gets resolved faster if you provide as much information as possible!** 21 | 22 | ## Development 23 | 24 | * Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/guard-minitest/master/frames). 25 | * Source hosted at [GitHub](https://github.com/guard/guard-minitest). 26 | 27 | Pull requests are very welcome! Please try to follow these simple rules if applicable: 28 | 29 | * Please create a topic branch for every separate change you make. 30 | * Make sure your patches are well tested. All specs run by Travis CI must pass. 31 | * Update the [README](https://github.com/guard/guard-minitest/blob/master/README.md). 32 | * Update the [CHANGELOG](https://github.com/guard/guard/blob/master/CHANGELOG.md) for noteworthy changes (don't forget to run `bundle exec pimpmychangelog` and watch the magic happen)! 33 | * Please **do not change** the version number. 34 | 35 | For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on 36 | `#guard` (irc.freenode.net). 37 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec development_group: :gem_build_deps 4 | 5 | group :gem_build_deps do 6 | gem 'rake' 7 | end 8 | 9 | group :development do 10 | gem 'guard-rspec', require: false 11 | gem 'ruby_gntp', require: false 12 | 13 | # Used for release 14 | gem 'gems', require: false 15 | gem 'netrc', require: false 16 | gem 'octokit', require: false 17 | 18 | gem 'guard-rubocop', require: false 19 | end 20 | 21 | group :test do 22 | gem 'rspec', '>= 3.1.0', require: false 23 | end 24 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | group :development, halt_on_fail: true do 2 | guard :rspec, cmd: 'bundle exec rspec' do 3 | watch(%r{^spec/(.*)_spec\.rb$}) 4 | watch(%r{^(lib/.*/)?([^/]+)\.rb$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" } 5 | watch(%r{^spec/spec_helper\.rb$}) { 'spec' } 6 | end 7 | 8 | guard :rubocop do 9 | watch(%r{.+\.rb$}) 10 | watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Yann Lugrin, Rémy Coutable 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Guard::Minitest 2 | [![Gem Version](https://badge.fury.io/rb/guard-minitest.svg)](http://badge.fury.io/rb/guard-minitest) [![Build Status](https://travis-ci.org/guard/guard-minitest.svg?branch=master)](https://travis-ci.org/guard/guard-minitest) [![Dependency Status](https://gemnasium.com/guard/guard-minitest.svg)](https://gemnasium.com/guard/guard-minitest) [![Code Climate](https://codeclimate.com/github/guard/guard-minitest.svg)](https://codeclimate.com/github/guard/guard-minitest) [![Coverage Status](https://coveralls.io/repos/guard/guard-minitest/badge.svg?branch=master)](https://coveralls.io/r/guard/guard-minitest) 3 | 4 | Guard::Minitest allows to automatically & intelligently launch tests with the 5 | [minitest framework](https://github.com/seattlerb/minitest) when files are modified. 6 | 7 | * Compatible with minitest >= 3.0 (optimal support for 5.x). 8 | * Tested against Ruby 1.9.3, 2.0.0, JRuby and Rubinius (1.9 mode). 9 | 10 | *IMPORTANT NOTE: `guard-minitest` does not depend on `guard` due to obscure issues - you must either install `guard` first or add it explicitly in your `Gemfile` (see: [#131](https://github.com/guard/guard-minitest/pull/131) for details)* 11 | 12 | ## Install 13 | 14 | Please be sure to have [Guard](http://github.com/guard/guard) installed before you continue. 15 | 16 | The simplest way to install Guard::Minitest is to use [Bundler](http://gembundler.com/). 17 | 18 | Add Guard::Minitest to your `Gemfile`: 19 | 20 | ```ruby 21 | group :development do 22 | gem 'guard' # NOTE: this is necessary in newer versions 23 | gem 'guard-minitest' 24 | end 25 | ``` 26 | 27 | and install it by running Bundler: 28 | 29 | ```bash 30 | $ bundle 31 | ``` 32 | 33 | Add guard definition to your Guardfile by running the following command: 34 | 35 | ```bash 36 | guard init minitest 37 | ``` 38 | 39 | ## Ruby on Rails 40 | 41 | ### Spring 42 | 43 | Due to complexities in how arguments are handled and running tests for selected files, it's best to use the following spring command: 44 | 45 | ```ruby 46 | guard "minitest", spring: "bin/rails test" do 47 | # ... 48 | end 49 | ``` 50 | 51 | (For details see issue [#130](https://github.com/guard/guard-minitest/issues/130)). 52 | 53 | ### Rails gem dependencies 54 | 55 | Ruby on Rails lazy loads gems as needed in its test suite. 56 | As a result Guard::Minitest may not be able to run all tests until the gem dependencies are resolved. 57 | 58 | To solve the issue either add the missing dependencies or remove the tests. 59 | 60 | Example: 61 | 62 | ``` 63 | Specify ruby-prof as application's dependency in Gemfile to run benchmarks. 64 | ``` 65 | 66 | Rails automatically generates a performance test stub in the `test/performance` directory which can trigger this error. 67 | Either add `ruby-prof` to your `Gemfile` (inside the `test` group): 68 | 69 | ```ruby 70 | group :test do 71 | gem 'ruby-prof' 72 | end 73 | ``` 74 | 75 | Or remove the test (or even the `test/performance` directory if it isn't necessary). 76 | 77 | ## Usage 78 | 79 | Please read [Guard usage doc](http://github.com/guard/guard#readme) 80 | 81 | ## Guardfile 82 | 83 | Guard::Minitest can be adapated to all kind of projects. 84 | Please read [guard doc](http://github.com/guard/guard#readme) for more info about the Guardfile DSL. 85 | 86 | ### Standard Guardfile when using Minitest::Unit 87 | 88 | ```ruby 89 | guard :minitest do 90 | watch(%r{^test/(.*)\/?test_(.*)\.rb$}) 91 | watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" } 92 | watch(%r{^test/test_helper\.rb$}) { 'test' } 93 | end 94 | ``` 95 | 96 | ### Standard Guardfile when using Minitest::Spec 97 | 98 | ```ruby 99 | guard :minitest do 100 | watch(%r{^spec/(.*)_spec\.rb$}) 101 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } 102 | watch(%r{^spec/spec_helper\.rb$}) { 'spec' } 103 | end 104 | ``` 105 | 106 | ## Options 107 | 108 | ### List of available options 109 | 110 | ```ruby 111 | all_on_start: false # run all tests in group on startup, default: true 112 | all_after_pass: true # run all tests in group after changed specs pass, default: false 113 | cli: '--test' # pass arbitrary Minitest CLI arguments, default: '' 114 | test_folders: ['tests'] # specify an array of paths that contain test files, default: %w[test spec] 115 | include: ['lib'] # specify an array of include paths to the command that runs the tests 116 | test_file_patterns: %w[test_*.rb] # specify an array of patterns that test files must match in order to be run, default: %w[*_test.rb test_*.rb *_spec.rb] 117 | spring: true # enable spring support, default: false 118 | zeus: true # enable zeus support; default: false 119 | drb: true # enable DRb support, default: false 120 | bundler: false # don't use "bundle exec" to run the minitest command, default: true 121 | rubygems: true # require rubygems when running the minitest command (only if bundler is disabled), default: false 122 | env: {} # specify some environment variables to be set when the test command is invoked, default: {} 123 | all_env: {} # specify additional environment variables to be set when all tests are being run, default: false 124 | autorun: false # require 'minitest/autorun' automatically, default: true 125 | ``` 126 | 127 | ### Options usage examples 128 | 129 | #### `:test_folders` and `:test_file_patterns` 130 | 131 | You can change the default location of test files using the `:test_folders` option and change the pattern of test files using the `:test_file_patterns` option: 132 | 133 | ```ruby 134 | guard :minitest, test_folders: 'test/unit', test_file_patterns: '*_test.rb' do 135 | # ... 136 | end 137 | ``` 138 | 139 | #### `:cli` 140 | 141 | You can pass any of the standard MiniTest CLI options using the `:cli` option: 142 | 143 | ```ruby 144 | guard :minitest, cli: '--seed 123456 --verbose' do 145 | # ... 146 | end 147 | ``` 148 | 149 | #### `:spring` 150 | 151 | [Spring](https://github.com/jonleighton/spring) is supported (Ruby 1.9.X / Rails 3.2+ only), but you must enable it: 152 | 153 | ```ruby 154 | guard :minitest, spring: true do 155 | # ... 156 | end 157 | ``` 158 | 159 | Since version 2.3.0, the default Spring command works is `bin/rake test` making the integration with your Rails >= 4.1 app effortless. 160 | 161 | If you're using an older version of Rails (or no Rails at all), you might want to customize the Spring command, e.g.: 162 | 163 | ```ruby 164 | guard :minitest, spring: 'spring rake test' do 165 | # ... 166 | end 167 | ``` 168 | 169 | #### `:zeus` 170 | 171 | [Zeus](https://github.com/burke/zeus) is supported, but you must enable it. 172 | Please note that notifications support is very basic when using Zeus. The zeus client exit status is evaluated, and 173 | a Guard `:success` or `:failed` notification is triggered. It does not include the test results though. 174 | 175 | If you're interested in improving it, please 176 | [open a new issue](https://github.com/guard/guard-minitest/issues/new). 177 | 178 | If your test helper matches the test_file_patterns, it can lead to problems 179 | as guard-minitest will submit the test helper itself to the zeus test 180 | command when running all tests. For example, if the test helper is 181 | called ``test/test_helper.rb`` it will match ``test_*.rb``. In this case you can 182 | either change the test_file_patterns or rename the test helper. 183 | 184 | ```ruby 185 | guard :minitest, zeus: true do 186 | # ... 187 | end 188 | ``` 189 | 190 | #### `:drb` 191 | 192 | [Spork / spork-testunit](https://github.com/sporkrb/spork-testunit) is supported, but you must enable it: 193 | 194 | ```ruby 195 | guard :minitest, drb: true do 196 | # ... 197 | end 198 | ``` 199 | The drb test runner honors the :include option, but does not (unlike the 200 | default runner) automatically include :test_folders. If you want to 201 | include the test paths, you must explicitly add them to :include. 202 | 203 | ## Development 204 | 205 | * Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/guard-minitest/master/frames). 206 | * Source hosted at [GitHub](https://github.com/guard/guard-minitest). 207 | 208 | Pull requests are very welcome! Please try to follow these simple rules if applicable: 209 | 210 | * Please create a topic branch for every separate change you make. 211 | * Make sure your patches are well tested. All specs run by Travis CI must pass. 212 | * Update the [README](https://github.com/guard/guard-minitest/blob/master/README.md). 213 | * Please **do not change** the version number. 214 | 215 | For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on 216 | `#guard` (irc.freenode.net). 217 | 218 | ## Maintainer 219 | 220 | [Eric Steele](https://github.com/genericsteele) 221 | 222 | ## Author 223 | 224 | [Yann Lugrin](https://github.com/yannlugrin) 225 | 226 | ## Contributors 227 | 228 | [https://github.com/guard/guard-minitest/graphs/contributors](https://github.com/guard/guard-minitest/graphs/contributors) 229 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | ## How to release a new version of guard-minitest 2 | 3 | ### During the development of the next release 4 | 5 | 1. If you don't have a release notes draft, create one at [https://github.com/guard/guard-minitest/releases/new](https://github.com/guard/guard-minitest/releases/new) (the version sould be set to `vX.Y.Z+1` for now). 6 | 1. Each time you merge a pull-request (or fix an issue, or simply push a change that should appear in the release note), update the release notes draft and keep the style consistent with previous release notes: 7 | ```markdown 8 | ### Bug fix ("Bug fixes" if there are several bug fixes, see below...) 9 | 10 | * #XXX, #YYY Title of the pull-request/issue or any meaningful text. 11 | 12 | ### New features 13 | 14 | * #ZZZ Title of the pull-request/issue or any meaningful text. 15 | * owe89wq There's no issue/PR attached to this new feature (bad!), but a commit is referenced on the left. 16 | 17 | ### Improvement 18 | 19 | * as65dah This improvement has been done in the commit referenced on the left. 20 | ``` 21 | 22 | Note that there's no need to mention the author of each change since they can be retrieved either from the issue/PR or from the actual commit. 23 | 24 | ### Once you're ready to release the next version 25 | 26 | 1. [Check that the specs pass](https://travis-ci.org/guard/guard-minitest). 27 | 1. Look at the release notes draft and update its version accordingly: 28 | - If there's new features, increment minor digit and reset patch digit, e.g. `vX.Y+1.0`. 29 | - If there's new features that break retro-compatibility, increment major digit and reset minor & patch digits, e.g. `vX+1.0.0`. 30 | - See [SemVer](http://semver.org) when in doubts. 31 | 1. Then, update the version of the gem accordingly too, in `lib/guard/minitest/version.rb` AND in `spec/lib/guard/minitest/version_spec.rb`. 32 | 1. Commit `Bump to X.Y.Z` and push to GitHub. 33 | 1. Run the magic rake task: `bundle exec rake release:full`. This will push the gem to Rubygems, and publish the GitHub release notes! 34 | 1. Congratulate yourself and enjoy a fresh beer, you deserve it! 35 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | desc 'Run all specs' 5 | 6 | require 'rspec/core/rake_task' 7 | RSpec::Core::RakeTask.new(:spec) do |t| 8 | t.verbose = (ENV['CI'] == 'true') 9 | end 10 | 11 | task default: :spec 12 | 13 | class Releaser 14 | 15 | def initialize(options = {}) 16 | @project_name = options.delete(:project_name) { raise 'project_name is needed!' } 17 | @gem_name = options.delete(:gem_name) { raise 'gem_name is needed!' } 18 | @github_repo = options.delete(:github_repo) { raise 'github_repo is needed!' } 19 | @version = options.delete(:version) { raise 'version is needed!' } 20 | end 21 | 22 | def full 23 | rubygems 24 | github 25 | end 26 | 27 | def rubygems 28 | input = '' 29 | begin 30 | puts "Release #{@project_name} #{@version} to RubyGems? (y/n)" 31 | input = STDIN.gets.chomp.downcase 32 | end while !%w[y n].include?(input) 33 | 34 | exit if input == 'n' 35 | 36 | Rake::Task['release'].invoke 37 | end 38 | 39 | def github 40 | require 'gems' 41 | 42 | if @version != Gems.info(@gem_name)['version'] 43 | puts "#{@project_name} #{@version} is not yet released." 44 | puts "Please release it first with: rake release:gem" 45 | exit 46 | end 47 | 48 | tags = `git ls-remote --tags origin`.split("\n") 49 | unless tags.find { |tag| tag =~ /v#{@version}$/ } 50 | puts "The tag v#{@version} has not yet been pushed." 51 | puts "Please push it first with: rake release:gem" 52 | exit 53 | end 54 | 55 | require 'octokit' 56 | gh_client = Octokit::Client.new(netrc: true) 57 | gh_releases = gh_client.releases(@github_repo) 58 | tag_name = "v#{@version}" 59 | 60 | if gh_release = gh_releases.find { |r| r.tag_name == tag_name && r.draft == true } 61 | input = '' 62 | puts "Draft release for #{tag_name}:\n" 63 | puts gh_release.body 64 | puts "\n-------------------------\n\n" 65 | begin 66 | puts "Would you like to publish this GitHub release now? (y/n)" 67 | input = STDIN.gets.chomp.downcase 68 | end while !%w[y n].include?(input) 69 | 70 | exit if input == 'n' 71 | 72 | if gh_client.update_release(gh_release.rels[:self].href, draft: false) 73 | gh_release = gh_client.releases(@github_repo).find { |r| r.tag_name == tag_name && r.draft == false } 74 | puts "GitHub release #{tag_name} has been published!" 75 | puts "\nPlease enjoy and spread the word!" 76 | puts "Lack of inspiration? Here's a tweet you could improve:\n\n" 77 | puts "Just released #{@project_name} #{@version}! #{gh_release.rels[:html].href}" 78 | else 79 | puts "GitHub release #{tag_name} couldn't be published!" 80 | end 81 | end 82 | end 83 | 84 | end 85 | 86 | PROJECT_NAME = 'Guard::Minitest' 87 | CURRENT_VERSION = Guard::MinitestVersion::VERSION 88 | 89 | def releaser 90 | $releaser ||= Releaser.new(project_name: PROJECT_NAME, gem_name: 'guard-minitest', 91 | github_repo: 'guard/guard-minitest', version: CURRENT_VERSION) 92 | end 93 | 94 | namespace :release do 95 | desc "Push #{PROJECT_NAME} #{CURRENT_VERSION} to RubyGems and publish its GitHub release" 96 | task full: ['release:gem', 'release:github'] 97 | 98 | desc "Push #{PROJECT_NAME} #{CURRENT_VERSION} to RubyGems" 99 | task :gem do 100 | releaser.rubygems 101 | end 102 | 103 | desc "Publish #{PROJECT_NAME} #{CURRENT_VERSION} GitHub release" 104 | task :github do 105 | releaser.github 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.minitest-4: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec path: '../' 4 | 5 | gem 'rake' 6 | gem 'minitest', '~> 4.0' 7 | gem 'coveralls', require: false 8 | 9 | platforms :rbx do 10 | gem 'racc' 11 | gem 'rubysl', '~> 2.0' 12 | gem 'psych' 13 | gem 'rubinius-coverage' 14 | end 15 | 16 | group :test do 17 | gem 'rspec', '>= 3.1.0', require: false 18 | end 19 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.minitest-5: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec path: '../' 4 | 5 | gem 'rake' 6 | gem 'minitest', '~> 5.0' 7 | gem 'coveralls', require: false 8 | 9 | platforms :rbx do 10 | gem 'racc' 11 | gem 'rubysl', '~> 2.0' 12 | gem 'psych' 13 | gem 'rubinius-coverage' 14 | end 15 | 16 | group :test do 17 | gem 'rspec', '>= 3.1.0', require: false 18 | end 19 | -------------------------------------------------------------------------------- /guard-minitest.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | $:.push File.expand_path('../lib', __FILE__) 4 | require 'guard/minitest/version' 5 | 6 | Gem::Specification.new do |s| 7 | s.name = 'guard-minitest' 8 | s.version = Guard::MinitestVersion::VERSION 9 | s.platform = Gem::Platform::RUBY 10 | s.license = 'MIT' 11 | s.authors = ['Yann Lugrin', 'Rémy Coutable'] 12 | s.email = ['remy@rymai.me'] 13 | s.homepage = 'https://rubygems.org/gems/guard-minitest' 14 | s.summary = 'Guard plugin for the Minitest framework' 15 | s.description = 'Guard::Minitest automatically run your tests with Minitest framework (much like autotest)' 16 | 17 | s.required_ruby_version = '>= 1.9.2' 18 | 19 | s.add_runtime_dependency 'guard-compat', '~> 1.2' 20 | s.add_runtime_dependency 'minitest', '>= 3.0' 21 | 22 | s.add_development_dependency 'bundler' 23 | 24 | s.files = `git ls-files -z lib`.split("\x0") + %w[CHANGELOG.md LICENSE README.md] 25 | s.require_path = 'lib' 26 | end 27 | -------------------------------------------------------------------------------- /lib/guard/minitest.rb: -------------------------------------------------------------------------------- 1 | require 'guard/compat/plugin' 2 | 3 | module Guard 4 | class Minitest < Plugin 5 | require 'guard/minitest/runner' 6 | require 'guard/minitest/utils' 7 | require 'guard/minitest/version' 8 | 9 | attr_accessor :runner 10 | 11 | def initialize(options = {}) 12 | super 13 | @options = { 14 | all_on_start: true 15 | }.merge(options) 16 | @runner = Runner.new(@options) 17 | end 18 | 19 | def start 20 | Compat::UI.info "Guard::Minitest #{MinitestVersion::VERSION} is running, with Minitest::Unit #{Utils.minitest_version}!" 21 | run_all if @options[:all_on_start] 22 | end 23 | 24 | def stop 25 | true 26 | end 27 | 28 | def reload 29 | true 30 | end 31 | 32 | def run_all 33 | throw_on_failed_tests { runner.run_all } 34 | end 35 | 36 | def run_on_modifications(paths = []) 37 | throw_on_failed_tests { runner.run_on_modifications(paths) } 38 | end 39 | 40 | def run_on_additions(paths) 41 | runner.run_on_additions(paths) 42 | end 43 | 44 | def run_on_removals(paths) 45 | runner.run_on_removals(paths) 46 | end 47 | 48 | private 49 | 50 | def throw_on_failed_tests 51 | throw :task_has_failed unless yield 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/guard/minitest/inspector.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest' 2 | 3 | module Guard 4 | class Minitest < Plugin 5 | class Inspector 6 | attr_reader :test_folders, :test_file_patterns 7 | 8 | def initialize(test_folders, test_file_patterns) 9 | @test_folders = test_folders.uniq.compact 10 | @test_file_patterns = test_file_patterns.uniq.compact 11 | end 12 | 13 | def clean_all 14 | clean(test_folders) 15 | end 16 | 17 | def clean(paths) 18 | paths.reduce([]) do |memo, path| 19 | if File.directory?(path) 20 | memo += _test_files_for_paths(path) 21 | else 22 | memo << path if _test_file?(path) 23 | end 24 | memo 25 | end.uniq 26 | end 27 | 28 | def clear_memoized_test_files 29 | @all_test_files = nil 30 | end 31 | 32 | def all_test_files 33 | @all_test_files ||= _test_files_for_paths 34 | end 35 | 36 | private 37 | 38 | def _test_files_for_paths(paths = test_folders) 39 | paths = _join_for_glob(Array(paths)) 40 | files = _join_for_glob(test_file_patterns) 41 | 42 | Dir["#{paths}/**/#{files}"] 43 | end 44 | 45 | def _test_file?(path) 46 | _test_files_for_paths.map {|path| File.expand_path(path) } 47 | .include?(File.expand_path(path)) 48 | end 49 | 50 | def _join_for_glob(fragments) 51 | "{#{fragments.join(',')}}" 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/guard/minitest/notifier.rb: -------------------------------------------------------------------------------- 1 | require 'guard/compat/plugin' 2 | 3 | module Guard 4 | class Minitest < Plugin 5 | class Notifier 6 | def self.guard_message(test_count, assertion_count, failure_count, error_count, skip_count, duration) 7 | message = "#{test_count} tests" 8 | message << " (#{skip_count} skipped)" if skip_count > 0 9 | message << "\n#{assertion_count} assertions, #{failure_count} failures, #{error_count} errors" 10 | if test_count && assertion_count 11 | message << "\n\n%.2f tests/s, %.2f assertions/s\n\nFinished in %.4f seconds" % [test_count / duration, assertion_count / duration, duration] 12 | end 13 | message 14 | end 15 | 16 | # failed | pending (skip) | success 17 | def self.guard_image(failure_count, skip_count) 18 | if failure_count > 0 19 | :failed 20 | elsif skip_count > 0 21 | :pending 22 | else 23 | :success 24 | end 25 | end 26 | 27 | def self.notify(test_count, assertion_count, failure_count, error_count, skip_count, duration) 28 | message = guard_message(test_count, assertion_count, failure_count, error_count, skip_count, duration) 29 | image = guard_image(failure_count + error_count, skip_count) 30 | 31 | Compat::UI.notify(message, title: 'Minitest results', image: image) 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/guard/minitest/reporter.rb: -------------------------------------------------------------------------------- 1 | require 'minitest' 2 | require 'guard/minitest/notifier' 3 | 4 | module Guard 5 | class Minitest < Plugin 6 | class Reporter < ::Minitest::StatisticsReporter 7 | def report 8 | super 9 | 10 | ::Guard::Minitest::Notifier.notify(count, assertions, 11 | failures, errors, 12 | skips, total_time) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/guard/minitest/reporters/old_reporter.rb: -------------------------------------------------------------------------------- 1 | require 'minitest' 2 | require 'guard/minitest/notifier' 3 | 4 | module Guard 5 | class Minitest < Plugin 6 | class Reporter < ::Minitest::Reporter 7 | def report 8 | aggregate = results.group_by { |r| r.failure.class } 9 | aggregate.default = [] # dumb. group_by should provide this 10 | 11 | f = aggregate[::Minitest::Assertion].size 12 | e = aggregate[::Minitest::UnexpectedError].size 13 | s = aggregate[::Minitest::Skip].size 14 | t = Time.now - start_time 15 | 16 | ::Guard::Minitest::Notifier.notify(count, assertions, f, e, s, t) 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/guard/minitest/runner.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest/inspector' 2 | require 'English' 3 | 4 | module Guard 5 | class Minitest < Plugin 6 | class Runner 7 | attr_accessor :inspector 8 | 9 | def initialize(options = {}) 10 | @options = { 11 | all_after_pass: false, 12 | bundler: File.exist?("#{Dir.pwd}/Gemfile"), 13 | rubygems: false, 14 | drb: false, 15 | zeus: false, 16 | spring: false, 17 | all_env: {}, 18 | env: {}, 19 | include: [], 20 | test_folders: %w(test spec), 21 | test_file_patterns: %w(*_test.rb test_*.rb *_spec.rb), 22 | cli: nil, 23 | autorun: true 24 | }.merge(options) 25 | 26 | parse_deprecated_options 27 | 28 | [:test_folders, :test_file_patterns].each do |k| 29 | @options[k] = Array(@options[k]).uniq.compact 30 | end 31 | 32 | @inspector = Inspector.new(test_folders, test_file_patterns) 33 | end 34 | 35 | def run(paths, options = {}) 36 | return unless options[:all] || !paths.empty? 37 | 38 | message = "Running: #{options[:all] ? 'all tests' : paths.join(' ')}" 39 | Compat::UI.info message, reset: true 40 | 41 | begin 42 | status = _run_possibly_bundled_command(paths, options[:all]) 43 | rescue Errno::ENOENT => e 44 | Compat::UI.error e.message 45 | throw :task_has_failed 46 | end 47 | 48 | success = status.zero? 49 | 50 | # When using zeus or spring, the Guard::Minitest::Reporter can't be used because the minitests run in another 51 | # process, but we can use the exit status of the client process to distinguish between :success and :failed. 52 | if zeus? || spring? 53 | Compat::UI.notify(message, title: 'Minitest results', image: success ? :success : :failed) 54 | end 55 | 56 | run_all_coz_ok = @options[:all_after_pass] && success && !options[:all] 57 | run_all_coz_ok ? run_all : success 58 | end 59 | 60 | def run_all 61 | paths = inspector.clean_all 62 | run(paths, all: true) 63 | end 64 | 65 | def run_on_modifications(paths = []) 66 | paths = inspector.clean(paths) 67 | run(paths, all: all_paths?(paths)) 68 | end 69 | 70 | def run_on_additions(_paths) 71 | inspector.clear_memoized_test_files 72 | true 73 | end 74 | 75 | def run_on_removals(_paths) 76 | inspector.clear_memoized_test_files 77 | end 78 | 79 | private 80 | 81 | def cli_options 82 | @cli_options ||= Array(@options[:cli]) 83 | end 84 | 85 | def bundler? 86 | @options[:bundler] && !@options[:spring] 87 | end 88 | 89 | def rubygems? 90 | !bundler? && @options[:rubygems] 91 | end 92 | 93 | def drb? 94 | @options[:drb] 95 | end 96 | 97 | def zeus? 98 | @options[:zeus].is_a?(String) || @options[:zeus] 99 | end 100 | 101 | def spring? 102 | @options[:spring].is_a?(String) || @options[:spring] 103 | end 104 | 105 | def all_after_pass? 106 | @options[:all_after_pass] 107 | end 108 | 109 | def test_folders 110 | @options[:test_folders] 111 | end 112 | 113 | def include_folders 114 | @options[:include] 115 | end 116 | 117 | def test_file_patterns 118 | @options[:test_file_patterns] 119 | end 120 | 121 | def autorun? 122 | @options[:autorun] 123 | end 124 | 125 | def _run(*args) 126 | Compat::UI.debug "Running: #{args.join(' ')}" 127 | return $CHILD_STATUS.exitstatus unless Kernel.system(*args).nil? 128 | 129 | fail Errno::ENOENT, args.join(' ') 130 | end 131 | 132 | def _run_possibly_bundled_command(paths, all) 133 | args = minitest_command(paths, all) 134 | bundler_env = !bundler? && defined?(::Bundler) 135 | bundler_env ? ::Bundler.with_original_env { _run(*args) } : _run(*args) 136 | end 137 | 138 | def _commander(paths) 139 | return drb_command(paths) if drb? 140 | return zeus_command(paths) if zeus? 141 | return spring_command(paths) if spring? 142 | ruby_command(paths) 143 | end 144 | 145 | def minitest_command(paths, all) 146 | cmd_parts = [] 147 | 148 | cmd_parts << 'bundle exec' if bundler? 149 | cmd_parts << _commander(paths) 150 | 151 | [cmd_parts.compact.join(' ')].tap do |args| 152 | env = generate_env(all) 153 | args.unshift(env) if env.length > 0 154 | end 155 | end 156 | 157 | def drb_command(paths) 158 | %w(testdrb) + generate_includes(false) + relative_paths(paths) 159 | end 160 | 161 | def zeus_command(paths) 162 | command = @options[:zeus].is_a?(String) ? @options[:zeus] : 'test' 163 | ['zeus', command] + relative_paths(paths) 164 | end 165 | 166 | def spring_command(paths) 167 | command = @options[:spring].is_a?(String) ? @options[:spring] : 'bin/rake test' 168 | cmd_parts = [command] 169 | cmd_parts << File.expand_path('../runners/old_runner.rb', __FILE__) unless Utils.minitest_version_gte_5? || command != 'spring testunit' 170 | if cli_options.length > 0 171 | cmd_parts + paths + ['--'] + cli_options 172 | else 173 | cmd_parts + paths 174 | end 175 | end 176 | 177 | def ruby_command(paths) 178 | cmd_parts = ['ruby'] 179 | cmd_parts.concat(generate_includes) 180 | cmd_parts << '-r rubygems' if rubygems? 181 | cmd_parts << '-r bundler/setup' if bundler? 182 | cmd_parts << '-r minitest/autorun' if autorun? 183 | cmd_parts.concat(paths.map { |path| "-r ./#{path}" }) 184 | 185 | unless Utils.minitest_version_gte_5? 186 | cmd_parts << "-r #{File.expand_path('../runners/old_runner.rb', __FILE__)}" 187 | end 188 | 189 | # All the work is done through minitest/autorun 190 | # and requiring the test files, so this is just 191 | # a placeholder so Ruby doesn't try to exceute 192 | # code from STDIN. 193 | cmd_parts << '-e ""' 194 | 195 | cmd_parts << '--' 196 | cmd_parts << '--guard' 197 | cmd_parts += cli_options 198 | cmd_parts 199 | end 200 | 201 | def generate_includes(include_test_folders = true) 202 | if include_test_folders 203 | folders = test_folders + include_folders 204 | else 205 | folders = include_folders 206 | end 207 | 208 | folders.map { |f| %(-I"#{f}") } 209 | end 210 | 211 | def generate_env(all = false) 212 | base_env.merge(all ? all_env : {}) 213 | end 214 | 215 | def base_env 216 | Hash[(@options[:env] || {}).map { |key, value| [key.to_s, value.to_s] }] 217 | end 218 | 219 | def all_env 220 | return { @options[:all_env].to_s => 'true' } unless @options[:all_env].is_a? Hash 221 | Hash[@options[:all_env].map { |key, value| [key.to_s, value.to_s] }] 222 | end 223 | 224 | def relative_paths(paths) 225 | paths.map { |p| "./#{p}" } 226 | end 227 | 228 | def all_paths?(paths) 229 | paths == inspector.all_test_files 230 | end 231 | 232 | def parse_deprecated_options 233 | if @options.key?(:notify) 234 | # TODO: no coverage 235 | Compat::UI.info %(DEPRECATION WARNING: The :notify option is deprecated. Guard notification configuration is used.) 236 | end 237 | 238 | [:seed, :verbose].each do |key| 239 | next unless (value = @options.delete(key)) 240 | 241 | final_value = "--#{key}" 242 | final_value << " #{value}" unless [TrueClass, FalseClass].include?(value.class) 243 | cli_options << final_value 244 | 245 | Compat::UI.info %(DEPRECATION WARNING: The :#{key} option is deprecated. Pass standard command line argument "--#{key}" to Minitest with the :cli option.) 246 | end 247 | end 248 | end 249 | end 250 | end 251 | -------------------------------------------------------------------------------- /lib/guard/minitest/runners/old_runner.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/unit' 2 | require 'guard/minitest/notifier' 3 | 4 | module MiniTest 5 | class MiniTest::Unit 6 | begin 7 | alias_method :_run_anything_without_guard, :_run_anything 8 | def _run_anything(type) 9 | start = Time.now 10 | _run_anything_without_guard(type) 11 | duration = Time.now - start 12 | ::Guard::Minitest::Notifier.notify(test_count, assertion_count, failures, errors, skips, duration) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/guard/minitest/templates/Guardfile: -------------------------------------------------------------------------------- 1 | guard :minitest do 2 | # with Minitest::Unit 3 | watch(%r{^test/(.*)\/?test_(.*)\.rb$}) 4 | watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" } 5 | watch(%r{^test/test_helper\.rb$}) { 'test' } 6 | 7 | # with Minitest::Spec 8 | # watch(%r{^spec/(.*)_spec\.rb$}) 9 | # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } 10 | # watch(%r{^spec/spec_helper\.rb$}) { 'spec' } 11 | 12 | # Rails 4 13 | # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" } 14 | # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' } 15 | # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } 16 | # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } 17 | # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" } 18 | # watch(%r{^test/.+_test\.rb$}) 19 | # watch(%r{^test/test_helper\.rb$}) { 'test' } 20 | 21 | # Rails < 4 22 | # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" } 23 | # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" } 24 | # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" } 25 | end 26 | -------------------------------------------------------------------------------- /lib/guard/minitest/utils.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/requirement' 2 | 3 | require 'guard/minitest' 4 | 5 | module Guard 6 | class Minitest < Plugin 7 | class Utils 8 | def self.minitest_version 9 | @@minitest_version ||= begin 10 | require 'minitest' 11 | ::Minitest::VERSION 12 | 13 | rescue LoadError, NameError 14 | require 'minitest/unit' 15 | ::MiniTest::Unit::VERSION 16 | end 17 | end 18 | 19 | def self.minitest_version_gte_5? 20 | @@minitest_version_gte_5 ||= Gem::Requirement.new('>= 5').satisfied_by?(Gem::Version.new(minitest_version)) 21 | end 22 | 23 | def self.minitest_version_gte_5_0_4? 24 | @@minitest_version_gte_5_0_4 ||= Gem::Requirement.new('>= 5.0.4').satisfied_by?(Gem::Version.new(minitest_version)) 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/guard/minitest/version.rb: -------------------------------------------------------------------------------- 1 | module Guard 2 | class MinitestVersion 3 | VERSION = '2.4.6' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/minitest/guard_minitest_plugin.rb: -------------------------------------------------------------------------------- 1 | module Minitest 2 | def self.plugin_guard_minitest_options(opts, options) # :nodoc: 3 | opts.on '--guard', 'Run with guard plugin enabled' do 4 | options[:guard] = true 5 | end 6 | end 7 | 8 | def self.plugin_guard_minitest_init(options) # :nodoc: 9 | return unless options[:guard] 10 | 11 | require 'guard/minitest/utils' 12 | 13 | # Require guard unless we're using guard-minitest to test a guard plugin 14 | require 'guard' unless Dir['guard-*.gemspec'].any? 15 | 16 | if ::Guard::Minitest::Utils.minitest_version_gte_5_0_4? 17 | require 'guard/minitest/reporter' 18 | else 19 | require 'guard/minitest/reporters/old_reporter' 20 | end 21 | 22 | reporter << ::Guard::Minitest::Reporter.new 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/fixtures/bundler/Gemfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guard/guard-minitest/b7946a0b4e24ab625cb8cb04efe3ca1116ccac9e/spec/fixtures/bundler/Gemfile -------------------------------------------------------------------------------- /spec/lib/guard/minitest/inspector_spec.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest/inspector' 2 | 3 | RSpec.describe Guard::Minitest::Inspector do 4 | let(:inspector) { Guard::Minitest::Inspector.new(%w(test spec), %w(*_test.rb test_*.rb *_spec.rb)) } 5 | 6 | describe 'clean' do 7 | before do 8 | @files_on_disk = Dir['spec/**/*_spec.rb'].sort 9 | end 10 | 11 | it 'should add all test files under the given dir' do 12 | expect(inspector.clean(['spec']).sort).to eq @files_on_disk 13 | end 14 | 15 | it 'should remove non-test files' do 16 | expect(inspector.clean(['spec/guard/minitest_spec.rb', 'bob.rb'])).to_not include 'bob.rb' 17 | end 18 | 19 | it 'should remove non-existing test files' do 20 | expect(inspector.clean(['spec/guard/minitest_spec.rb', 'bob_spec.rb'])).to_not include 'test_bob.rb' 21 | end 22 | 23 | it 'should remove non-test existing files (2)' do 24 | expect(inspector.clean(['spec/guard/minitest/formatter_spec.rb'])).to eq [] 25 | end 26 | 27 | it 'should keep test folder path' do 28 | expect(inspector.clean(['spec/guard/minitest_spec.rb', 'spec']).sort).to eq @files_on_disk 29 | end 30 | 31 | it 'should remove duplication' do 32 | expect(inspector.clean(['spec/lib/guard/minitest_spec.rb', 'spec/lib/guard/minitest_spec.rb'])).to eq ['spec/lib/guard/minitest_spec.rb'] 33 | end 34 | 35 | it 'should remove duplication (2)' do 36 | expect(inspector.clean(%w(spec spec)).sort).to eq @files_on_disk 37 | end 38 | 39 | it 'should remove test folder includes in other test folder' do 40 | expect(inspector.clean(['spec/minitest', 'spec']).sort).to eq @files_on_disk 41 | end 42 | 43 | it 'should not include test files not in the given dir' do 44 | expect(inspector.clean(['spec/guard/minitest'])).to_not include 'spec/guard/minitest_spec.rb' 45 | end 46 | 47 | it 'should include test files in the root dir' do 48 | inspector = Guard::Minitest::Inspector.new(%w[.], %w[*.md]) 49 | expect(inspector.clean(['README.md'])).to eq ['README.md'] 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/lib/guard/minitest/notifier_spec.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest/notifier' 2 | 3 | RSpec.describe Guard::Minitest::Notifier do 4 | subject { Guard::Minitest::Notifier } 5 | 6 | describe '.guard_message' do 7 | it 'should format message without skipped test' do 8 | expect(subject.guard_message(1, 2, 3, 4, 0, 10.0)).to eq "1 tests\n2 assertions, 3 failures, 4 errors\n\n0.10 tests/s, 0.20 assertions/s\n\nFinished in 10.0000 seconds" 9 | end 10 | 11 | it 'should format message with skipped test' do 12 | expect(subject.guard_message(1, 2, 3, 4, 5, 10.0)).to eq "1 tests (5 skipped)\n2 assertions, 3 failures, 4 errors\n\n0.10 tests/s, 0.20 assertions/s\n\nFinished in 10.0000 seconds" 13 | end 14 | end 15 | 16 | describe '.guard_image' do 17 | it 'should select failed image' do 18 | expect(subject.guard_image(1, 2)).to eq :failed 19 | expect(subject.guard_image(1, 0)).to eq :failed 20 | end 21 | 22 | it 'should select pending image' do 23 | expect(subject.guard_image(0, 2)).to eq :pending 24 | end 25 | 26 | it 'should select success image' do 27 | expect(subject.guard_image(0, 0)).to eq :success 28 | end 29 | end 30 | 31 | describe '.notify' do 32 | it 'should call Guard::Notifier' do 33 | allow(Guard::Compat::UI).to receive(:notify).with( 34 | "1 tests\n2 assertions, 0 failures, 0 errors\n\n0.10 tests/s, 0.20 assertions/s\n\nFinished in 10.0000 seconds", 35 | title: 'Minitest results', 36 | image: :success 37 | ) 38 | 39 | subject.notify(1, 2, 0, 0, 0, 10.0) 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/lib/guard/minitest/runner_spec.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest/runner' 2 | require 'guard/minitest/utils' 3 | 4 | RSpec.describe Guard::Minitest::Runner do 5 | let(:options) { {} } 6 | subject { described_class.new(options) } 7 | 8 | before do 9 | @old_runner = Guard::Minitest::Utils.minitest_version_gte_5? ? '' : " #{File.expand_path('../../../../../lib/guard/minitest/runners/old_runner.rb', __FILE__)}" 10 | @require_old_runner = Guard::Minitest::Utils.minitest_version_gte_5? ? '' : " -r#{@old_runner}" 11 | allow(Guard::Compat::UI).to receive(:notify) 12 | allow(Guard::Compat::UI).to receive(:debug) 13 | 14 | allow(Kernel).to receive(:system) do |*args| 15 | fail "stub me: Kernel.system(#{ args.map(&:inspect) * ', '})" 16 | end 17 | end 18 | 19 | describe 'options' do 20 | describe 'cli_options' do 21 | it 'defaults to empty string' do 22 | expect(subject.send(:cli_options)).to eq [] 23 | end 24 | 25 | context 'with cli' do 26 | let(:options) { { cli: '--test' } } 27 | it 'is set with \'cli\'' do 28 | expect(subject.send(:cli_options)).to eq ['--test'] 29 | end 30 | end 31 | end 32 | 33 | describe 'deprecated options' do 34 | describe 'seed' do 35 | let(:options) { { seed: 123_456_789 } } 36 | it 'sets cli options' do 37 | expect(Guard::Compat::UI).to receive(:info).with('DEPRECATION WARNING: The :seed option is deprecated. Pass standard command line argument "--seed" to Minitest with the :cli option.') 38 | 39 | expect(subject.send(:cli_options)).to eq ['--seed 123456789'] 40 | end 41 | end 42 | 43 | describe 'verbose' do 44 | let(:options) { { verbose: true } } 45 | it 'sets cli options' do 46 | expect(Guard::Compat::UI).to receive(:info).with('DEPRECATION WARNING: The :verbose option is deprecated. Pass standard command line argument "--verbose" to Minitest with the :cli option.') 47 | 48 | expect(subject.send(:cli_options)).to eq ['--verbose'] 49 | end 50 | end 51 | end 52 | 53 | describe 'bundler' do 54 | it 'defaults to true if Gemfile exist' do 55 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('bundler')) 56 | 57 | expect(subject.send(:bundler?)).to eq true 58 | end 59 | 60 | it 'defaults to false if Gemfile don\'t exist' do 61 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('empty')) 62 | 63 | expect(subject.send(:bundler?)).to eq false 64 | end 65 | 66 | context 'with bundler false' do 67 | let(:options) { { bundler: false } } 68 | it 'is forced to false' do 69 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('bundler')) 70 | 71 | expect(subject.send(:bundler?)).to eq false 72 | end 73 | end 74 | 75 | context 'with spring' do 76 | let(:options) { { spring: true } } 77 | it 'is forced to false if spring is enabled' do 78 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('bundler')) 79 | 80 | expect(subject.send(:bundler?)).to eq false 81 | end 82 | end 83 | end 84 | 85 | describe 'rubygems' do 86 | it 'defaults to false if Gemfile exist' do 87 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('bundler')) 88 | 89 | expect(subject.send(:rubygems?)).to eq false 90 | end 91 | 92 | it 'defaults to false if Gemfile don\'t exist' do 93 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('empty')) 94 | 95 | expect(subject.send(:rubygems?)).to eq false 96 | end 97 | 98 | context 'when bundler is disabled' do 99 | let(:options) { { bundler: false, rubygems: true } } 100 | it 'is true if bundler is disabled' do 101 | expect(subject.send(:rubygems?)).to eq true 102 | end 103 | end 104 | 105 | context 'when bundler is enabled' do 106 | let(:options) { { bundler: true, rubygems: true } } 107 | it 'is false if bundler is enabled' do 108 | expect(subject.send(:rubygems?)).to eq false 109 | end 110 | end 111 | end 112 | 113 | describe 'drb' do 114 | it 'defaults to false' do 115 | expect(subject.send(:drb?)).to eq false 116 | end 117 | 118 | context 'when set to true' do 119 | let(:options) { { drb: true } } 120 | specify { expect(subject.send(:drb?)).to eq true } 121 | end 122 | end 123 | 124 | describe 'zeus' do 125 | it 'defaults to false' do 126 | expect(subject.send(:zeus?)).to eq false 127 | end 128 | 129 | context 'when true' do 130 | let(:options) { { zeus: true } } 131 | specify { expect(subject.send(:zeus?)).to eq true } 132 | end 133 | 134 | context 'when string which represents the command to send to zeus' do 135 | let(:options) { { zeus: 'blah' } } 136 | specify { expect(subject.send(:zeus?)).to eq true } 137 | end 138 | end 139 | 140 | describe 'spring' do 141 | it 'defaults to false' do 142 | expect(subject.send(:spring?)).to eq false 143 | end 144 | 145 | context 'when true' do 146 | let(:options) { { spring: true } } 147 | specify { expect(subject.send(:spring?)).to eq true } 148 | end 149 | 150 | context 'when using a string which represents the command to send to spring' do 151 | let(:options) { { spring: 'rake test' } } 152 | specify { expect(subject.send(:spring?)).to eq true } 153 | end 154 | end 155 | 156 | describe 'all_after_pass' do 157 | it 'defaults to false' do 158 | expect(subject.send(:all_after_pass?)).to eq false 159 | end 160 | 161 | context 'when true' do 162 | let(:options) { { all_after_pass: true } } 163 | specify { expect(subject.send(:all_after_pass?)).to eq true } 164 | end 165 | end 166 | 167 | describe 'autorun' do 168 | it 'defaults to true' do 169 | expect(subject.send(:autorun?)).to eq true 170 | end 171 | 172 | context 'when false' do 173 | let(:options) { { autorun: false } } 174 | specify { expect(subject.send(:autorun?)).to eq false } 175 | end 176 | end 177 | end 178 | 179 | describe 'run' do 180 | before do 181 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('empty')) 182 | end 183 | 184 | context 'when Guard is in debug mode' do 185 | before do 186 | allow(Kernel).to receive(:system) { system('true') } 187 | allow(Guard::Compat::UI).to receive(:error) 188 | end 189 | 190 | it 'outputs command' do 191 | expect(Guard::Compat::UI).to receive(:debug).with("Running: ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard") 192 | subject.run(['test/test_minitest.rb']) 193 | end 194 | end 195 | 196 | context 'when binary is not found' do 197 | before do 198 | allow(Kernel).to receive(:system) { nil } 199 | allow(Guard::Compat::UI).to receive(:error) 200 | end 201 | 202 | it 'shows an error' do 203 | expect(Guard::Compat::UI).to receive(:error).with("No such file or directory - ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard") 204 | catch(:task_has_failed) { subject.run(['test/test_minitest.rb']) } 205 | end 206 | 207 | it 'throw a task_has_failed symbol' do 208 | expect { subject.run(['test/test_minitest.rb']) }.to throw_symbol(:task_has_failed) 209 | end 210 | end 211 | 212 | context 'with cli arguments' do 213 | let(:options) { { cli: '--seed 12345 --verbose' } } 214 | 215 | it 'passes :cli arguments' do 216 | expect(Kernel).to receive(:system).with( 217 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard --seed 12345 --verbose" 218 | ) { system('true') } 219 | 220 | subject.run(['test/test_minitest.rb']) 221 | end 222 | end 223 | 224 | context 'runs with specified directories included' do 225 | let(:options) { { include: %w(lib app) } } 226 | it 'runs with specified directories included' do 227 | expect(Kernel).to receive(:system).with( 228 | "ruby -I\"test\" -I\"spec\" -I\"lib\" -I\"app\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 229 | ) { system('true') } 230 | 231 | subject.run(['test/test_minitest.rb']) 232 | end 233 | end 234 | 235 | describe 'autorun disabled' do 236 | let(:options) { { autorun: false } } 237 | 238 | it 'does not require minitest/autorun' do 239 | expect(Kernel).to receive(:system).with( 240 | "ruby -I\"test\" -I\"spec\" -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 241 | ) { system('true') } 242 | 243 | subject.run(['test/test_minitest.rb']) 244 | end 245 | end 246 | 247 | context 'when running the full suite' do 248 | let(:options) { { all_env: { 'TESTS_ALL' => true } } } 249 | it 'sets env via all_env if running the full suite' do 250 | expect(Kernel).to receive(:system).with( 251 | { 'TESTS_ALL' => 'true' }, 252 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 253 | ) { system('true') } 254 | 255 | subject.run(['test/test_minitest.rb'], all: true) 256 | end 257 | end 258 | 259 | context 'allows string setting of all_env' do 260 | let(:options) { { all_env: 'TESTS_ALL' } } 261 | it 'allows string setting of all_env' do 262 | expect(Kernel).to receive(:system).with( 263 | { 'TESTS_ALL' => 'true' }, 264 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 265 | ) { system('true') } 266 | 267 | subject.run(['test/test_minitest.rb'], all: true) 268 | end 269 | end 270 | 271 | context 'runs with the specified environment' do 272 | let(:options) { { env: { MINITEST_TEST: 'test' } } } 273 | it 'runs with the specified environment' do 274 | expect(Kernel).to receive(:system).with( 275 | { 'MINITEST_TEST' => 'test' }, 276 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 277 | ) { system('true') } 278 | 279 | subject.run(['test/test_minitest.rb']) 280 | end 281 | end 282 | 283 | context 'with the all environment' do 284 | let(:options) { { env: { MINITEST_TEST: 'test', MINITEST: true }, all_env: { MINITEST_TEST: 'all' } } } 285 | it 'merges the specified environment' do 286 | expect(Kernel).to receive(:system).with( 287 | { 'MINITEST_TEST' => 'all', 'MINITEST' => 'true' }, 288 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 289 | ) { system('true') } 290 | 291 | subject.run(['test/test_minitest.rb'], all: true) 292 | end 293 | end 294 | 295 | describe 'in empty folder' do 296 | before do 297 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('empty')) 298 | end 299 | 300 | it 'runs without bundler and rubygems' do 301 | expect(Guard::Compat::UI).to receive(:info) 302 | expect(Kernel).to receive(:system).with( 303 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 304 | ) { system('true') } 305 | 306 | subject.run(['test/test_minitest.rb']) 307 | end 308 | 309 | context 'without bundler but rubygems' do 310 | let(:options) { { rubygems: true } } 311 | it 'runs without bundler but rubygems' do 312 | expect(Guard::Compat::UI).to receive(:info) 313 | expect(Kernel).to receive(:system).with( 314 | "ruby -I\"test\" -I\"spec\" -r rubygems -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 315 | ) { system('true') } 316 | 317 | subject.run(['test/test_minitest.rb']) 318 | end 319 | end 320 | end 321 | 322 | describe 'in bundler folder' do 323 | before do 324 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('bundler')) 325 | end 326 | 327 | context 'with bundler but not rubygems' do 328 | let(:options) { { bundler: true, rubygems: false } } 329 | it 'runs with bundler' do 330 | expect(Guard::Compat::UI).to receive(:info) 331 | expect(Kernel).to receive(:system).with( 332 | "bundle exec ruby -I\"test\" -I\"spec\" -r bundler/setup -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 333 | ) { system('true') } 334 | 335 | subject.run(['test/test_minitest.rb']) 336 | end 337 | end 338 | 339 | context 'without bundler but rubygems' do 340 | let(:options) { { bundler: false, rubygems: true } } 341 | it 'runs without bundler' do 342 | expect(Guard::Compat::UI).to receive(:info) 343 | expect(Kernel).to receive(:system).with( 344 | "ruby -I\"test\" -I\"spec\" -r rubygems -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 345 | ) { system('true') } 346 | 347 | subject.run(['test/test_minitest.rb']) 348 | end 349 | end 350 | 351 | context 'without bundler and rubygems' do 352 | let(:options) { { bundler: false, rubygems: false } } 353 | it 'runs without bundler' do 354 | expect(Guard::Compat::UI).to receive(:info) 355 | expect(Kernel).to receive(:system).with( 356 | "ruby -I\"test\" -I\"spec\" -r minitest/autorun -r ./test/test_minitest.rb#{@require_old_runner} -e \"\" -- --guard" 357 | ) { system('true') } 358 | 359 | subject.run(['test/test_minitest.rb']) 360 | end 361 | end 362 | end 363 | 364 | describe 'all_after_pass' do 365 | describe 'when set' do 366 | let(:options) { { all_after_pass: true } } 367 | 368 | it 'runs all tests after success' do 369 | allow(Kernel).to receive(:system) { system('true') } 370 | expect(subject).to receive(:run_all) 371 | 372 | subject.run(['test/test_minitest.rb']) 373 | end 374 | 375 | it 'does not run all tests after failure' do 376 | allow(Kernel).to receive(:system) { system('false') } 377 | expect(subject).to receive(:run_all).never 378 | 379 | subject.run(['test/test_minitest.rb']) 380 | end 381 | end 382 | 383 | describe 'when unset' do 384 | let(:options) { { all_after_pass: false } } 385 | 386 | it 'does not run all tests again after success' do 387 | allow(Kernel).to receive(:system) { system('true') } 388 | expect(subject).to receive(:run_all).never 389 | 390 | subject.run(['test/test_minitest.rb']) 391 | end 392 | end 393 | end 394 | 395 | describe 'zeus' do 396 | context 'with default zeus command' do 397 | let(:options) { { zeus: true } } 398 | it 'runs with default zeus command' do 399 | expect(Guard::Compat::UI).to receive(:info) 400 | expect(Kernel).to receive(:system).with('zeus test ./test/test_minitest.rb') { system('true') } 401 | 402 | subject.run(['test/test_minitest.rb']) 403 | end 404 | end 405 | 406 | context 'with custom zeus command' do 407 | let(:options) { { zeus: 'abcxyz' } } 408 | it 'runs with custom zeus command' do 409 | expect(Guard::Compat::UI).to receive(:info) 410 | expect(Kernel).to receive(:system).with('zeus abcxyz ./test/test_minitest.rb') { system('true') } 411 | 412 | subject.run(['test/test_minitest.rb']) 413 | end 414 | end 415 | 416 | describe 'notifications' do 417 | let(:options) { { zeus: true } } 418 | 419 | it 'provides success notification when the zeus exit status is 0' do 420 | expect(Kernel).to receive(:system).with('zeus test ./test/test_minitest.rb') { system('true') } 421 | expect(Guard::Compat::UI).to receive(:notify).with('Running: test/test_minitest.rb', title: 'Minitest results', image: :success) 422 | 423 | subject.run(['test/test_minitest.rb']) 424 | end 425 | 426 | it 'provides failed notification when the zeus exit status is non-zero or the command failed' do 427 | expect(Kernel).to receive(:system).with('zeus test ./test/test_minitest.rb') { system('false') } 428 | expect(Guard::Compat::UI).to receive(:notify).with('Running: test/test_minitest.rb', title: 'Minitest results', image: :failed) 429 | 430 | subject.run(['test/test_minitest.rb']) 431 | end 432 | end 433 | end 434 | 435 | describe 'spring' do 436 | context 'when true' do 437 | let(:options) { { spring: true } } 438 | it 'runs with default spring command' do 439 | expect(Guard::Compat::UI).to receive(:info) 440 | expect(Kernel).to receive(:system).with('bin/rake test test/test_minitest.rb') { system('true') } 441 | 442 | subject.run(['test/test_minitest.rb']) 443 | end 444 | 445 | it 'runs with a clean environment' do 446 | expect(Guard::Compat::UI).to receive(:info) 447 | expect(Bundler).to receive(:with_original_env).and_yield 448 | expect(Kernel).to receive(:system).with('bin/rake test test/test_minitest.rb') { system('true') } 449 | 450 | subject.run(['test/test_minitest.rb']) 451 | end 452 | it 'provides success notification when the spring exit status is 0' do 453 | expect(Kernel).to receive(:system).with('bin/rake test test/test_minitest.rb') { system('true') } 454 | expect(Guard::Compat::UI).to receive(:notify).with('Running: test/test_minitest.rb', title: 'Minitest results', image: :success) 455 | 456 | subject.run(['test/test_minitest.rb']) 457 | end 458 | 459 | it 'provides failed notification when the spring exit status is non-zero or the command failed' do 460 | expect(Kernel).to receive(:system).with('bin/rake test test/test_minitest.rb') { system('false') } 461 | expect(Guard::Compat::UI).to receive(:notify).with('Running: test/test_minitest.rb', title: 'Minitest results', image: :failed) 462 | 463 | subject.run(['test/test_minitest.rb']) 464 | end 465 | end 466 | 467 | context 'with custom spring command' do 468 | let(:options) { { spring: 'spring rake test' } } 469 | it 'runs with custom spring command' do 470 | expect(Guard::Compat::UI).to receive(:info) 471 | expect(Kernel).to receive(:system).with('spring rake test test/test_minitest.rb') { system('true') } 472 | 473 | subject.run(['test/test_minitest.rb']) 474 | end 475 | end 476 | 477 | context 'with true and cli options' do 478 | let(:options) { { spring: true, cli: '--seed 12345 --verbose' } } 479 | it 'runs default spring command with cli' do 480 | expect(Guard::Compat::UI).to receive(:info) 481 | expect(Kernel).to receive(:system).with('bin/rake test test/test_minitest.rb -- --seed 12345 --verbose') { system('true') } 482 | 483 | subject.run(['test/test_minitest.rb']) 484 | end 485 | end 486 | 487 | context 'with custom command and cli options' do 488 | let(:options) { { spring: 'spring rake test', cli: '--seed 12345 --verbose' } } 489 | it 'runs custom spring command with cli' do 490 | expect(Guard::Compat::UI).to receive(:info) 491 | expect(Kernel).to receive(:system).with('spring rake test test/test_minitest.rb -- --seed 12345 --verbose') { system('true') } 492 | 493 | subject.run(['test/test_minitest.rb']) 494 | end 495 | end 496 | end 497 | 498 | describe 'drb' do 499 | context 'with drb' do 500 | let(:options) { { drb: true } } 501 | it 'should run with drb' do 502 | expect(Guard::Compat::UI).to receive(:info) 503 | expect(Kernel).to receive(:system).with('testdrb ./test/test_minitest.rb') { system('true') } 504 | 505 | subject.run(['test/test_minitest.rb']) 506 | end 507 | end 508 | 509 | context 'with specific directories' do 510 | let(:options) { { drb: true, include: %w(lib app) } } 511 | it 'runs with specified directories included' do 512 | expect(Kernel).to receive(:system) 513 | .with("testdrb -I\"lib\" -I\"app\" ./test/test_minitest.rb") { system('true') } 514 | 515 | subject.run(['test/test_minitest.rb']) 516 | end 517 | end 518 | end 519 | 520 | describe 'when no paths are passed' do 521 | it 'does not run a command' do 522 | expect(Kernel).to_not receive(:system) 523 | 524 | subject.run([]) 525 | end 526 | 527 | it 'still runs all if requested' do 528 | expect(Kernel).to receive(:system) 529 | .with("ruby -I\"test\" -I\"spec\" -r minitest/autorun#{@require_old_runner} -e \"\" -- --guard") { system('true') } 530 | 531 | expect(subject.run([], all: true)).to eq true 532 | end 533 | end 534 | 535 | it 'includes the --guard flag to signal minitest to load the plugin' do 536 | expect(Kernel).to receive(:system).with( 537 | a_string_starting_with('ruby').and(a_string_including('-- --guard')) 538 | ) { system('true') } 539 | 540 | subject.run(['test/test_minitest.rb']) 541 | end 542 | end 543 | 544 | describe 'run_all' do 545 | it 'runs all tests' do 546 | paths = %w(test/test_minitest_1.rb test/test_minitest_2.rb) 547 | allow(subject.inspector).to receive(:clean_all).and_return(paths) 548 | expect(subject).to receive(:run).with(paths, all: true).and_return(true) 549 | 550 | expect(subject.run_all).to eq true 551 | end 552 | end 553 | 554 | describe 'run_on_modifications' do 555 | before do 556 | @paths = %w(test/test_minitest_1.rb test/test_minitest_2.rb) 557 | allow(Dir).to receive(:pwd).and_return(fixtures_path.join('empty')) 558 | allow(Dir).to receive(:[]).and_return(@paths) 559 | end 560 | 561 | describe 'when all paths are passed' do 562 | before do 563 | allow(subject.inspector).to receive(:clean).and_return(@paths) 564 | end 565 | 566 | it 'runs minitest in all paths' do 567 | expect(subject).to receive(:run).with(@paths, all: true).and_return(true) 568 | 569 | expect(subject.run_on_modifications(@paths)).to eq true 570 | end 571 | 572 | context 'even when all_after_pass is enabled' do 573 | let(:options) { { all_after_pass: true } } 574 | it 'does not run all tests again after success' do 575 | allow(Kernel).to receive(:system) { system('true') } 576 | expect(subject).to receive(:run_all).never 577 | 578 | expect(subject.run_on_modifications(@paths)).to eq true 579 | end 580 | end 581 | end 582 | 583 | describe 'when not all paths are passed' do 584 | before do 585 | allow(subject.inspector).to receive(:clean).and_return(['test/test_minitest_1.rb']) 586 | end 587 | 588 | it 'runs minitest in paths' do 589 | expect(subject).to receive(:run).with(['test/test_minitest_1.rb'], all: false).and_return(true) 590 | 591 | expect(subject.run_on_modifications(@paths)).to eq true 592 | end 593 | 594 | context 'with all_after_pass enabled' do 595 | let(:options) { { all_after_pass: true } } 596 | 597 | before do 598 | allow(subject.inspector).to receive(:clean_all).and_return( 599 | ['test/test_minitest_1.rb', 'test/test_minitest_2.rb'] 600 | ) 601 | end 602 | 603 | it 'runs all tests again after success if all_after_pass enabled' do 604 | subject 605 | allow(Kernel).to receive(:system) { system('true') } 606 | allow(subject).to receive(:run).with(['test/test_minitest_1.rb'], all: false).and_call_original 607 | expect(subject).to receive(:run).with(@paths, all: true).and_return(true) 608 | 609 | expect(subject.run_on_modifications(@paths)).to eq true 610 | end 611 | end 612 | end 613 | end 614 | 615 | describe 'run_on_additions' do 616 | it 'clears the test file cache and runs minitest for the new path' do 617 | allow(subject.inspector).to receive(:clean).with(['test/guard/minitest/test_new.rb']).and_return(['test/guard/minitest/test_new.rb']) 618 | expect(subject.inspector).to receive(:clear_memoized_test_files) 619 | 620 | expect(subject.run_on_additions(['test/guard/minitest/test_new.rb'])).to eq true 621 | end 622 | end 623 | 624 | describe 'run_on_removals' do 625 | it 'clears the test file cache and does not run minitest' do 626 | allow(subject.inspector).to receive(:clean).with(['test/guard/minitest/test_deleted.rb']).and_return(['test/guard/minitest/test_deleted.rb']) 627 | expect(subject.inspector).to receive(:clear_memoized_test_files) 628 | expect(subject).to receive(:run).never 629 | 630 | subject.run_on_removals(['test/guard/minitest/test_deleted.rb']) 631 | end 632 | end 633 | 634 | context 'when guard is not included' do 635 | before do 636 | allow(Kernel).to receive(:system).and_call_original 637 | end 638 | 639 | it 'loads correctly as minitest plugin' do 640 | code = <<-EOS 641 | require 'guard/minitest/runner' 642 | EOS 643 | 644 | system(*%w(bundle exec ruby -e) + [code]) 645 | end 646 | end 647 | end 648 | -------------------------------------------------------------------------------- /spec/lib/guard/minitest/utils_spec.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest/utils' 2 | 3 | RSpec.describe Guard::Minitest::Utils do 4 | context 'when guard is included first' do 5 | it 'loads correctly as minitest plugin' do 6 | code = <<-EOS 7 | require 'guard/minitest/utils' 8 | EOS 9 | 10 | system(*%w(bundle exec ruby -rguard -e) + [code]) 11 | end 12 | end 13 | 14 | context 'when guard is not included' do 15 | it 'loads correctly as minitest plugin' do 16 | code = <<-EOS 17 | require 'guard/minitest/utils' 18 | EOS 19 | 20 | system(*%w(bundle exec ruby -e) + [code]) 21 | end 22 | 23 | if !Guard::Minitest::Utils.minitest_version_gte_5? 24 | context 'when runner for old minitest is used' do 25 | it "load guard automatically" do 26 | code = <<-EOS 27 | require 'guard/minitest/runners/old_runner' 28 | exit 0 29 | EOS 30 | 31 | expect(system(*%w(bundle exec ruby -e) + [code])).to eq(true) 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/lib/guard/minitest_spec.rb: -------------------------------------------------------------------------------- 1 | require 'guard/minitest' 2 | 3 | RSpec.describe Guard::Minitest do 4 | subject { Guard::Minitest } 5 | 6 | let(:runner) { Guard::Minitest::Runner } 7 | let(:guard) { subject.new } 8 | 9 | describe 'initialization' do 10 | it 'initializes runner with default options' do 11 | expect(runner).to receive(:new).with(all_on_start: true) 12 | 13 | subject.new 14 | end 15 | end 16 | 17 | describe 'start' do 18 | it 'runs all tests at start via runner' do 19 | expect_any_instance_of(subject).to receive(:run_all) 20 | 21 | subject.new.start 22 | end 23 | 24 | it 'do not run all tests if you pass run_all_on_start: false' do 25 | expect_any_instance_of(subject).to receive(:run_all).never 26 | 27 | subject.new(all_on_start: false).start 28 | end 29 | end 30 | 31 | describe 'stop' do 32 | it 'returns true' do 33 | expect(guard.stop).to eq true 34 | end 35 | end 36 | 37 | describe 'reload' do 38 | it 'returns true' do 39 | expect(guard.reload).to eq true 40 | end 41 | end 42 | 43 | describe 'run_on_modifications' do 44 | it 'is run through runner' do 45 | expect_any_instance_of(runner).to receive(:run_on_modifications) 46 | .and_return(true) 47 | 48 | guard.run_on_modifications 49 | end 50 | end 51 | 52 | describe 'run_on_additions' do 53 | let(:paths) { %w(path1 path2) } 54 | 55 | it 'is run through runner' do 56 | expect_any_instance_of(runner).to receive(:run_on_additions).with(paths) 57 | 58 | guard.run_on_additions(paths) 59 | end 60 | end 61 | 62 | describe 'run_on_removals' do 63 | let(:paths) { %w(path1 path2) } 64 | 65 | it 'runs run_on_removals via runner' do 66 | expect_any_instance_of(runner).to receive(:run_on_removals).with(paths) 67 | 68 | guard.run_on_removals(paths) 69 | end 70 | end 71 | 72 | describe 'halting and throwing on test failure' do 73 | it 'throws on failed test run' do 74 | stubbed_runner = double 75 | allow(stubbed_runner).to receive(:run).and_return(false) 76 | expect(stubbed_runner).to receive(:run_all) 77 | expect(stubbed_runner).to receive(:run_on_modifications) 78 | 79 | guard.runner = stubbed_runner 80 | 81 | expect { guard.run_all }.to throw_symbol :task_has_failed 82 | expect { guard.run_on_modifications }.to throw_symbol :task_has_failed 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rspec' 2 | 3 | if ENV['CI'] 4 | require 'coveralls' 5 | Coveralls.wear! do 6 | add_filter 'spec' 7 | end 8 | end 9 | 10 | require 'guard/compat/test/helper' 11 | 12 | RSpec.configure do |config| 13 | config.expect_with :rspec do |expectations| 14 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 15 | end 16 | 17 | config.mock_with :rspec do |mocks| 18 | mocks.verify_partial_doubles = true 19 | end 20 | 21 | config.filter_run :focus 22 | config.run_all_when_everything_filtered = true 23 | 24 | config.disable_monkey_patching! 25 | 26 | # config.warnings = true 27 | 28 | config.default_formatter = 'doc' if config.files_to_run.one? 29 | 30 | # config.profile_examples = 10 31 | 32 | config.order = :random 33 | 34 | Kernel.srand config.seed 35 | 36 | def fixtures_path 37 | @fixtures_path ||= Pathname.new(File.expand_path('../fixtures/', __FILE__)) 38 | end 39 | 40 | config.before do 41 | allow(Guard::Compat::UI).to receive(:info) 42 | end 43 | end 44 | --------------------------------------------------------------------------------