smokescreen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in smokescreen.gemspec
4
+ gemspec
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2013 LivingSocial, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,84 @@
1
+ # Smokescreen
2
+
3
+ Quickly run critical tests on your app, recently changed tests, or tests related to recent changed files
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'smokescreen'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install smokescreen
18
+
19
+
20
+ ## Usage
21
+
22
+ Setting up smokescreen is fairly easy, include the gem in your `Gemfile`, and then require it in your primary `Rakefile` or in any of your `lib/tasks/other_rakefiles`.
23
+
24
+ #in Gemfile
25
+ group :development, :test do
26
+ gem 'smokescreen'
27
+ end
28
+
29
+ #in a Rakefile
30
+ require 'smokescreen'
31
+
32
+ #below require in rake file
33
+ Smokescreen.configure(:critical_tests => ["test/functional/purchases_controller_test.rb", "test/functional/important_controller_test.rb"])
34
+
35
+ After you require smokescreen make sure to configure the critical tests. Just pass in an array of tests that you want to be be considered part of the critical set of tests.
36
+
37
+ ### After configuring Smokescreen
38
+
39
+ You can view all the tasks together running `bundle exec rake -T smoke`, as you can tell there are four main groupings of tests current, deploy, previous, and recent.
40
+
41
+
42
+ rake test:smokescreen:critical:functionals # Run tests for critical:functionals
43
+ rake test:smokescreen:current:all # run most important tests as well as tests for current...
44
+ rake test:smokescreen:current:changed # run tests related to currently changed files (git diff)
45
+ rake test:smokescreen:current:changed_tests # run currently changed test files (git diff)
46
+ rake test:smokescreen:current:functionals # Run tests for functionals
47
+ rake test:smokescreen:current:functionals:changed_tests # Run tests for functionals:changed_tests
48
+ rake test:smokescreen:current:units # Run tests for units
49
+ rake test:smokescreen:current:units:changed_tests # Run tests for units:changed_tests
50
+ rake test:smokescreen:deploy:all # run most important tests as well as tests for files c...
51
+ rake test:smokescreen:deploy:changed # run tests related to files changed since last deploy
52
+ rake test:smokescreen:deploy:functionals # Run tests for functionals
53
+ rake test:smokescreen:deploy:units # Run tests for units
54
+ rake test:smokescreen:previous:all # run most important tests as well as tests for previou...
55
+ rake test:smokescreen:previous:changed # run tests related to previously changed files (last c...
56
+ rake test:smokescreen:previous:changed_tests # run previously changed test files (last commit, git s...
57
+ rake test:smokescreen:previous:functionals # Run tests for functionals
58
+ rake test:smokescreen:previous:functionals:changed_tests # Run tests for functionals:changed_tests
59
+ rake test:smokescreen:previous:units # Run tests for units
60
+ rake test:smokescreen:previous:units:changed_tests # Run tests for units:changed_tests
61
+ rake test:smokescreen:recent:all # run most important tests as well as recently effected...
62
+ rake test:smokescreen:recent:changed # run tests for currently changed files (git diff)
63
+ rake test:smokescreen:recent:changed_tests # run recently changed test files (current and previous...
64
+ rake test:smokescreen:recent:functionals # Run tests for functionals
65
+ rake test:smokescreen:recent:functionals:changed_tests # Run tests for functionals:changed_tests
66
+ rake test:smokescreen:recent:units # Run tests for units
67
+ rake test:smokescreen:recent:units:changed_tests # Run tests for units:changed_tests
68
+
69
+
70
+ ### Running Smokescreen
71
+
72
+ The most common task I run is `rake test:smokescreen:recent:all`, as it is the most comprehensive. That task runs the critical tests, test files related to currently change files (as found by git diff), and test files related to recently changed files (as found by git show). It is easy to target more specifically if you choose.
73
+
74
+ I also find running `rake test:smokescreen:previous:changed_tests` or `rake test:smokescreen:previous:all` handy when doing code review on another developers cherry-picked commit. Making sure the tests don't have one of the "it works on my machine" bugs.
75
+
76
+ Smokescreen has only been used on a small set of projects, and doesn't currently support anything other than `test:unit`. I know now that it is extracted out that I plan to add it to some other projects and hopefully it will be easy to make some improvements to the tool. I already know there could be some great improvements to the process of matching up likely related test files to recent changes. Adding support to run any recently failing tests from CI would also be another great feature.
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it
81
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
82
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
83
+ 4. Push to the branch (`git push origin my-new-feature`)
84
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,15 @@
1
+ require "smokescreen/version"
2
+
3
+ module Smokescreen
4
+ @@critical_tests = []
5
+
6
+ def self.configure(options = {})
7
+ @@critical_tests = options.fetch(:critical_tests){[]}
8
+ require "smokescreen/tasks"
9
+ end
10
+
11
+ def self.critical_tests
12
+ @@critical_tests
13
+ end
14
+
15
+ end
@@ -0,0 +1,286 @@
1
+ require 'rake/testtask'
2
+
3
+ namespace :test do
4
+ namespace :smokescreen do
5
+
6
+ #####
7
+ # Rake is so weird, but to define a task all code inside the task is evaluated at definition time
8
+ # This has lead to splitting out the methods, so that when defined they should really do nothing,
9
+ # but when invoked they should run and output info.
10
+ #
11
+ # I am sure this means there is a better way to do this, but I don't know it
12
+ ####
13
+ def functionals_critical(test_changed_files, t)
14
+ t.libs << "test"
15
+ t.verbose = true
16
+ if !test_changed_files.empty?
17
+ t.test_files = test_changed_files
18
+ else
19
+ t.test_files = []
20
+ end
21
+ end
22
+
23
+ def critical_test_files
24
+ Smokescreen.critical_tests
25
+ end
26
+
27
+ desc 'runs most critical functional tests'
28
+ Rake::TestTask.new("critical:functionals") do |t|
29
+ functionals_critical(critical_test_files, t)
30
+ end
31
+
32
+ # this won't work until your capistrano supports fetching the currently deployed git SHA on production
33
+ def changed_files_since_deploy
34
+ if File.exists?("log/latest-REVISION-syntaxcheck")
35
+ revision = File.read("log/latest-REVISION-syntaxcheck").chomp
36
+
37
+ `git whatchanged #{revision}..HEAD`.split("\n").select{|l| l =~ /^\:/}.collect {|l| l.split("\t")[1]}.sort.uniq
38
+ else
39
+ puts "log/latest-REVISION-syntaxcheck not found. run 'cap fetch_currently_deployed_version' to get it"
40
+ []
41
+ end
42
+ end
43
+
44
+ # file changes detected by git diff
45
+ def currently_changed_files
46
+ `git status --porcelain`.split("\n").map{ |file| file.split.last }
47
+ end
48
+
49
+ # file changes detected by git show
50
+ def previously_changed_files
51
+ `git show --pretty="format:" --name-only`.split("\n")
52
+ end
53
+
54
+ # based on a list of files changes try to detect functional tests we should likely run
55
+ # include test files that were directly modified
56
+ def functionals_changed(test_changed_files, t)
57
+ changed_controllers = []
58
+ changed_functional_tests = []
59
+ changed_view_directories = Set.new
60
+ test_changed_files.each do |file|
61
+ controller_match = file.match(/app\/controllers\/(.*).rb/)
62
+ if controller_match
63
+ changed_controllers << controller_match[1]
64
+ end
65
+
66
+ view_match = file.match(/app\/views\/(.*)\/.+\.erb/)
67
+ if view_match
68
+ changed_view_directories << view_match[1]
69
+ end
70
+
71
+ functional_test_match = file.match(/test\/functional\/(.*).rb/)
72
+ if functional_test_match
73
+ changed_functional_tests << functional_test_match[1]
74
+ end
75
+ end
76
+
77
+ test_files = FileList['test/functional/**/*_test.rb'].select{|file| changed_controllers.any?{|controller| file.match(/test\/functional\/#{controller}_test.rb/) }} +
78
+ FileList['test/functional/**/*_test.rb'].select{|file| changed_view_directories.any?{|view_directory| file.match(/test\/functional\/#{view_directory}_controller_test.rb/) }} +
79
+ FileList['test/functional/**/*_test.rb'].select{|file|
80
+ (changed_functional_tests.any?{|functional_test| file.match(/test\/functional\/#{functional_test}.rb/) } ||
81
+ test_changed_files.any?{|changed_file| file==changed_file })
82
+ }
83
+
84
+ test_files = test_files.uniq
85
+ test_files = test_files.reject{ |f| Smokescreen.critical_tests.include?(f) }
86
+
87
+ t.libs << "test"
88
+ t.verbose = true
89
+ if !test_files.empty?
90
+ t.test_files = test_files
91
+ else
92
+ t.test_files = []
93
+ end
94
+ end
95
+
96
+ # run tests against any functional test file, that has been modified
97
+ def functionals_changed_tests(test_changed_files, t)
98
+ test_changed_files = test_changed_files.split("\n") if test_changed_files.is_a?(String)
99
+ test_files = FileList['test/functional/**/*_test.rb'].select{|file| test_changed_files.any?{|changed_file| file==changed_file }}
100
+ test_files = test_files.uniq
101
+ test_files = test_files.reject{ |f| Smokescreen.critical_tests.include?(f) }
102
+
103
+ t.libs << "test"
104
+ t.verbose = true
105
+ if !test_files.empty?
106
+ t.test_files = test_files
107
+ else
108
+ t.test_files = []
109
+ end
110
+ end
111
+
112
+ # based on a list of files changes try to detect unit tests we should likely run.
113
+ # include test files that were directly modified
114
+ def units_changed(test_changed_files, t)
115
+ changed_models = []
116
+ test_changed_files.each do |file|
117
+ matched = file.match(/app\/models\/(.*).rb/)
118
+ if matched
119
+ changed_models << matched[1]
120
+ end
121
+ end
122
+ test_files = FileList['test/unit/*_test.rb'].select{|file|
123
+ (changed_models.any?{|model| file.match(/test\/unit\/#{model}_test.rb/) } ||
124
+ test_changed_files.any?{|changed_file| file==changed_file })
125
+ }
126
+ test_files = test_files.uniq
127
+
128
+ t.libs << "test"
129
+ t.verbose = true
130
+ if !test_files.empty?
131
+ t.test_files = test_files
132
+ else
133
+ t.test_files = []
134
+ end
135
+ end
136
+
137
+ # run tests against any unit test file, that has been modified
138
+ def units_changed_tests(test_changed_files, t)
139
+ test_changed_files = test_changed_files.split("\n") if test_changed_files.is_a?(String)
140
+ test_files = FileList['test/unit/*_test.rb'].select{|file| test_changed_files.any?{|changed_file| file==changed_file }}
141
+ test_files = test_files.uniq
142
+
143
+ t.libs << "test"
144
+ t.verbose = true
145
+ if !test_files.empty?
146
+ t.test_files = test_files
147
+ else
148
+ t.test_files = []
149
+ end
150
+ end
151
+
152
+ namespace :deploy do
153
+ desc 'run most important tests as well as tests for files changed since the last deploy'
154
+ task :all do
155
+ Rake::Task["test:smokescreen:critical:functionals"].invoke
156
+ Rake::Task["test:smokescreen:deploy:changed"].invoke
157
+ end
158
+
159
+ desc 'run tests related to files changed since last deploy'
160
+ task :changed do
161
+ Rake::Task["test:smokescreen:deploy:functionals"].invoke
162
+ Rake::Task["test:smokescreen:deploy:units"].invoke
163
+ end
164
+
165
+ Rake::TestTask.new("functionals") do |t|
166
+ functionals_changed(changed_files_since_deploy, t)
167
+ end
168
+
169
+ Rake::TestTask.new("units") do |t|
170
+ units_changed(changed_files_since_deploy, t)
171
+ end
172
+ end
173
+
174
+ namespace :previous do
175
+ desc 'run most important tests as well as tests for previously changed files (last commit, git show)'
176
+ task :all do
177
+ Rake::Task["test:smokescreen:critical:functionals"].invoke
178
+ Rake::Task["test:smokescreen:previous:changed"].invoke
179
+ end
180
+
181
+ desc 'run tests related to previously changed files (last commit, git show)'
182
+ task :changed do
183
+ Rake::Task["test:smokescreen:previous:functionals"].invoke
184
+ Rake::Task["test:smokescreen:previous:units"].invoke
185
+ end
186
+
187
+ desc 'run previously changed test files (last commit, git show)'
188
+ task :changed_tests do
189
+ Rake::Task["test:smokescreen:previous:functionals:changed_tests"].invoke
190
+ Rake::Task["test:smokescreen:previous:units:changed_tests"].invoke
191
+ end
192
+
193
+ Rake::TestTask.new("functionals") do |t|
194
+ functionals_changed(previously_changed_files, t)
195
+ end
196
+
197
+ Rake::TestTask.new("functionals:changed_tests") do |t|
198
+ functionals_changed_tests(previously_changed_files, t)
199
+ end
200
+
201
+ Rake::TestTask.new("units") do |t|
202
+ units_changed(previously_changed_files, t)
203
+ end
204
+
205
+ Rake::TestTask.new("units:changed_tests") do |t|
206
+ units_changed_tests(previously_changed_files, t)
207
+ end
208
+ end
209
+
210
+ namespace :current do
211
+ desc 'run most important tests as well as tests for currently changed files (git diff)'
212
+ task :all do
213
+ Rake::Task["test:smokescreen:critical:functionals"].invoke
214
+ Rake::Task["test:smokescreen:current:changed"].invoke
215
+ end
216
+
217
+ desc 'run tests related to currently changed files (git diff)'
218
+ task :changed do
219
+ Rake::Task["test:smokescreen:current:functionals"].invoke
220
+ Rake::Task["test:smokescreen:current:units"].invoke
221
+ end
222
+
223
+ desc 'run currently changed test files (git diff)'
224
+ task :changed_tests do
225
+ Rake::Task["test:smokescreen:current:functionals:changed_tests"].invoke
226
+ Rake::Task["test:smokescreen:current:units:changed_tests"].invoke
227
+ puts @results
228
+ end
229
+
230
+ Rake::TestTask.new("functionals") do |t|
231
+ functionals_changed(currently_changed_files, t)
232
+ end
233
+
234
+ Rake::TestTask.new("functionals:changed_tests") do |t|
235
+ functionals_changed_tests(currently_changed_files, t)
236
+ end
237
+
238
+ Rake::TestTask.new("units") do |t|
239
+ units_changed(currently_changed_files, t)
240
+ end
241
+
242
+ Rake::TestTask.new("units:changed_tests") do |t|
243
+ units_changed_tests(currently_changed_files, t)
244
+ end
245
+
246
+ end
247
+
248
+ namespace :recent do
249
+ desc 'run most important tests as well as recently effected tests (git diff + git show)'
250
+ task :all do
251
+ Rake::Task["test:smokescreen:critical:functionals"].invoke
252
+ Rake::Task["test:smokescreen:recent:changed"].invoke
253
+ end
254
+
255
+ desc 'run tests for currently changed files (git diff)'
256
+ task :changed do
257
+ Rake::Task["test:smokescreen:recent:functionals"].invoke
258
+ Rake::Task["test:smokescreen:recent:units"].invoke
259
+ end
260
+
261
+ desc 'run recently changed test files (current and previous commit test files)'
262
+ task :changed_tests do
263
+ Rake::Task["test:smokescreen:recent:functionals:changed_tests"].invoke
264
+ Rake::Task["test:smokescreen:recent:units:changed_tests"].invoke
265
+ end
266
+
267
+ Rake::TestTask.new("functionals") do |t|
268
+ functionals_changed((previously_changed_files + currently_changed_files).uniq, t)
269
+ end
270
+
271
+ Rake::TestTask.new("functionals:changed_tests") do |t|
272
+ functionals_changed_tests((previously_changed_files + currently_changed_files).uniq, t)
273
+ end
274
+
275
+ Rake::TestTask.new("units") do |t|
276
+ units_changed((previously_changed_files + currently_changed_files).uniq, t)
277
+ end
278
+
279
+ Rake::TestTask.new("units:changed_tests") do |t|
280
+ units_changed_tests((previously_changed_files + currently_changed_files).uniq, t)
281
+ end
282
+
283
+ end
284
+
285
+ end
286
+ end
@@ -0,0 +1,3 @@
1
+ module Smokescreen
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'smokescreen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "smokescreen"
8
+ spec.version = Smokescreen::VERSION
9
+ spec.authors = ["Dan Mayer"]
10
+ spec.email = ["dan.mayer@livingsocial.com"]
11
+ spec.description = %q{Smokescreen is a smoke test suite that tries to run the most critical and most likely effected tests related to recent changes.}
12
+ spec.summary = %q{Smokescreen the minimal final smoke tests for a project}
13
+ spec.homepage = ""
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
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smokescreen
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Dan Mayer
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-09-13 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 9
30
+ segments:
31
+ - 1
32
+ - 3
33
+ version: "1.3"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description: Smokescreen is a smoke test suite that tries to run the most critical and most likely effected tests related to recent changes.
51
+ email:
52
+ - dan.mayer@livingsocial.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - .gitignore
61
+ - Gemfile
62
+ - LICENSE.txt
63
+ - README.md
64
+ - Rakefile
65
+ - lib/smokescreen.rb
66
+ - lib/smokescreen/tasks.rb
67
+ - lib/smokescreen/version.rb
68
+ - smokescreen.gemspec
69
+ has_rdoc: true
70
+ homepage: ""
71
+ licenses:
72
+ - MIT
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.6.2
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Smokescreen the minimal final smoke tests for a project
103
+ test_files: []
104
+