what_to_run 0.1.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NWI3ZjRiMTMzYmQ5YzA0NmM4NjJkNTViM2VkOTJkZTI2NDQxNmE4MQ==
5
- data.tar.gz: !binary |-
6
- MmE2Yzc1YWVhMjA3NDliZjk4YTQ5NzdlNjljNTg4NzZjMjBjODM1Mg==
2
+ SHA1:
3
+ metadata.gz: 5628bef322e5ffe04df75062217228f1c462251a
4
+ data.tar.gz: a3a0beabaabfb83223a0b588acb713a0e56a682f
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZmY3Yzk3ZmY1ZmMwMTMzNTc3ZWYyYzRjNjU5NjVhODY0NmNkODI2MTM4YzJi
10
- NGNjYTRhNTg5MjRkMTdhY2NhNWNhYjBhZDE4M2VjYjEwOTI1MTJhNWFiNWRh
11
- NDAxNjFiMjc1NDUyYTI0YTllYzBlNTk0NmQ2MWQ2MWYyM2NiMmQ=
12
- data.tar.gz: !binary |-
13
- ZGZmMzBiYjZkZmUzMzcxNDZhZWU5MjgxZTAwMDQwMjAwOGY0MTQwZTliMDdm
14
- MmNjNjczNTdlN2YzNjg5YWUyZWFlYzkwZTlhMTIwMWY0YWQ1MDk1MjRhNjY0
15
- MmIxYzM3M2NjYWYxYTM3OTM4ZTgzOTNhOGRlOWRkY2JhYjQzNjI=
6
+ metadata.gz: bbb66e545238e59c45d64b927b518a9b1b25bfb6cd7e24c17125ac5e00b32f3ead0bbf2346052cbeb7f5be69b10687e2106153303c5377ad7f73924d3a6a38f8
7
+ data.tar.gz: ff854a098d8f76780a4c7977cdb17ad57d3adfc1a1a1253910e4fca1a3bd2b71b3a2c3864c8145ef4a384830370900cda21ebb8e63b29ff006cc4aace266e702
data/README.md CHANGED
@@ -1,14 +1,30 @@
1
1
  # What To Run
2
2
 
