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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +8 -0
- data/lib/factory_sloth/cli.rb +18 -6
- data/lib/factory_sloth/code_mod.rb +22 -25
- data/lib/factory_sloth/file_processor.rb +4 -4
- data/lib/factory_sloth/spec_runner.rb +13 -0
- data/lib/factory_sloth/version.rb +1 -1
- data/lib/factory_sloth.rb +1 -0
- metadata +3 -3
- data/Gemfile.lock +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cefc242e547927b9e8805b2dd4be60905f4dd5e484a5b42da6699e3c104879e8
|
4
|
+
data.tar.gz: 60c06cc54a40a35b4a72850d636510af0883071760fd88b5587091e1866de261
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/lib/factory_sloth/cli.rb
CHANGED
@@ -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
|
-
|
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 :
|
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
|
-
|
25
|
-
|
26
|
-
|
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 =
|
30
|
-
self.
|
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
|
-
|
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 :
|
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
|
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.
|
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
|
-
|
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
|
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
|
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.
|
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-
|
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
|