factory_sloth 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93e7cdb1f418a30bf140f3b28ce646bcbf9d46302b45bb105948c32ceee042ff
4
- data.tar.gz: b019faddee1c76fa58feb3129df86b6af87087c12f94ce8daddfaa5cfe14408a
3
+ metadata.gz: cefc242e547927b9e8805b2dd4be60905f4dd5e484a5b42da6699e3c104879e8
4
+ data.tar.gz: 60c06cc54a40a35b4a72850d636510af0883071760fd88b5587091e1866de261
5
5
  SHA512:
6
- metadata.gz: eab4ae49740dc1c9ded502ea5af2558e3edc441bf7a5527f8d382ae7bb71da9dd0bac816beb75572b1c3afdc18d89c7c402e567d90c1302b95b5232f293a43a9
7
- data.tar.gz: 6c184366974c8428d81f800d063c10a243c8c7989154f9c7b5dfcb27651af85723fcd04d2b24d1b84819f62ab5150eb3ee3d52c5bb8bea950c56b5ff744ba484
6
+ metadata.gz: c96fcd9841cd70fc952f6f503bd2e84024a2bf786fd132805f0badff7b5208f720be9cc36a73981d77f65fa932e256d7b4ecf2c08e59425ce811e10c61f2813a
7
+ data.tar.gz: 885c2928964f3dff1e041a4fa09b3c85a13a452e3168a6985754b0ec6fae01c1cc550001f76808451d02ee477bdcb82b1d2c10dd82576f95b1555b2eab325dcb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.1.0] - 2023-05-16
4
+
5
+ ### Added
6
+
7
+ - Added summary at end of CLI output
8
+
9
+ ## [1.0.1] - 2023-05-14
10
+
11
+ ### Fixed
12
+
13
+ - Fixed shelling out on linuxes with simple shells
14
+
3
15
  ## [1.0.0] - 2023-05-14
4
16
 