3
+ [![Join the chat at https://gitter.im/DyegoCosta/what_to_run](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/DyegoCosta/what_to_run?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
3
5
  [![Build Status](https://travis-ci.org/DyegoCosta/what_to_run.svg?branch=master)](https://travis-ci.org/DyegoCosta/what_to_run)
4
6
 
5
- What To Run is a lib for regression test selection, use it to predict which tests you should run when you make any modification on your codebase.
7
+ What To Run is a lib for regression test selection for Ruby projects, use it to predict which tests you should run when you make any modification on your codebase.
8
+
9
+ This lib was inspired by [@tenderlove](https://github.com/tenderlove) [blog post](tenderlove-post). Make sure to check it out.
10
+
6
11
 
7
- This lib is based on [@tenderlove](https://github.com/tenderlove) idea and guidance, make sure to read his [blog post](http://tenderlovemaking.com/2015/02/13/predicting-test-failues.html) on the subject.
12
+ From the _[An Empirical Study of Regression Test Selection Techniques](rts-article)_ article:
13
+
14
+ > Regression testing is the process of validating modified software to detect whether new errors
15
+ have been introduced into previously tested code and to provide confidence that modifications
16
+ are correct. Since regression testing is an expensive process, researchers have proposed
17
+ regression test selection techniques as a way to reduce some of this expense. These techniques
18
+ attempt to reduce costs by selecting and running only a subset of the test cases in a program’s
19
+ existing test suite.
20
+
21
+ [rts-article]: https://www.cs.umd.edu/~aporter/Docs/p184-graves.pdf
22
+ [tenderlove-post]: http://tenderlovemaking.com/2015/02/13/predicting-test-failues.html
8
23
 
9
24
  ## Requirements
10
25
 
11
26
  - Project must be inside a Git repository
27
+ - CMake to build the gem
12
28
 
13
29
  ## Installation
14
30
 
@@ -27,12 +43,12 @@ $ bundle
27
43
  Or install it yourself as:
28
44
 
29
45
  ```
30
- gem install what_to_run
46
+ $ gem install what_to_run
31
47
  ```
32
48
 
33
49
  ## Usage
34
50
 
35
- Require the lib with:
51
+ Require it after requiring your test framework and before load your files to be tested and your test suite config:
36
52
 
37
53
  Minitest
38
54
 
@@ -46,29 +62,41 @@ RSpec
46
62
  require 'what_to_run/rspec'
47
63
  ```
48
64
 
49
- Run your tests on a clean git branch
65
+ Run your full tests suite with COLLECT=1 on a **clean git branch**
50
66
 
51
67
  Minitest
52
68
 
53
69
  ```
54
- $ COLLECTION=1 bundle exec rake test
70
+ $ COLLECT=1 bundle exec rake test
55
71
  ```
56
72
 
57
73
  RSpec
58
74
 
59
75
  ```
60
- $ COLLECTION=1 bundle exec rspec
76
+ $ COLLECT=1 bundle exec rspec
61
77
  ```
62
78
 
63
79
  This will create the initial coverage information. Then make your desired modifications on your code.
64
80
 
65
- Now to predict which tests is likely fail, run this:
81
+ Now to run the tests that could reveal faults do the following
82
+
83
+ ```
84
+ $ what_to_run <framework> [options]
85
+ ```
86
+
87
+ Supported frameworks are:
66
88
 
67
89
  ```
68
- $ what_to_run
90
+ rspec
91
+ minitest
69
92
  ```
70
93
 
71
- :warning: A `run_log.json` file will be created in the current directory, you might want to include it in your `.gitignore`.
94
+ Options are:
95
+
96
+ ```
97
+ -e, --exec EXECUTABLE Alternate test runner executable
98
+ -h, --help Prints this help
99
+ ```
72
100
 
73
101
  ## Contributing
74
102
 
@@ -2,4 +2,5 @@
2
2
 
3
3
  require 'what_to_run'
4
4
 
5
- puts WhatToRun.predict
5
+ WhatToRun::CLI.new.run ARGV
6
+
@@ -1,91 +1,63 @@
1
- require 'json'
2
- require 'rugged'
3
1
  require 'set'
2
+ require 'rugged'
3
+
4
+ require_relative 'what_to_run/tracker'
4
5
 
5
6
  module WhatToRun
6
- extend self
7
+ autoload :CLI, 'what_to_run/cli'
8
+ autoload :VERSION, 'what_to_run/version'
7
9
 
8
- def predict
9
- lines_to_run.inject([]) do |tests, (file, line)|
10
- path = File.expand_path(file)
11
- tests += Array cov_map[path][line]
10
+ class << self
11
+ def predict
12
+ lines_to_run.inject(Set.new) do |tests, (file, line)|
13
+ tests += Array cov_map[file][line]
14
+ end
12
15
  end
13
- end
14
-
15
- def lines_to_run
16
- repo = Rugged::Repository.new('.')
17
- lines_to_run = Set.new
18
16
 
19
- repo.index.diff.each_patch do |patch|
20
- file = patch.delta.old_file[:path]
21
-
22
- patch.each_hunk do |hunk|
23
- hunk.each_line do |line|
24
- case line.line_origin
25
- when :addition
26
- lines_to_run << [file, line.new_lineno]
27
- when :deletion
28
- lines_to_run << [file, line.old_lineno]
29
- when :context
30
- # do nothing
17
+ def lines_to_run
18
+ repository = Rugged::Repository.discover('.')
19
+ repository_root = File.expand_path("..", repository.path)
20
+ lines_to_run = Set.new
21
+
22
+ repository.index.diff.each_patch do |patch|
23
+ file = patch.delta.old_file[:path]
24
+ file_path = File.join(repository_root, file)
25
+
26
+ patch.each_hunk do |hunk|
27
+ hunk.each_line do |line|
28
+ case line.line_origin
29
+ when :addition
30
+ lines_to_run << [file_path, line.new_lineno]
31
+ when :deletion
32
+ lines_to_run << [file_path, line.old_lineno]
33
+ when :context
34
+ # do nothing
35
+ end
31
36
  end
32
37
  end
33
38
  end
34
- end
35
-
36
- lines_to_run
37
- end
38
-
39
- def cov_delta(before, after)
40
- after.each_with_object({}) do |(file_name, lines_cov), delta|
41
- before_lines_cov = before[file_name]
42
-
43
- # skip arrays that are exactly the same
44
- next if before_lines_cov == lines_cov
45
39
 
46
- # subtract the old coverage from the new coverage
47
- cov = lines_cov_delta(before_lines_cov, lines_cov)
48
-
49
- # add the "diffed" coverage to the hash
50
- delta[file_name] = cov
40
+ lines_to_run
51
41
  end
52
- end
53
-
54
- def cov_map
55
- cov_map = Hash.new { |h, file| h[file] = Hash.new { |i, line| i[line] = [] } }
56
42
 
57
- File.open('run_log.json') do |f|
58
- JSON.parse(f.read).each do |cov_info|
59
- before, after = cov_info.last(2)
60
- desc = build_test_desc(cov_info)
43
+ def cov_map
44
+ schema = Hash.new { |h, file| h[file] = Hash.new { |i, line| i[line] = [] } }
61
45
 
62
- delta = cov_delta(before, after)
63
-
64
- delta.each_pair do |file, lines|
46
+ @cov_map ||= Tracker.read.inject(schema) do |cov_map, (desc, cov_delta)|
47
+ cov_delta.each_pair do |file, lines|
65
48
  file_map = cov_map[file]
66
49
 
67
- lines.each_with_index do |val, i|
68
- file_map[i + 1] << desc if line_executed?(val)
50
+ lines.each_with_index do |line, i|
51
+ file_map[i + 1] << desc if line_executed?(line)
69
52
  end
70
53
  end
54
+
55
+ cov_map
71
56
  end
72
57
  end
73
58
 
74
- cov_map
75
- end
76
-
77
- def build_test_desc(cov_info)
78
- using_minitest = cov_info.length == 4
79
- using_minitest ? cov_info.first(2).join('#') : cov_info.first
80
- end
81
-
82
- def line_executed?(line)
83
- line.to_i > 0
84
- end
85
-
86
- def lines_cov_delta(before_lines_cov, after_lines_cov)
87
- after_lines_cov.zip(before_lines_cov).map do |lines_after, lines_before|
88
- lines_after ? lines_after - lines_before : lines_after
59
+ def line_executed?(line)
60
+ line.to_i > 0
89
61
  end
90
62
  end
91
63
  end
@@ -0,0 +1,52 @@
1
+ require 'optparse'
2
+ require 'shellwords'
3
+
4
+ module WhatToRun
5
+ class CLI
6
+ def run(argv)
7
+ framework = Array(argv)[0]
8
+
9
+ abort 'Must specify a test framework' unless framework
10
+
11
+ options = parse_options!(argv)
12
+
13
+ begin
14
+ runner = load_runner framework.downcase
15
+ runner.new(options).run
16
+ rescue LoadError
17
+ abort "Unsupported test framework: #{framework}"
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def parse_options!(argv)
24
+ options = {}
25
+
26
+ parser = OptionParser.new do |opts|
27
+ opts.banner = 'Usage: what_to_run <framework> [options]'
28
+
29
+ opts.on('-e', '--exec EXECUTABLE', 'Alternate test runner executable') do |e|
30
+ options[:exec] = e
31
+ end
32
+
33
+ opts.on('-h', '--help', 'Prints this help') do
34
+ puts opts
35
+ exit
36
+ end
37
+ end
38
+
39
+ parser.parse!(argv)
40
+
41
+ options
42
+ end
43
+
44
+ def load_runner(framework)
45
+ require "what_to_run/#{framework}/runner"
46
+ klass_name = "WhatToRun::#{RUNNERS[framework]}::Runner"
47
+ klass_name.split('::').inject(Object) {|x, y| x.const_get(y.to_sym)}
48
+ end
49
+
50
+ RUNNERS = {'rspec' => 'RSpec', 'minitest' => 'Minitest'}
51
+ end
52
+ end
@@ -0,0 +1,77 @@
1
+ module WhatToRun
2
+ class Differ
3
+ class << self
4
+ ##
5
+ # Gives the delta beteween the coverage result
6
+ # before and after a test run and before starting
7
+ # the test suite
8
+ #
9
+ # Results in the lines that may trigger the test
10
+ # that gave the after result
11
+ def coverage_delta(cov_before, cov_after, cov_before_suite)
12
+ cov_after.each_with_object({}) do |(file_name, lines_cov_after), delta|
13
+ lines_cov_before = cov_before[file_name]
14
+ lines_cov_before_suite = cov_before_suite[file_name]
15
+
16
+ next unless file_covered?(lines_cov_before, lines_cov_after)
17
+
18
+ lines_delta = lines_cov_delta \
19
+ lines_cov_before_suite, lines_cov_before, lines_cov_after
20
+
21
+ delta[file_name] = lines_delta
22
+ end
23
+ end
24
+
25
+ ##
26
+ # It needs to diff the diff of before and after
27
+ # with the coverage before the test suite in order
28
+ # to include the uncovered lines to all tests that
29
+ # touch this file
30
+ def lines_cov_delta(before_suite, before, after)
31
+ delta = diff before_suite, diff(before, after)
32
+ delta.map(&method(:normalize_cov_result))
33
+ end
34
+
35
+ def diff(before, after)
36
+ after = Array(after)
37
+ before = Array(before)
38
+
39
+ after.zip(before).map do |lines_after, lines_before|
40
+ lines_after ? lines_after - lines_before.to_i : lines_after
41
+ end
42
+ end
43
+
44
+ ##
45
+ # The possible param value that this method might receive
46
+ # are the following
47
+ #
48
+ # @param result positive => should run the test
49
+ # @param result negative => should run the test
50
+ # @param result nil => should run the test
51
+ # @param result zero => should not run the test
52
+ #
53
+ # This method will convert negative and nil values to 1,
54
+ # which will make them represent lines that should be run.
55
+ # The positive lines can be kept as they are since this mean
56
+ # they will be run.
57
+ #
58
+ # The only exception case is the 0 result which will be kept
59
+ # as it is so we don't run lines within the not called methods
60
+ #
61
+ # This introduces false positives to avoid missing tests that
62
+ # depends on lines that are evaluated when the file is required
63
+ #
64
+ # @return 1 to represent that this line should trigger the current test
65
+ # @return 0 to represent that this line should not trigger the current test
66
+ def normalize_cov_result(result)
67
+ result.nil? || result.to_i < 0 ? 1 : result
68
+ end
69
+
70
+ def file_covered?(cov_before, cov_after)
71
+ cov_before != cov_after
72
+ end
73
+ end
74
+
75
+ private_class_method :lines_cov_delta, :file_covered?
76
+ end
77
+ end
@@ -1,26 +1,28 @@
1
- require 'json'
2
- require 'coverage'
3
- require 'coverage_peeker'
1
+ configure = -> do
2
+ require 'coverage'
3
+ require 'coverage_peeker'
4
+ require 'what_to_run/tracker'
4
5
 
5
- Coverage.start
6
+ Coverage.start
6
7
 
7
- require 'minitest'
8
+ require 'minitest'
8
9
 
9
- class Minitest::Runnable
10
- LOGS = []
10
+ WhatToRun::Tracker.start
11
11
 
12
- Minitest.after_run {
13
- File.open('run_log.json', 'w') { |f| f.write JSON.dump LOGS }
14
- }
12
+ class Minitest::Runnable
13
+ Minitest.after_run {WhatToRun::Tracker.finish}
15
14
 
16
- class << self
17
- alias :old_run_one_method :run_one_method
15
+ class << self
16
+ alias :old_run_one_method :run_one_method
18
17
 
19
- def run_one_method klass, method_name, reporter
20
- before = CoveragePeeker.peek_result
21
- old_run_one_method klass, method_name, reporter
22
- after = CoveragePeeker.peek_result
23
- LOGS << [ klass.name, method_name.to_s, before, after ]
18
+ def run_one_method(klass, method_name, reporter)
19
+ before = CoveragePeeker.peek_result
20
+ old_run_one_method klass, method_name, reporter
21
+ after = CoveragePeeker.peek_result
22
+ WhatToRun::Tracker.track "#{klass.name}##{method_name}", before, after
23
+ end
24
24
  end
25
25
  end
26
26
  end
27
+
28
+ configure.call if ENV['COLLECT'] && ENV['COLLECT'] != 'false'
@@ -0,0 +1,28 @@
1
+ require 'what_to_run/runner'
2
+ require 'shellwords'
3
+
4
+ module WhatToRun
5
+ module Minitest
6
+ class Runner < WhatToRun::Runner
7
+ DEFAULT_EXECUTABLE = 'bundle exec rake test'.freeze
8
+
9
+ def initialize(opts = {})
10
+ super({exec: DEFAULT_EXECUTABLE}.merge(opts))
11
+ end
12
+
13
+ private
14
+
15
+ def predicted_example_args
16
+ patterns = predicted_examples.flat_map do |example|
17
+ "^#{example}$"
18
+ end
19
+
20
+ examples = patterns.join('|')
21
+
22
+ name_arg = Shellwords.escape("--name=/#{examples}/")
23
+
24
+ "TESTOPTS=\"#{name_arg}\""
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,21 +1,27 @@
1
- require 'json'
2
- require 'rspec'
1
+ configure = -> do
2
+ require 'coverage'
3
+ require 'coverage_peeker'
4
+ require 'what_to_run/tracker'
3
5
 
4
- require 'coverage'
5
- require 'coverage_peeker'
6
+ Coverage.start
6
7
 
7
- LOGS = []
8
- Coverage.start
8
+ RSpec.configuration.before(:suite) do
9
+ WhatToRun::Tracker.start
10
+ end
9
11
 
10
- RSpec.configuration.after(:suite) {
11
- File.open('run_log.json', 'w') { |f| f.write JSON.dump LOGS }
12
- }
12
+ RSpec.configuration.after(:suite) do
13
+ WhatToRun::Tracker.finish
14
+ Coverage.result
15
+ end
13
16
 
14
- RSpec.configuration.around(:example) do |example|
15
- before = CoveragePeeker.peek_result
16
- puts 'before:' + before.object_id.to_s
17
- example.call
18
- after = CoveragePeeker.peek_result
19
- puts 'after:' + after.object_id.to_s
20
- LOGS << [ example.full_description, before, after ]
17
+ RSpec.configuration.around(:each) do |example|
18
+ before = CoveragePeeker.peek_result
19
+ example.call
20
+ after = CoveragePeeker.peek_result
21
+
22
+ WhatToRun::Tracker.track \
23
+ example.metadata[:full_description], before, after
24
+ end
21
25
  end
26
+
27
+ configure.call if ENV['COLLECT'] && ENV['COLLECT'] != 'false'
@@ -0,0 +1,21 @@
1
+ require 'what_to_run/runner'
2
+ require 'shellwords'
3
+
4
+ module WhatToRun
5
+ module RSpec
6
+ class Runner < WhatToRun::Runner
7
+ DEFAULT_EXECUTABLE = 'bundle exec rspec'.freeze
8
+
9
+ def initialize(opts = {})
10
+ super({exec: DEFAULT_EXECUTABLE}.merge(opts))
11
+ end
12
+
13
+ private
14
+
15
+ def predicted_example_args
16
+ args = predicted_examples.flat_map { |example| ['-e', example] }
17
+ Shellwords.join(args)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require 'what_to_run'
2
+
3
+ module WhatToRun
4
+ ##
5
+ # Abstract base spec runner
6
+ class Runner
7
+ attr_reader :executable, :collect
8
+
9
+ def initialize(opts = {})
10
+ @executable = opts.fetch(:exec)
11
+ end
12
+
13
+ def run
14
+ if predicted_examples.empty?
15
+ exit 0
16
+ else
17
+ Kernel.exec command
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def command
24
+ "#{executable} #{predicted_example_args}"
25
+ end
26
+
27
+ def predicted_example_args
28
+ fail NotImplementedError, 'Subclass must override #predicted_example_args'
29
+ end
30
+
31
+ def predicted_examples
32
+ @predicted_examples ||= WhatToRun.predict
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,74 @@
1
+ require 'sqlite3'
2
+ require 'fileutils'
3
+
4
+ require 'coverage_peeker'
5
+ require_relative 'differ'
6
+
7
+ module WhatToRun
8
+ class Tracker
9
+ FileUtils.mkdir_p('.what_to_run')
10
+
11
+ DB_NAME = 'run_log'.freeze
12
+
13
+ DB = SQLite3::Database.open \
14
+ ".what_to_run/#{DB_NAME}#{ENV['TEST_ENV_NUMBER']}.db"
15
+
16
+ class << self
17
+ def start
18
+ DB.execute 'drop table if exists coverage'
19
+
20
+ DB.execute <<-SQL
21
+ create table if not exists coverage (
22
+ description varchar,
23
+ log blob
24
+ )
25
+ SQL
26
+
27
+ @before_suite = CoveragePeeker.peek_result
28
+ end
29
+
30
+ def track(description, before, after)
31
+ coverage = Marshal.dump \
32
+ Differ.coverage_delta(before, after, @before_suite)
33
+
34
+ DB.execute 'insert into coverage VALUES(?, ?)',
35
+ [description, SQLite3::Blob.new(coverage)]
36
+ end
37
+
38
+ def finish
39
+ DB.close
40
+ end
41
+
42
+ def read
43
+ query = 'select description, log from coverage'
44
+
45
+ unless additional_databases.empty?
46
+ attach_databases!
47
+ query += union_query
48
+ end
49
+
50
+ DB.execute(query).map { |row| [row[0], Marshal.load(row[1])] }
51
+ end
52
+
53
+ def additional_databases
54
+ count = Dir['.what_to_run/*.db'].length
55
+ (2..count).map { |n| "#{DB_NAME}#{n}" }
56
+ end
57
+
58
+ def attach_databases!
59
+ additional_databases.each do |db|
60
+ DB.execute "attach '.what_to_run/#{db}.db' as #{db}"
61
+ end
62
+ end
63
+
64
+ def union_query
65
+ additional_databases.inject('') do |query, db|
66
+ query += " union select description, log from #{db}.coverage"
67
+ end
68
+ end
69
+ end
70
+
71
+ private_class_method :additional_databases,
72
+ :attach_databases!, :union_query
73
+ end
74
+ end
@@ -0,0 +1,3 @@
1
+ module WhatToRun
2
+ VERSION = '1.0.2'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: what_to_run
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
@@ -9,48 +9,68 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-30 00:00:00.000000000 Z
12
+ date: 2015-04-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0.9'
21
- - - ! '>='
21
+ - - ">="
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.9.0
24
24
  type: :development
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
- - - ~>
28
+ - - "~>"
29
29
  - !ruby/object:Gem::Version
30
30
  version: '0.9'
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.9.0
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: rugged
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.21'
41
- - - ! '>='
41
+ - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  version: 0.21.0
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - ~>
48
+ - - "~>"
49
49
  - !ruby/object:Gem::Version
50
50
  version: '0.21'
51
- - - ! '>='
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: 0.21.0
54
+ - !ruby/object:Gem::Dependency
55
+ name: sqlite3
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.3'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.3.10
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.3'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.10
54
74
  description: Predict which tests are likely to fail after you’ve changed the code
55
75
  email: dyego@dyegocosta.com
56
76
  executables:
@@ -66,8 +86,15 @@ files:
66
86
  - ext/coverage_peeker/extconf.rb
67
87
  - lib/coverage_peeker.rb
68
88
  - lib/what_to_run.rb
89
+ - lib/what_to_run/cli.rb
90
+ - lib/what_to_run/differ.rb
69
91
  - lib/what_to_run/minitest.rb
92
+ - lib/what_to_run/minitest/runner.rb
70
93
  - lib/what_to_run/rspec.rb
94
+ - lib/what_to_run/rspec/runner.rb
95
+ - lib/what_to_run/runner.rb
96
+ - lib/what_to_run/tracker.rb
97
+ - lib/what_to_run/version.rb
71
98
  homepage: https://github.com/DyegoCosta/what_to_run
72
99
  licenses:
73
100
  - MIT
@@ -78,12 +105,12 @@ require_paths:
78
105
  - lib
79
106
  required_ruby_version: !ruby/object:Gem::Requirement
80
107
  requirements:
81
- - - ! '>='
108
+ - - ">="
82
109
  - !ruby/object:Gem::Version
83
110
  version: 1.9.3
84
111
  required_rubygems_version: !ruby/object:Gem::Requirement
85
112
  requirements:
86
- - - ! '>='
113
+ - - ">="
87
114
  - !ruby/object:Gem::Version
88
115
  version: '0'
89
116
  requirements: []