parallel_tests-fine_grain_test 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.hound.yml +8 -0
  4. data/.rubocop.default.yml +1114 -0
  5. data/.rubocop.disabled.yml +125 -0
  6. data/.rubocop.enabled.yml +1352 -0
  7. data/.rubocop.yml +66 -0
  8. data/.ruby-version +1 -0
  9. data/.travis.yml +5 -0
  10. data/Appraisals +14 -0
  11. data/Gemfile +8 -0
  12. data/README.md +51 -0
  13. data/Rakefile +10 -0
  14. data/bin/parallel_fine_grain_test +9 -0
  15. data/exe/parallel_tests-fine_grain_test +3 -0
  16. data/gemfiles/activesupport_3.gemfile +11 -0
  17. data/gemfiles/activesupport_3.gemfile.lock +44 -0
  18. data/gemfiles/activesupport_4.gemfile +10 -0
  19. data/gemfiles/activesupport_4.gemfile.lock +48 -0
  20. data/gemfiles/activesupport_5.gemfile +10 -0
  21. data/gemfiles/activesupport_5.gemfile.lock +47 -0
  22. data/lib/parallel_tests/fine_grain_test.rb +8 -0
  23. data/lib/parallel_tests/fine_grain_test/file_queue.rb +80 -0
  24. data/lib/parallel_tests/fine_grain_test/minitest.rb +4 -0
  25. data/lib/parallel_tests/fine_grain_test/minitest/extension.rb +27 -0
  26. data/lib/parallel_tests/fine_grain_test/minitest/suite.rb +35 -0
  27. data/lib/parallel_tests/fine_grain_test/railtie.rb +8 -0
  28. data/lib/parallel_tests/fine_grain_test/runner.rb +27 -0
  29. data/lib/parallel_tests/fine_grain_test/runtime_logger.rb +81 -0
  30. data/lib/parallel_tests/fine_grain_test/tasks.rb +21 -0
  31. data/lib/parallel_tests/fine_grain_test/test_case.rb +20 -0
  32. data/lib/parallel_tests/fine_grain_test/test_helper.rb +16 -0
  33. data/lib/parallel_tests/fine_grain_test/test_unit.rb +11 -0
  34. data/lib/parallel_tests/fine_grain_test/test_unit/collector.rb +54 -0
  35. data/lib/parallel_tests/fine_grain_test/test_unit/test_suite.rb +59 -0
  36. data/lib/parallel_tests/fine_grain_test/version.rb +5 -0
  37. data/parallel_tests-fine_grain_test.gemspec +23 -0
  38. metadata +122 -0
