fixture_reducer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ gem "bump"
5
+ gem "rake"
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ require "bump/tasks"
data/Readme.md ADDED
@@ -0,0 +1,26 @@
1
+ Test speedup by replacing fixtures :all with only the necessary
2
+
3
+ - reduces fixtures :all
4
+ - tries common fixtures first before going to one-by-one approach
5
+ - uses zeus if zeus is running (faster)
6
+
7
+ Install
8
+ =======
9
+
10
+ gem install fixture_reducer
11
+
12
+ Usage
13
+ =====
14
+
15
+ fixture-reducer test/foo_test.rb test/bar_test.rb ...
16
+
17
+ TODO
18
+ ====
19
+ - tests + travis (please use rspec)
20
+ - rspec support
21
+
22
+ Author
23
+ ======
24
+ [Michael Grosser](http://grosser.it)<br/>
25
+ michael@grosser.it<br/>
26
+ License: MIT<br/>
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'fixture_reducer'
4
+
5
+ raise "pass me test files" if ARGV.empty?
6
+ puts "running on #{ARGV.inspect}"
7
+
8
+ ARGV.each { |file| FixtureReducer.new(file).reduce_fixtures! }
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ name = "fixture_reducer"
3
+ require "#{name.gsub("-","/")}/version"
4
+
5
+ Gem::Specification.new name, FixtureReducer::VERSION do |s|
6
+ s.summary = "Test speedup by replacing fixtures :all with only the necessary"
7
+ s.authors = ["Michael Grosser"]
8
+ s.email = "michael@grosser.it"
9
+ s.homepage = "http://github.com/grosser/#{name}"
10
+ s.files = `git ls-files`.split("\n")
11
+ s.license = "MIT"
12
+ s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem")
13
+ s.cert_chain = ["gem-public_cert.pem"]
14
+ s.executables = ["fixture-reducer"]
15
+ end
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
3
+ YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
4
+ MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
5
+ aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
6
+ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
7
+ MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
8
+ cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
9
+ 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
10
+ h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
11
+ FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
12
+ /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
13
+ WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
14
+ AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
15
+ Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
16
+ /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
17
+ NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
18
+ y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
19
+ ycwMXfl0
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,3 @@
1
+ module FixtureReducer
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,147 @@
1
+ require "fixture_reducer/version"
2
+
3
+ module FixtureReducer
4
+ class FixtureReducer
5
+ # also use multiline fixture declarations
6
+ FIXTURE_REX = /(^\s+)fixtures\s+([^,\s]+(,\s*[^,\s]+)*)/m
7
+
8
+ attr_reader :test_file
9
+
10
+ def initialize(test_file)
11
+ @test_file = test_file
12
+ @test_folder = test_file.split("/").first
13
+ @test_extension = "_#{@test_folder}.rb"
14
+ end
15
+
16
+ def reduce_fixtures!
17
+ if fixtures = fixture_params(test_file)
18
+ puts "#{test_file} uses #{fixtures.join(", ")}"
19
+
20
+ if run_with(fixtures)
21
+ puts "initial run: SUCCESS"
22
+ original_fixtures = fixtures.dup
23
+ fixtures = reduced_via_common([99, 95, 90, 80, 50]) if fixtures == [":all"]
24
+ fixtures = reduce_one_by_one(fixtures)
25
+ report_and_keep_reduction(original_fixtures, fixtures)
26
+ else
27
+ puts "initial run: FAILED"
28
+ end
29
+ else
30
+ puts "did not find fixtures in #{test_file}"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def usage_stats
37
+ @usage_stats ||= begin
38
+ used_fixtures = Dir["#{@test_folder}/**/*#{@test_extension}"].map { |file| fixture_params(file) }.compact.flatten
39
+ used_fixtures -= [":all"]
40
+ used_fixtures.flatten.group_by(&:to_s).map { |g, f| [g, f.size] }.sort_by(&:last)
41
+ end.freeze
42
+ end
43
+
44
+ def common_fixtures(percent)
45
+ usage = usage_stats.dup
46
+ total = usage.map(&:last).inject(&:+)
47
+ used = 0
48
+ used += usage.shift.last while used < (total / 100 * percent)
49
+ usage.reverse.map(&:first)
50
+ end
51
+
52
+ def run(file)
53
+ `bundle exec rake db:test:prepare && #{test_runner} #{file}`
54
+ $?.success?
55
+ end
56
+
57
+ def test_runner
58
+ if File.exist? ".zeus.sock"
59
+ "zeus testrb"
60
+ else
61
+ "bundle exec ruby"
62
+ end
63
+ end
64
+
65
+ def run_with(fixtures)
66
+ old = read(test_file)
67
+ write_fixtures(fixtures)
68
+ run test_file
69
+ ensure
70
+ write(test_file, old)
71
+ end
72
+
73
+ def write(file, content)
74
+ File.open(file, 'w'){|f| f.write content }
75
+ end
76
+
77
+ def write_fixtures(fixtures)
78
+ code = (fixtures.empty? ? "" : "fixtures #{fixtures.join(', ')}")
79
+ write(test_file, File.read(test_file).sub(FIXTURE_REX, "\\1#{code}"))
80
+ end
81
+
82
+ def read(file)
83
+ File.read(file)
84
+ end
85
+
86
+ def fixtures_in_file
87
+ found = fixture_params(test_file)
88
+ found == [":all"] ? available_fixtures : found
89
+ end
90
+
91
+ def fixture_params(file)
92
+ content = File.read(file)
93
+ return unless match = content.match(FIXTURE_REX)
94
+ match[2].split(/,\s+/)
95
+ end
96
+
97
+ def available_fixtures
98
+ folder = "#{@test_folder}/fixtures/"
99
+ extensions = ["yml", "csv"]
100
+ Dir["#{folder}*.{#{extensions.join(",")}}"].map{|f| f.sub(%r{#{folder}(.*)(\.#{extensions.join("|")})}, ":\\1") }
101
+ end
102
+
103
+ def report_and_keep_reduction(original_fixtures, fixtures)
104
+ original_fixtures = available_fixtures if original_fixtures == [":all"]
105
+ removed_fixtures = original_fixtures - fixtures
106
+
107
+ if removed_fixtures.empty?
108
+ puts "could not reduce fixtures"
109
+ else
110
+ puts "could reduce fixtures by #{removed_fixtures.size}"
111
+ write_fixtures(fixtures)
112
+ end
113
+ end
114
+
115
+ def reduced_via_common(percentages)
116
+ last_success = nil
117
+ percentages.each do |percent|
118
+ fixtures = common_fixtures(percent)
119
+ if run_with(fixtures)
120
+ puts "common #{percent}% run: SUCCESS"
121
+ last_success = fixtures
122
+ else
123
+ puts "common #{percent}% run: FAILED"
124
+ break
125
+ end
126
+ end
127
+ last_success || available_fixtures
128
+ end
129
+
130
+ def reduce_one_by_one(fixtures)
131
+ necessary_fixtures = fixtures
132
+ fixtures.each do |fixture|
133
+ current_try = necessary_fixtures - [fixture]
134
+
135
+ if read(test_file) =~ /(^|[^a-z\d_])#{fixture.sub(':','')}[\( ]:/
136
+ puts "#{fixture} is called directly"
137
+ elsif run_with(current_try)
138
+ puts "#{fixture} is not needed"
139
+ necessary_fixtures = current_try
140
+ else
141
+ puts "#{fixture} is needed"
142
+ end
143
+ end
144
+ necessary_fixtures
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe FixtureReducer do
4
+ it "has a VERSION" do
5
+ FixtureReducer::VERSION.should =~ /^[\.\da-z]+$/
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require "fixture_reducer"
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fixture_reducer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Grosser
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - !binary |-
13
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNakNDQWhxZ0F3SUJB
14
+ Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREEvTVJBd0RnWURWUVFEREFkdGFX
15
+ Tm8KWVdWc01SY3dGUVlLQ1pJbWlaUHlMR1FCR1JZSFozSnZjM05sY2pFU01C
16
+ QUdDZ21TSm9tVDhpeGtBUmtXQW1sMApNQjRYRFRFek1ESXdNekU0TVRNeE1W
17
+ b1hEVEUwTURJd016RTRNVE14TVZvd1B6RVFNQTRHQTFVRUF3d0hiV2xqCmFH
18
+ RmxiREVYTUJVR0NnbVNKb21UOGl4a0FSa1dCMmR5YjNOelpYSXhFakFRQmdv
19
+ SmtpYUprL0lzWkFFWkZnSnAKZERDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFB
20
+ RGdnRVBBRENDQVFvQ2dnRUJBTW9yWG8vaGdiVXE5NytrSUk5SApNc1FjTGRD
21
+ Lzd3UTFaUDJPc2hWSFBrZVAwcUg4TUJIR2c2ZVlpc09YMnViTmFnRjlZVENa
22
+ V25ocmRLcndwTE9PCmNQTGFaYmpVamxqSjNjUVIzQjhZbjF2ZVY1SWhHODZR
23
+ c2VUQmp5bXpKV3NMcHFKMVVaR3BmQjl0WGNzRnR1eE8KNnZIdmNJSGR6dmMv
24
+ T1VrSUN0dExiSCsxcWI2cnNIVWNlcWgrSnJINEdyc0o1SDRoQWZJZHlTMlhN
25
+ SzdZUktiaApoK0lCdTZkRldKSkJ5ekZzWW1WMVBEWGxuM1VCbWdBdDY1Y21D
26
+ dTRxUGZUaGlvQ0dEemJTSnJHREdMbXcvcEZYCkZQcFZDbTF6Z1lTYjF2NlFu
27
+ ZjNjZ1hhMmYyd1lHbTE3K3pBVnlJRHB3cnlGcnU5eUYvakp4RTM4ei9EUnNk
28
+ OVIKLzg4Q0F3RUFBYU01TURjd0NRWURWUjBUQkFJd0FEQWRCZ05WSFE0RUZn
29
+ UVVzaU5uWEh0S2VNWVljcjR5SlZtUQpXT05MK0l3d0N3WURWUjBQQkFRREFn
30
+ U3dNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUFseU43a0tvL05RQ1EwCkFP
31
+ elpMWjNXQWVQdlN0a0NGSUo1M3RzdjVLeW80cE1BbGx2K0JnUHp6QnQ3cWk2
32
+ MDVtRlNMNnpCZDl1TG91K1cKQ28zczQ4cDFkeTdDampBZlZRZG1WTkhGM013
33
+ WHRmQzJPRXl2U1FQaTR4S1I4aWJhOHdhM3hwOUxWbzFQdUxwdwovNkRzckNo
34
+ V3c3NEhmc0pONnFKT0s2ODRoSmVUOGxCWUFVZmlDM3dEMG93b1BTZytYdHlB
35
+ QWRkaXNSK0tWNVkxCk5tVkh1THRRY05UWnkrZ1JodDNhaEpSTXVDNlF5TG1r
36
+ VHNmKzZNYWVud0FNa0FnSGRzd0dzSnp0T25ObkJhM0YKeTBrQ1NXbUs2RCt4
37
+ L1NiZlM2cjdLZTA3TVJxemlKZEI5R3VFMSswY0lSdUZoOEVRK0xONkhYQ0tN
38
+ NXBvbi9HVQp5Y3dNWGZsMAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
+ date: 2013-03-10 00:00:00.000000000 Z
40
+ dependencies: []
41
+ description:
42
+ email: michael@grosser.it
43
+ executables:
44
+ - fixture-reducer
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Gemfile
49
+ - Rakefile
50
+ - Readme.md
51
+ - bin/fixture-reducer
52
+ - fixture_reducer.gemspec
53
+ - gem-public_cert.pem
54
+ - lib/fixture_reducer.rb
55
+ - lib/fixture_reducer/version.rb
56
+ - spec/fixture_reducer_spec.rb
57
+ - spec/spec_helper.rb
58
+ homepage: http://github.com/grosser/fixture_reducer
59
+ licenses:
60
+ - MIT
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ segments:
72
+ - 0
73
+ hash: -542410227692063686
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ segments:
81
+ - 0
82
+ hash: -542410227692063686
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.25
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Test speedup by replacing fixtures :all with only the necessary
89
+ test_files: []
metadata.gz.sig ADDED
Binary file