ttnt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c69fb42081da978ceceab090449ce8267f72783e
4
+ data.tar.gz: eadd988f0e19af23b3b93323741fac8305f045f2
5
+ SHA512:
6
+ metadata.gz: 8e5c3b484d7f8f337e8354e80841851c3cbb494dc24b5dc24d0cd0efa84054eea3e6490e11a895ade25a14de54ea0f428572a705d8513857d8ce5da5fd2869f1
7
+ data.tar.gz: 5dc1013d1aa5fb54b09a28b786a9ba6deabdad2b16418034988c04db79bf0372982a8e0343211831bce3039abcbbeb0fc0f4e4bccec6116661c226c0acecd693
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ before_install: gem install bundler -v 1.10.2
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ttnt.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Genki Sugimoto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,112 @@
1
+ # TTNT: Test This, Not That!
2
+
3
+ Developing under [Google Summer of Code 2015](http://www.google-melange.com/gsoc/homepage/google/gsoc2015) with mentoring organization [Ruby on Rails](http://rubyonrails.org/).
4
+
5
+ Full proposal of this project is [here](https://github.com/Genki-S/gsoc2015/blob/master/proposal.md) (might be obsolete in some ways, read this README about this project itself rather than the proposal).
6
+
7
+ ## Goal of this project
8
+
9
+ [rails/rails](https://github.com/rails/rails) has a problem that CI builds take hours to finish. This project aims to solve that problem by making it possible to run only tests related to changes introduced in target commits/branches/PRs.
10
+
11
+ ### Approach
12
+
13
+ The idea is based on [Aaron Patterson](https://twitter.com/tenderlove)'s article ["Predicting Test Failures"](http://tenderlovemaking.com/2015/02/13/predicting-test-failues.html). This program uses differences in code between base commit (say, the latest commit of master branch) and target commit (say, HEAD of your feature branch) to calculate which test cases are affected by that change.
14
+
15
+ ## Terminology
16
+
17
+ - test-to-code mapping
18
+ - mapping which maps test (file name) to code (file name and line number) executed on that test run for a given commit
19
+ - this will be used to determine tests that are affected by changes in code
20
+ - base commit
21
+ - the commit to which the tests you should run will be calculated (e.g. the latest commit of master branch)
22
+ - this commit should have test-to-code mapping
23
+ - target commit
24
+ - the commit on which you want to select tests you should run (e.g. HEAD of your feature branch)
25
+ - this commit does not have to have test-to-code mapping
26
+
27
+ ## Current Status
28
+
29
+ This project is still in an early stage and we are experimenting the best approach to solve the problem.
30
+
31
+ Currently, this program does:
32
+
33
+ - Generate test-to-code mapping for a given commit
34
+ - Given base commit and target commit, output test files you should run
35
+
36
+ Limitations:
37
+
38
+ - Test selection algorithm is not perfect yet (it may produce false-positives and false-negatives)
39
+ - Only supports git
40
+ - Only supports MiniTest
41
+ - Only select test files, not fine-grained test cases
42
+ - And a lot more!
43
+
44
+ ## Roadmap
45
+
46
+ Roadmap is under construction.
47
+
48
+ ## Installation
49
+
50
+ Add this line to your application's Gemfile:
51
+
52
+ ```ruby
53
+ gem 'ttnt'
54
+ ```
55
+
56
+ And then execute:
57
+
58
+ $ bundle
59
+
60
+ Or install it yourself as:
61
+
62
+ $ gem install ttnt
63
+
64
+ ## Requirements
65
+
66
+ Developed and only tested under ruby version 2.2.1.
67
+
68
+ ## Usage
69
+
70
+ ### Produce test-to-code mapping for a given commit
71
+
72
+ This pre-computation is required to select tests later.
73
+
74
+ Basically, you can substitute `ruby` command with `ttnt-anchor` command.
75
+ For example, if you want to produce test-to-code mapping for `test/mail_layout_test.rb` in `ActionMailer` of rails/rails:
76
+
77
+ ```
78
+ $ cd /your/local/rails/rails
79
+ $ git checkout BASE_COMMIT
80
+ $ cd actionmailer
81
+ $ ttnt-anchor -w -Itest test/mail_layout_test.rb -n test_explicit_class_layout
82
+ ```
83
+
84
+ (this example is taken from ["Contributing to Ruby on Rails — Ruby on Rails Guides"](http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#running-tests)).
85
+
86
+ This will produce test-to-code mapping for the test file `test/mail_layout_test.rb` under `.ttnt/BASE_COMMIT_SHA/test_to_code_mapping/TEST_FILE_NAME.json` which resides in your project base directory (the same repository in which `.git` directory resides).
87
+
88
+ ### Select tests
89
+
90
+ ```
91
+ $ git checkout TARGET_COMMIT
92
+ $ ttnt BASE_COMMIT
93
+ ```
94
+
95
+ This will assume test-to-code mapping is properly produced for the BASE\_COMMIT.
96
+
97
+ ## Development
98
+
99
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
100
+
101
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
102
+
103
+ ## Contributing
104
+
105
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Genki-S/ttnt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
106
+
107
+ Please don't hesitate to [open a issue](https://github.com/Genki-S/ttnt/issues/new) to share your ideas for me! Any comment will be valuable especially in this early development stage.
108
+
109
+ ## License
110
+
111
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
112
+
@@ -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/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ttnt"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
12
+
13
+ # require "irb"
14
+ # IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rugged'
4
+ require_relative '../lib/ttnt/test_selector'
5
+
6
+ USAGE = %{
7
+ ttnt (Test This, Not That)
8
+
9
+ Usage:
10
+ ttnt BASE_SHA
11
+
12
+ What it does:
13
+ Output test files you should run based on changes between commits BASE_SHA and HEAD.
14
+ }
15
+
16
+ if ARGV.count != 1
17
+ puts USAGE
18
+ exit 1
19
+ end
20
+
21
+ repo = Rugged::Repository.discover('.')
22
+ ts = TTNT::TestSelector.new(repo.head.target_id, ARGV[0])
23
+ tests = ts.select_tests
24
+ if tests.empty?
25
+ STDERR.puts 'No test selected.'
26
+ else
27
+ puts tests.to_a.join("\n")
28
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ gem_root = File.expand_path('../lib', File.dirname(File.expand_path(__FILE__)))
4
+ argv = ARGV
5
+ argv.unshift('ruby', '-I', gem_root, '-r', 'ttnt/anchor')
6
+
7
+ exec(*argv)
@@ -0,0 +1,5 @@
1
+ require "ttnt/version"
2
+
3
+ module TTNT
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'coverage'
2
+ require 'ttnt/test_to_code_mapping'
3
+ require 'rugged'
4
+
5
+ test_file = $0
6
+
7
+ Coverage.start
8
+
9
+ at_exit do
10
+ # Use current HEAD
11
+ sha = Rugged::Repository.discover('.').head.target_id
12
+ mapping = TTNT::TestToCodeMapping.new(sha)
13
+ mapping.append_from_coverage(test_file, Coverage.result)
14
+ end
@@ -0,0 +1,40 @@
1
+ require 'set'
2
+ require 'rugged'
3
+ require_relative './test_to_code_mapping'
4
+
5
+ module TTNT
6
+ class TestSelector
7
+ def initialize(target_sha, base_sha)
8
+ @repo = Rugged::Repository.discover('.')
9
+ @target_obj = @repo.lookup(target_sha)
10
+ @base_obj = @repo.lookup(base_sha)
11
+ end
12
+
13
+ def select_tests
14
+ tests = Set.new
15
+ mapping = TTNT::TestToCodeMapping.new(@base_obj.oid)
16
+ # TODO: if mapping is not found (ttnt-anchor has not been run)
17
+
18
+ diff = @base_obj.diff(@target_obj)
19
+ diff.each_patch do |patch|
20
+ file = patch.delta.old_file[:path]
21
+ patch.each_hunk do |hunk|
22
+ # TODO: think if this selection covers all possibilities
23
+ hunk.each_line do |line|
24
+ case line.line_origin
25
+ when :addition
26
+ # FIXME: new_lineno is suspicious
27
+ # (what if hunk1 adds 100 lines and hunk2 add 1 line?)
28
+ tests += mapping.get_tests(file: file, lineno: line.new_lineno)
29
+ when :deletion
30
+ tests += mapping.get_tests(file: file, lineno: line.old_lineno)
31
+ else
32
+ # do nothing
33
+ end
34
+ end
35
+ end
36
+ end
37
+ tests.delete(nil)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,95 @@
1
+ require 'rugged'
2
+ require 'json'
3
+
4
+ # Terminologies:
5
+ # spectra: { filename => [line, numbers, executed], ... }
6
+
7
+ module TTNT
8
+ class TestToCodeMapping
9
+ DIRECTORY_SEPARATOR_PLACEHOLDER = '=+='.freeze
10
+
11
+ def initialize(sha)
12
+ @sha = sha
13
+ @repo = Rugged::Repository.discover('.')
14
+ raise 'Not in a git repository' unless @repo
15
+ end
16
+
17
+ def append_from_coverage(test, coverage)
18
+ spectra = normalize_path(select_project_files(spectra_from_coverage(coverage)))
19
+ save_spectra(test: test, spectra: spectra)
20
+ end
21
+
22
+ def read_spectra(test:)
23
+ if File.exists?(spectra_file(test: test))
24
+ JSON.parse(File.read(spectra_file(test: test)))
25
+ else
26
+ {}
27
+ end
28
+ end
29
+
30
+ def get_tests(file:, lineno:)
31
+ tests = Set.new
32
+ all_tests.each do |test|
33
+ spectra = read_spectra(test: test)
34
+ lines = spectra[file]
35
+ next unless lines
36
+ n = lines.bsearch { |x| x >= lineno }
37
+ if n == lineno
38
+ tests << test
39
+ end
40
+ end
41
+ tests
42
+ end
43
+
44
+ private
45
+
46
+ def normalize_path(spectra)
47
+ spectra.map do |filename, lines|
48
+ [filename.sub(@repo.workdir, ''), lines]
49
+ end.to_h
50
+ end
51
+
52
+ def select_project_files(spectra)
53
+ spectra.select do |filename, lines|
54
+ filename.start_with?(@repo.workdir)
55
+ end
56
+ end
57
+
58
+ def spectra_from_coverage(cov)
59
+ spectra = Hash.new { |h, k| h[k] = [] }
60
+ cov.each do |filename, executions|
61
+ executions.each_with_index do |execution, i|
62
+ next if execution.nil? || execution == 0
63
+ spectra[filename] << i + 1
64
+ end
65
+ end
66
+ spectra
67
+ end
68
+
69
+ def save_spectra(test:, spectra:)
70
+ dir = base_savedir
71
+ unless File.directory?(dir)
72
+ FileUtils.mkdir_p(dir)
73
+ end
74
+ File.write(spectra_file(test: test), spectra.to_json)
75
+ end
76
+
77
+ def base_savedir
78
+ "#{@repo.workdir}/.ttnt/#{@sha}/test_to_code_mapping"
79
+ end
80
+
81
+ def spectra_file(test:)
82
+ filename = test.gsub('/', DIRECTORY_SEPARATOR_PLACEHOLDER)
83
+ "#{base_savedir}/#{filename}.json"
84
+ end
85
+
86
+ def all_tests
87
+ Dir["#{base_savedir}/*.json"].map do |filename|
88
+ filename
89
+ .sub(/.*\//, '')
90
+ .sub(/\.json\Z/, '')
91
+ .gsub(DIRECTORY_SEPARATOR_PLACEHOLDER, '/')
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,3 @@
1
+ module TTNT
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ttnt/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ttnt"
8
+ spec.version = TTNT::VERSION
9
+ spec.authors = ["Genki Sugimoto"]
10
+ spec.email = ["cfhoyuk.reccos.nelg@gmail.com"]
11
+
12
+ spec.summary = %q{Select test cases to run based on changes in committed code}
13
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
14
+ spec.homepage = "http://github.com/Genki-S/ttnt"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "rugged", "0.23.0b2"
31
+ spec.add_dependency "json", "1.8.3"
32
+
33
+ spec.add_development_dependency "bundler", "~> 1.10"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "minitest"
36
+
37
+ # Pry
38
+ spec.add_development_dependency "hirb"
39
+ spec.add_development_dependency "awesome_print"
40
+ spec.add_development_dependency "pry"
41
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ttnt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Genki Sugimoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-06-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rugged
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.23.0b2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.23.0b2
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: hirb
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: awesome_print
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - cfhoyuk.reccos.nelg@gmail.com
128
+ executables:
129
+ - ttnt
130
+ - ttnt-anchor
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".gitignore"
135
+ - ".travis.yml"
136
+ - CODE_OF_CONDUCT.md
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - bin/console
142
+ - bin/setup
143
+ - exe/ttnt
144
+ - exe/ttnt-anchor
145
+ - lib/ttnt.rb
146
+ - lib/ttnt/anchor.rb
147
+ - lib/ttnt/test_selector.rb
148
+ - lib/ttnt/test_to_code_mapping.rb
149
+ - lib/ttnt/version.rb
150
+ - ttnt.gemspec
151
+ homepage: http://github.com/Genki-S/ttnt
152
+ licenses:
153
+ - MIT
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.4.5
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Select test cases to run based on changes in committed code
175
+ test_files: []