data/.rubocop.yml ADDED
@@ -0,0 +1,66 @@
1
+ inherit_from:
2
+ - .rubocop.enabled.yml
3
+ - .rubocop.disabled.yml
4
+ - .rubocop.default.yml
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.2
8
+
9
+ # Set max line length to 100
10
+ Metrics/LineLength:
11
+ Max: 100
12
+ Enabled: true
13
+
14
+ # Set max method length to 100
15
+ Metrics/MethodLength:
16
+ Max: 100
17
+
18
+ # Renaming `has_something?` to `something?` obfuscates whether it is a 'is-a'
19
+ # or a 'has-a' relationship.
20
+ Style/PredicateName:
21
+ Enabled: false
22
+
23
+ # ClassLength, ugh
24
+ Metrics/ClassLength:
25
+ Enabled: false
26
+
27
+ # Because only Paulus cares about documentation
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ # This cop is too aggresive in claiming a guard clause should be used
32
+ Style/GuardClause:
33
+ Enabled: false
34
+
35
+ # rescue in modifier form is very idiomatic and useful in certain situations!
36
+ Style/RescueModifier:
37
+ Enabled: false
38
+
39
+ # Otherwise you get a warning if you do ['Paulus', 'Productive', 'Very']
40
+ Style/WordArray:
41
+ Enabled: false
42
+
43
+ # This cop does not fare well with our increased method length. See http://c2.com/cgi/wiki?AbcMetric
44
+ Metrics/AbcSize:
45
+ Enabled: false
46
+
47
+ Metrics/CyclomaticComplexity:
48
+ Enabled: false
49
+
50
+ Metrics/PerceivedComplexity:
51
+ Enabled: false
52
+
53
+ # Avoid chaining a method call on a do...end block.
54
+ Style/MethodCalledOnDoEndBlock:
55
+ Enabled: true
56
+
57
+ # Prefer keyword arguments over option hashes
58
+ Style/OptionHash:
59
+ Enabled: true
60
+
61
+ Style/TrailingCommaInLiteral:
62
+ # If `comma`, the cop requires a comma after the last item in an array or
63
+ # hash, but only when each item is on its own line.
64
+ # If `consistent_comma`, the cop requires a comma after the last item of all
65
+ # non-empty array and hash literals.
66
+ EnforcedStyleForMultiline: comma
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.4
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.4
4
+ before_install: gem install bundler -v 1.11.2
5
+
data/Appraisals ADDED
@@ -0,0 +1,14 @@
1
+ appraise 'activesupport_3' do
2
+ gem 'test-unit', '2.5.5', require: false
3
+ gem 'activesupport', '3.2.22'
4
+ end
5
+
6
+ appraise 'activesupport_4' do
7
+ gem 'minitest', require: false
8
+ gem 'activesupport', '4.2.6'
9
+ end
10
+
11
+ appraise 'activesupport_5' do
12
+ gem 'minitest', require: false
13
+ gem 'activesupport', '5.0.0.rc1'
14
+ end
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in parallel_tests-fine_grain_test.gemspec
4
+ gemspec
5
+
6
+ gem 'minitest', require: false
7
+ gem 'mocha', require: false
8
+ gem 'appraisal'
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # ParallelTests::FineGrainTest
2
+
3
+ Normally the `parallel_tests` divvies up the test files between parallel test processes at the
4
+ beginning. This causes uneven runtimes as some test processes end up with faster test files while others end up with slower test files. Utilizing past execution times when divving up the tests helps, however, due to differences in test agents and varied execution times (i'm looking at you selenium) it still results in uneven runtimes.
5
+
6
+ This gem extends the `parallel_tests` gem to enable parallel test processes to pull tests from a global queue until there are no more tests. This results in all parallel test processes being
7
+ utilized much more optimally which leads to faster tests.
8
+
9
+ Tested with,
10
+ test-unit / activesupport 3.x
11
+ minitest / activesupport 4.x
12
+ minitest / activesupport 5.x
13
+
14
+ ## Installation
15
+
16
+ Add this lines to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'parallel_tests'
20
+ gem 'parallel_tests-fine_grain_test'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install parallel_tests-fine_grain_test
30
+
31
+ ## Usage
32
+
33
+ The usage is much like `parallel:test` task.
34
+
35
+ Example,
36
+ ```
37
+ %> rake parallel:fine_grain_test[^test/selenium]
38
+ ```
39
+
40
+ The FINE_GRAIN_TEST_RUNTIME_LOGGER can be optionally set to the location of the file where the test times should be read from / written to. Although optional, it is highly recommended to set FINE_GRAIN_TEST_RUNTIME_LOGGER as it helps the tests complete faster.
41
+
42
+ ## Development
43
+
44
+ After checking out the repo, run `bundle` to install dependencies. Then, run `rake test` to run the tests.
45
+
46
+ Note, this gem uses Minitest framework for its own tests but uses the Appraisal gem to test against potentially different version of test-unit and minitest. See the integration tests.
47
+
48
+ ## Contributing
49
+
50
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/parallel_tests-fine_grain_test.
51
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/parallel_tests/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # enable local usage from cloned repo
4
+ root = File.expand_path("../..", __FILE__)
5
+ $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
6
+
7
+ require "parallel_tests"
8
+
9
+ ParallelTests::CLI.new.run(["--type", "fine_grain_test"] + ARGV)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "parallel_tests/fine_grain_test"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "minitest", :require => false
6
+ gem "mocha", :require => false
7
+ gem "appraisal"
8
+ gem "test-unit", "2.5.5", :require => false
9
+ gem "activesupport", "3.2.22"
10
+
11
+ gemspec :path => "../"
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ parallel_tests-fine_grain_test (0.1.0)
5
+ parallel_tests (~> 2.4)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (3.2.22)
11
+ i18n (~> 0.6, >= 0.6.4)
12
+ multi_json (~> 1.0)
13
+ appraisal (2.1.0)
14
+ bundler
15
+ rake
16
+ thor (>= 0.14.0)
17
+ i18n (0.7.0)
18
+ metaclass (0.0.4)
19
+ minitest (5.9.0)
20
+ mocha (1.1.0)
21
+ metaclass (~> 0.0.1)
22
+ multi_json (1.12.0)
23
+ parallel (1.9.0)
24
+ parallel_tests (2.5.0)
25
+ parallel
26
+ rake (10.5.0)
27
+ test-unit (2.5.5)
28
+ thor (0.19.1)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ activesupport (= 3.2.22)
35
+ appraisal
36
+ bundler (~> 1.11)
37
+ minitest
38
+ mocha
39
+ parallel_tests-fine_grain_test!
40
+ rake (~> 10.0)
41
+ test-unit (= 2.5.5)
42
+
43
+ BUNDLED WITH
44
+ 1.12.3
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "minitest", :require => false
6
+ gem "mocha", :require => false
7
+ gem "appraisal"
8
+ gem "activesupport", "4.2.6"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ parallel_tests-fine_grain_test (0.1.0)
5
+ parallel_tests (~> 2.4)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.2.6)
11
+ i18n (~> 0.7)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.3, >= 0.3.4)
15
+ tzinfo (~> 1.1)
16
+ appraisal (2.1.0)
17
+ bundler
18
+ rake
19
+ thor (>= 0.14.0)
20
+ i18n (0.7.0)
21
+ json (1.8.3)
22
+ metaclass (0.0.4)
23
+ minitest (5.9.0)
24
+ mocha (1.1.0)
25
+ metaclass (~> 0.0.1)
26
+ parallel (1.9.0)
27
+ parallel_tests (2.5.0)
28
+ parallel
29
+ rake (10.5.0)
30
+ thor (0.19.1)
31
+ thread_safe (0.3.5)
32
+ tzinfo (1.2.2)
33
+ thread_safe (~> 0.1)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ activesupport (= 4.2.6)
40
+ appraisal
41
+ bundler (~> 1.11)
42
+ minitest
43
+ mocha
44
+ parallel_tests-fine_grain_test!
45
+ rake (~> 10.0)
46
+
47
+ BUNDLED WITH
48
+ 1.12.3
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "minitest", :require => false
6
+ gem "mocha", :require => false
7
+ gem "appraisal"
8
+ gem "activesupport", "5.0.0.rc1"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ parallel_tests-fine_grain_test (0.1.0)
5
+ parallel_tests (~> 2.4)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (5.0.0.rc1)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (~> 0.7)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ appraisal (2.1.0)
16
+ bundler
17
+ rake
18
+ thor (>= 0.14.0)
19
+ concurrent-ruby (1.0.2)
20
+ i18n (0.7.0)
21
+ metaclass (0.0.4)
22
+ minitest (5.9.0)
23
+ mocha (1.1.0)
24
+ metaclass (~> 0.0.1)
25
+ parallel (1.9.0)
26
+ parallel_tests (2.5.0)
27
+ parallel
28
+ rake (10.5.0)
29
+ thor (0.19.1)
30
+ thread_safe (0.3.5)
31
+ tzinfo (1.2.2)
32
+ thread_safe (~> 0.1)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ activesupport (= 5.0.0.rc1)
39
+ appraisal
40
+ bundler (~> 1.11)
41
+ minitest
42
+ mocha
43
+ parallel_tests-fine_grain_test!
44
+ rake (~> 10.0)
45
+
46
+ BUNDLED WITH
47
+ 1.12.3
@@ -0,0 +1,8 @@
1
+ require 'parallel_tests'
2
+ require "parallel_tests/fine_grain_test/version"
3
+ require "parallel_tests/fine_grain_test/railtie" if defined? Rails::Railtie
4
+
5
+ module ParallelTests
6
+ module FineGrainTest
7
+ end
8
+ end
@@ -0,0 +1,80 @@
1
+ require 'parallel_tests/fine_grain_test/test_case'
2
+
3
+ module ParallelTests
4
+ module FineGrainTest
5
+ class FileQueue
6
+ FILE_NAME = '.test.queue'.freeze
7
+ MARKER = '--POPULATE--'.freeze
8
+
9
+ def initialize(file_name = FILE_NAME)
10
+ @file_name = file_name
11
+ end
12
+
13
+ def reset
14
+ lock do |file|
15
+ rewrite(file, [ MARKER ])
16
+ end
17
+ end
18
+
19
+ def enq_all(test_cases)
20
+ lock do |file|
21
+ return if already_populated?(file)
22
+
23
+ test_cases = yield(test_cases) if block_given?
24
+
25
+ lines = test_cases.map { |test_case| TestCase.encode(test_case) }
26
+ rewrite(file, lines)
27
+ end
28
+ end
29
+
30
+ def deq
31
+ lock do |file|
32
+ lines = file.read.split(/\n/)
33
+ return nil if lines.empty? || lines[0].chomp == MARKER
34
+ rewrite(file, lines[1..-1])
35
+
36
+ return TestCase.decode(lines[0].chomp)
37
+ end
38
+ end
39
+
40
+ def size
41
+ lock do |file|
42
+ lines = file.read.split(/\n/)
43
+ if lines.empty? || lines[0].chomp == MARKER
44
+ return 0
45
+ else
46
+ return lines.size
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def rewrite(file, lines)
54
+ file.pos = 0
55
+ file.truncate(0)
56
+ lines.each do |line|
57
+ file.puts(line)
58
+ end
59
+ end
60
+
61
+ def already_populated?(file)
62
+ lines = file.read.split(/\n/)
63
+ return true if lines.empty?
64
+
65
+ lines[0].chomp != MARKER
66
+ end
67
+
68
+ def lock
69
+ File.open(@file_name, File::RDWR|File::CREAT) do |f|
70
+ begin
71
+ f.flock File::LOCK_EX
72
+ yield(f)
73
+ ensure
74
+ f.flock File::LOCK_UN
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end