5
17
  - Initial release
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/factory_sloth.svg)](http://badge.fury.io/rb/factory_sloth)
4
4
  [![Build Status](https://github.com/jaynetics/factory_sloth/actions/workflows/tests.yml/badge.svg)](https://github.com/jaynetics/factory_sloth/actions)
5
+ [![Coverage](https://codecov.io/gh/jaynetics/factory_sloth/branch/main/graph/badge.svg?token=W6UJA0F8WO)](https://codecov.io/gh/jaynetics/factory_sloth)
5
6
 
6
7
  `factory_sloth` is too lazy to write to the database.
7
8
 
@@ -49,10 +50,17 @@ Processing spec/models/user_spec.rb ...
49
50
  Processing spec/weird_dir/crazy_spec.rb ...
50
51
  - create in line 8 can be replaced with build_stubbed
51
52
  🔴 33 create calls found, 0 replaced (conflict)
53
+
54
+ Scanned 4 files, found 2 unnecessary create calls across 1 files and 1 broken specs
52
55
  ```
53
56
 
54
57
  The `conflict` case is rare. It only happens if individual examples were green after changing them, but at least one example failed when evaluating the whole file after all changes. This probably means that some other example was red even before making changes, or that something else is wrong with this spec file, e.g. some examples depend on other examples' side effects.
55
58
 
59
+ ## Limitations
60
+
61
+ - only works with RSpec so far
62
+ - downgrades create calls that never run (e.g. in skipped examples)
63
+
56
64
  ## Development
57
65
 
58
66
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -8,12 +8,8 @@ module FactorySloth
8
8
  args = option_parser.parse!(argv)
9
9
  specs = SpecPicker.call(paths: args)
10
10
  forced_files = @force ? specs : args
11
- bad_specs = FileProcessor.call(files: specs, forced_files: forced_files, dry_run: @lint)
12
-
13
- if @lint && bad_specs.any?
14
- warn "Found unnecessary create calls in:\n#{bad_specs.join("\n")}"
15
- exit 1
16
- end
11
+ results = FileProcessor.call(files: specs, forced_files: forced_files, dry_run: @lint)
12
+ print_summary(results)
17
13
  end
18
14
 
19
15
  private
@@ -51,5 +47,21 @@ module FactorySloth
51
47
  end
52
48
  end
53
49
  end
50
+
51
+ def print_summary(results)
52
+ unnecessary_call_count = results.values.sum { |v| v[:changed_create_calls].count }
53
+ changed_specs = results.keys.select { |path| results[path][:changed_create_calls].any? }
54
+ broken_specs = results.keys.select { |path| !results[path][:ok] }
55
+ stats = "Scanned #{results.count} files, found #{unnecessary_call_count}"\
56
+ " unnecessary create calls across #{changed_specs.count} files"\
57
+ "#{" and #{broken_specs.count} broken specs" if broken_specs.any?}"
58
+
59
+ if @lint && unnecessary_call_count > 0
60
+ warn "#{stats}:\n#{(changed_specs + broken_specs).join("\n")}"
61
+ exit 1
62
+ else
63
+ puts stats
64
+ end
65
+ end
54
66
  end
55
67
  end
@@ -1,62 +1,59 @@
1
- require 'tempfile'
2
-
3
1
  class FactorySloth::CodeMod
4
- attr_reader :change_count, :create_count, :ok, :original_code, :patched_code
5
- alias_method :ok?, :ok
2
+ attr_reader :create_calls, :changed_create_calls, :original_code, :patched_code
6
3
 
7
4
  def self.call(code)
8
5
  new(code).tap(&:call)
9
6
  end
10
7
 
11
8
  def initialize(code)
12
- self.change_count = 0
13
9
  self.original_code = code
14
10
  self.patched_code = code
15
11
  end
16
12
 
17
13
  def call
18
- create_calls = FactorySloth::CreateCallFinder.call(code: original_code)
14
+ self.create_calls = FactorySloth::CreateCallFinder.call(code: original_code)
19
15
 
20
16
  # Performance note: it might be faster to write ALL possible patches for a
21
17
  # given spec file to tempfiles first, and then run them all in a single
22
18
  # rspec call. However, this would make it impossible to use `--fail-fast`,
23
19
  # and might make examples fail that are not as idempotent as they should be.
24
- create_calls.sort_by { |line, col| [-line, -col] }.each do |line, col|
25
- try_patch(line, col, 'build') || try_patch(line, col, 'build_stubbed')
26
- end
20
+ self.changed_create_calls =
21
+ create_calls.sort_by { |line, col| [-line, -col] }.select do |line, col|
22
+ try_patch(line, col, 'build') || try_patch(line, col, 'build_stubbed')
23
+ end.sort
27
24
 
28
25
  # validate whole spec after changes, e.g. to detect side-effects
29
- self.ok = spec_code_passes?(patched_code)
30
- self.change_count = 0 unless ok?
26
+ self.ok = FactorySloth::SpecRunner.call(patched_code)
27
+ self.changed_create_calls.clear unless ok?
31
28
  self.patched_code = original_code unless ok?
32
- self.create_count = create_calls.count
29
+ end
30
+
31
+ def ok?
32
+ @ok
33
33
  end
34
34
 
35
35
  def changed?
36
36
  change_count > 0
37
37
  end
38
38
 
39
+ def create_count
40
+ create_calls.count
41
+ end
42
+
43
+ def change_count
44
+ changed_create_calls.count
45
+ end
46
+
39
47
  private
40
48
 
41
- attr_writer :change_count, :create_count, :ok, :original_code, :patched_code
49
+ attr_writer :create_calls, :changed_create_calls, :ok, :original_code, :patched_code
42
50
 
43
51
  def try_patch(line, col, variant)
44
52
  new_patched_code =
45
53
  patched_code.sub(/\A(?:.*\n){#{line - 1}}.{#{col}}\Kcreate/, variant)
46
- if spec_code_passes?(new_patched_code, line: line)
54
+ if FactorySloth::SpecRunner.call(new_patched_code, line: line)
47
55
  puts "- create in line #{line} can be replaced with #{variant}"
48
56
  self.patched_code = new_patched_code
49
- self.change_count += 1
50
57
  end
51
58
  end
52
-
53
- def spec_code_passes?(spec_code, line: nil)
54
- tempfile = Tempfile.new
55
- tempfile.write(spec_code)
56
- tempfile.close
57
- path = [tempfile.path, line].compact.map(&:to_s).join(':')
58
- result = !!system("bundle exec rspec #{path} --fail-fast &> /dev/null")
59
- tempfile.unlink
60
- result
61
- end
62
59
  end
@@ -3,7 +3,7 @@ module FactorySloth
3
3
  extend self
4
4
 
5
5
  def call(files:, forced_files: [], dry_run: false)
6
- files.select do |path|
6
+ files.each_with_object({}) do |path, acc|
7
7
  puts "Processing #{path} ..."
8
8
 
9
9
  if DoneTracker.done?(path) && !forced_files.include?(path)
@@ -11,9 +11,9 @@ module FactorySloth
11
11
  next
12
12
  end
13
13
 
14
- bad_creates_found = process(path, dry_run: dry_run)
14
+ result = process(path, dry_run: dry_run)
15
+ acc[path] = { ok: result.ok?, changed_create_calls: result.changed_create_calls }
15
16
  DoneTracker.mark_as_done(path)
16
- bad_creates_found
17
17
  end
18
18
  end
19
19
 
@@ -26,7 +26,7 @@ module FactorySloth
26
26
  File.write(path, result.patched_code) if result.changed?
27
27
  end
28
28
  puts result_message(result, dry_run), ''
29
- result.changed?
29
+ result
30
30
  end
31
31
 
32
32
  def result_message(result, dry_run)
@@ -0,0 +1,13 @@
1
+ require 'tempfile'
2
+
3
+ module FactorySloth::SpecRunner
4
+ def self.call(spec_code, line: nil)
5
+ tempfile = Tempfile.new
6
+ tempfile.write(spec_code)
7
+ tempfile.close
8
+ path = [tempfile.path, line].compact.map(&:to_s).join(':')
9
+ result = !!system("bundle exec rspec #{path} --fail-fast 1>/dev/null 2>&1")
10
+ tempfile.unlink
11
+ result
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module FactorySloth
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
data/lib/factory_sloth.rb CHANGED
@@ -6,4 +6,5 @@ require_relative 'factory_sloth/create_call_finder'
6
6
  require_relative 'factory_sloth/done_tracker'
7
7
  require_relative 'factory_sloth/file_processor'
8
8
  require_relative 'factory_sloth/spec_picker'
9
+ require_relative 'factory_sloth/spec_runner'
9
10
  require_relative 'factory_sloth/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_sloth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janosch Müller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-14 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -21,7 +21,6 @@ files:
21
21
  - ".rspec"
22
22
  - CHANGELOG.md
23
23
  - Gemfile
24
- - Gemfile.lock
25
24
  - LICENSE.txt
26
25
  - README.md
27
26
  - Rakefile
@@ -33,6 +32,7 @@ files:
33
32
  - lib/factory_sloth/done_tracker.rb
34
33
  - lib/factory_sloth/file_processor.rb
35
34
  - lib/factory_sloth/spec_picker.rb
35
+ - lib/factory_sloth/spec_runner.rb
36
36
  - lib/factory_sloth/version.rb
37
37
  homepage: https://github.com/jaynetics/factory_sloth
38
38
  licenses:
data/Gemfile.lock DELETED
@@ -1,47 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- factory_sloth (1.0.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- diff-lcs (1.5.0)
10
- docile (1.4.0)
11
- rake (13.0.6)
12
- rexml (3.2.5)
13
- rspec (3.12.0)
14
- rspec-core (~> 3.12.0)
15
- rspec-expectations (~> 3.12.0)
16
- rspec-mocks (~> 3.12.0)
17
- rspec-core (3.12.2)
18
- rspec-support (~> 3.12.0)
19
- rspec-expectations (3.12.3)
20
- diff-lcs (>= 1.2.0, < 2.0)
21
- rspec-support (~> 3.12.0)
22
- rspec-mocks (3.12.5)
23
- diff-lcs (>= 1.2.0, < 2.0)
24
- rspec-support (~> 3.12.0)
25
- rspec-support (3.12.0)
26
- simplecov (0.22.0)
27
- docile (~> 1.1)
28
- simplecov-html (~> 0.11)
29
- simplecov_json_formatter (~> 0.1)
30
- simplecov-cobertura (2.1.0)
31
- rexml
32
- simplecov (~> 0.19)
33
- simplecov-html (0.12.3)
34
- simplecov_json_formatter (0.1.4)
35
-
36
- PLATFORMS
37
- arm64-darwin-21
38
- ruby
39
-
40
- DEPENDENCIES
41
- factory_sloth!
42
- rake (~> 13.0)
43
- rspec (~> 3.0)
44
- simplecov-cobertura (~> 2.1)
45
-
46
- BUNDLED WITH
47
- 2.4.7