ai_refactor 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +5 -1
- data/README.md +63 -37
- data/Rakefile +1 -1
- data/ai_refactor.gemspec +1 -0
- data/exe/ai_refactor +78 -44
- data/lib/ai_refactor/cli.rb +86 -0
- data/lib/ai_refactor/context.rb +33 -0
- data/lib/ai_refactor/file_processor.rb +34 -17
- data/lib/ai_refactor/prompt.rb +84 -0
- data/lib/ai_refactor/prompts/diff.md +17 -0
- data/lib/ai_refactor/prompts/input.md +1 -0
- data/lib/ai_refactor/refactors/base_refactor.rb +176 -0
- data/lib/ai_refactor/refactors/generic.rb +6 -76
- data/lib/ai_refactor/refactors/minitest/write_test_for_class.md +11 -0
- data/lib/ai_refactor/refactors/minitest/write_test_for_class.rb +51 -0
- data/lib/ai_refactor/refactors/project/write_changelog_from_history.md +35 -0
- data/lib/ai_refactor/refactors/project/write_changelog_from_history.rb +50 -0
- data/lib/ai_refactor/refactors/{prompts/rspec_to_minitest_rails.md → rails/minitest/rspec_to_minitest.md} +40 -1
- data/lib/ai_refactor/refactors/rails/minitest/rspec_to_minitest.rb +77 -0
- data/lib/ai_refactor/refactors/rspec/minitest_to_rspec.rb +13 -0
- data/lib/ai_refactor/refactors.rb +13 -5
- data/lib/ai_refactor/{refactors/tests → test_runners}/minitest_runner.rb +1 -1
- data/lib/ai_refactor/{refactors/tests → test_runners}/rspec_runner.rb +1 -1
- data/lib/ai_refactor/{refactors/tests → test_runners}/test_run_diff_report.rb +1 -1
- data/lib/ai_refactor/{refactors/tests → test_runners}/test_run_result.rb +1 -1
- data/lib/ai_refactor/version.rb +1 -1
- data/lib/ai_refactor.rb +13 -8
- metadata +34 -11
- data/lib/ai_refactor/base_refactor.rb +0 -66
- data/lib/ai_refactor/refactors/minitest_to_rspec.rb +0 -11
- data/lib/ai_refactor/refactors/rspec_to_minitest_rails.rb +0 -103
- /data/lib/ai_refactor/refactors/{prompts → rspec}/minitest_to_rspec.md +0 -0
@@ -1,8 +1,8 @@
|
|
1
|
+
You are an expert software developer.
|
1
2
|
You convert RSpec tests to ActiveSupport::TestCase tests for Ruby on Rails.
|
2
3
|
ActiveSupport::TestCase uses MiniTest under the hood.
|
3
4
|
Remember that MiniTest does not support `context` blocks, instead these should be removed and the context
|
4
5
|
specified in them should be moved directly into the relevant tests.
|
5
|
-
Always enclose the output code in triple backticks (```).
|
6
6
|
|
7
7
|
Here are some examples to use as a guide:
|
8
8
|
|
@@ -42,6 +42,10 @@ subject(:model) { create(:order_state) }
|
|
42
42
|
context "when rejected" do
|
43
43
|
before { model.rejected_at = 1.day.ago }
|
44
44
|
|
45
|
+
it "should be not valid" do
|
46
|
+
expect(model).not_to be_valid
|
47
|
+
end
|
48
|
+
|
45
49
|
context "with reason and message" do
|
46
50
|
before do
|
47
51
|
model.rejected_message = reason
|
@@ -68,6 +72,11 @@ setup do
|
|
68
72
|
@reason = "my reason"
|
69
73
|
end
|
70
74
|
|
75
|
+
test "when rejected, model should be not valid" do
|
76
|
+
@model.rejected_at = 1.day.ago
|
77
|
+
refute @model.valid?
|
78
|
+
end
|
79
|
+
|
71
80
|
test "when rejected, with reason and message, model should be valid" do
|
72
81
|
@model.rejected_at = 1.day.ago
|
73
82
|
@model.rejected_message = @reason
|
@@ -231,3 +240,33 @@ test "stubs any instance" do
|
|
231
240
|
end
|
232
241
|
end
|
233
242
|
```
|
243
|
+
|
244
|
+
Example 9) RSpec:
|
245
|
+
```
|
246
|
+
assert_association @model, :message_thread, :belongs_to
|
247
|
+
```
|
248
|
+
|
249
|
+
Result 9) minitest:
|
250
|
+
|
251
|
+
```
|
252
|
+
assert_instance_of MessageThread, @model.message_thread
|
253
|
+
```
|
254
|
+
|
255
|
+
Example 10) RSpec:
|
256
|
+
```
|
257
|
+
assert_association @model, :message_thread, :belongs_to, optional: true
|
258
|
+
```
|
259
|
+
|
260
|
+
Result 10) minitest:
|
261
|
+
```
|
262
|
+
assoc = @model.reflect_on_association(:message_thread)
|
263
|
+
refute assoc.nil?, "no association :message_thread"
|
264
|
+
assert_equal :belongs_to, assoc.macro
|
265
|
+
assert assoc.options[:optional]
|
266
|
+
```
|
267
|
+
|
268
|
+
__{{context}}__
|
269
|
+
|
270
|
+
Only output the refactored class. Do NOT provide any other description of your work. Always enclose the output code in triple backticks (```).
|
271
|
+
|
272
|
+
Convert this Rspec file to minitest:
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AIRefactor
|
4
|
+
module Refactors
|
5
|
+
module Rails
|
6
|
+
module Minitest
|
7
|
+
class RspecToMinitest < BaseRefactor
|
8
|
+
def run
|
9
|
+
spec_runner = AIRefactor::TestRunners::RSpecRunner.new(input_file)
|
10
|
+
logger.verbose "Run spec #{input_file}... (#{spec_runner.command})"
|
11
|
+
|
12
|
+
spec_run = spec_runner.run
|
13
|
+
|
14
|
+
if spec_run.failed?
|
15
|
+
logger.warn "Skipping #{input_file}..."
|
16
|
+
logger.error "Failed to run #{input_file}, exited with status #{spec_run.exitstatus}. Stdout: #{spec_run.stdout}\n\nStderr: #{spec_run.stderr}\n\n"
|
17
|
+
self.failed_message = "Failed to run RSpec file, has errors"
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
|
21
|
+
logger.debug "\nOriginal test run results:"
|
22
|
+
logger.debug ">> Examples: #{spec_run.example_count}, Failures: #{spec_run.failure_count}, Pendings: #{spec_run.pending_count}\n"
|
23
|
+
|
24
|
+
begin
|
25
|
+
result = process!
|
26
|
+
rescue AIRefactor::NoOutputError => _e
|
27
|
+
return false
|
28
|
+
rescue => e
|
29
|
+
logger.error "Failed to convert #{input_file} to Minitest, error: #{e.message}"
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
|
33
|
+
logger.verbose "Converted #{input_file} to #{output_file_path}..." if result
|
34
|
+
|
35
|
+
minitest_runner = AIRefactor::TestRunners::MinitestRunner.new(output_file_path)
|
36
|
+
|
37
|
+
logger.verbose "Run generated test file #{output_file_path} (#{minitest_runner.command})..."
|
38
|
+
test_run = minitest_runner.run
|
39
|
+
|
40
|
+
if test_run.failed?
|
41
|
+
logger.warn "Skipping #{input_file}..."
|
42
|
+
logger.error "Failed to run translated #{output_file_path}, exited with status #{test_run.exitstatus}. Stdout: #{test_run.stdout}\n\nStderr: #{test_run.stderr}\n\n"
|
43
|
+
logger.error "Conversion failed!", bold: true
|
44
|
+
self.failed_message = "Generated test file failed to run correctly"
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
|
48
|
+
logger.debug "\nTranslated test file results:"
|
49
|
+
logger.debug ">> Runs: #{test_run.example_count}, Failures: #{test_run.failure_count}, Skips: #{test_run.pending_count}\n"
|
50
|
+
|
51
|
+
report = AIRefactor::TestRunners::TestRunDiffReport.new(spec_run, test_run)
|
52
|
+
|
53
|
+
if report.no_differences?
|
54
|
+
logger.verbose "Done converting #{input_file} to #{output_file_path}..."
|
55
|
+
logger.success "\nNo differences found! Conversion worked!"
|
56
|
+
true
|
57
|
+
else
|
58
|
+
logger.warn report.diff.colorize(:yellow)
|
59
|
+
logger.verbose "Done converting #{input_file} to #{output_file_path}..."
|
60
|
+
logger.error "\nDifferences found! Conversion failed!", bold: true
|
61
|
+
self.failed_message = "Generated test file run output did not match original RSpec spec run output"
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.description
|
67
|
+
"Convert RSpec file to Minitest (for Rails apps)"
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_output_path
|
71
|
+
input_file.gsub("_spec.rb", "_test.rb").gsub("spec/", "test/")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
module AIRefactor
|
4
4
|
module Refactors
|
5
|
+
def register(klass)
|
6
|
+
all[klass.refactor_name] = klass
|
7
|
+
end
|
8
|
+
module_function :register
|
9
|
+
|
5
10
|
def get(name)
|
6
11
|
all[name]
|
7
12
|
end
|
@@ -12,16 +17,19 @@ module AIRefactor
|
|
12
17
|
end
|
13
18
|
module_function :names
|
14
19
|
|
15
|
-
def
|
16
|
-
|
17
|
-
hash[klass.refactor_name] = klass
|
18
|
-
end
|
20
|
+
def descriptions
|
21
|
+
names.map { |n| "\"#{n}\"" }.zip(all.values.map(&:description)).to_h
|
19
22
|
end
|
20
|
-
module_function :
|
23
|
+
module_function :descriptions
|
21
24
|
|
22
25
|
def supported?(name)
|
23
26
|
names.include?(name)
|
24
27
|
end
|
25
28
|
module_function :supported?
|
29
|
+
|
30
|
+
def all
|
31
|
+
@all ||= {}
|
32
|
+
end
|
33
|
+
module_function :all
|
26
34
|
end
|
27
35
|
end
|
data/lib/ai_refactor/version.rb
CHANGED
data/lib/ai_refactor.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "zeitwerk"
|
4
|
+
loader = Zeitwerk::Loader.for_gem
|
5
|
+
loader.inflector.inflect(
|
6
|
+
"ai_refactor" => "AIRefactor",
|
7
|
+
"rspec_runner" => "RSpecRunner"
|
8
|
+
)
|
9
|
+
loader.setup # ready!
|
4
10
|
|
5
|
-
|
6
|
-
|
11
|
+
module AIRefactor
|
12
|
+
class NoOutputError < StandardError; end
|
13
|
+
# Your code goes here...
|
14
|
+
end
|
7
15
|
|
8
|
-
|
9
|
-
|
10
|
-
require_relative "ai_refactor/refactors/generic"
|
11
|
-
require_relative "ai_refactor/refactors/rspec_to_minitest_rails"
|
12
|
-
require_relative "ai_refactor/refactors/minitest_to_rspec"
|
16
|
+
# We eager load here to ensure that all Refactor classes are loaded at startup so they can be registered
|
17
|
+
loader.eager_load
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai_refactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Ierodiaconou
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - "<"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '5.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: zeitwerk
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.6'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.6'
|
61
75
|
description: Use OpenAI's ChatGPT to automate converting Rails RSpec tests to minitest
|
62
76
|
(ActiveSupport::TestCase).
|
63
77
|
email:
|
@@ -77,19 +91,28 @@ files:
|
|
77
91
|
- ai_refactor.gemspec
|
78
92
|
- exe/ai_refactor
|
79
93
|
- lib/ai_refactor.rb
|
80
|
-
- lib/ai_refactor/
|
94
|
+
- lib/ai_refactor/cli.rb
|
95
|
+
- lib/ai_refactor/context.rb
|
81
96
|
- lib/ai_refactor/file_processor.rb
|
82
97
|
- lib/ai_refactor/logger.rb
|
98
|
+
- lib/ai_refactor/prompt.rb
|
99
|
+
- lib/ai_refactor/prompts/diff.md
|
100
|
+
- lib/ai_refactor/prompts/input.md
|
83
101
|
- lib/ai_refactor/refactors.rb
|
102
|
+
- lib/ai_refactor/refactors/base_refactor.rb
|
84
103
|
- lib/ai_refactor/refactors/generic.rb
|
85
|
-
- lib/ai_refactor/refactors/
|
86
|
-
- lib/ai_refactor/refactors/
|
87
|
-
- lib/ai_refactor/refactors/
|
88
|
-
- lib/ai_refactor/refactors/
|
89
|
-
- lib/ai_refactor/refactors/
|
90
|
-
- lib/ai_refactor/refactors/
|
91
|
-
- lib/ai_refactor/refactors/
|
92
|
-
- lib/ai_refactor/refactors/
|
104
|
+
- lib/ai_refactor/refactors/minitest/write_test_for_class.md
|
105
|
+
- lib/ai_refactor/refactors/minitest/write_test_for_class.rb
|
106
|
+
- lib/ai_refactor/refactors/project/write_changelog_from_history.md
|
107
|
+
- lib/ai_refactor/refactors/project/write_changelog_from_history.rb
|
108
|
+
- lib/ai_refactor/refactors/rails/minitest/rspec_to_minitest.md
|
109
|
+
- lib/ai_refactor/refactors/rails/minitest/rspec_to_minitest.rb
|
110
|
+
- lib/ai_refactor/refactors/rspec/minitest_to_rspec.md
|
111
|
+
- lib/ai_refactor/refactors/rspec/minitest_to_rspec.rb
|
112
|
+
- lib/ai_refactor/test_runners/minitest_runner.rb
|
113
|
+
- lib/ai_refactor/test_runners/rspec_runner.rb
|
114
|
+
- lib/ai_refactor/test_runners/test_run_diff_report.rb
|
115
|
+
- lib/ai_refactor/test_runners/test_run_result.rb
|
93
116
|
- lib/ai_refactor/version.rb
|
94
117
|
homepage: https://github.com/stevegeek/ai_refactor
|
95
118
|
licenses:
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AIRefactor
|
4
|
-
class BaseRefactor
|
5
|
-
attr_reader :input_file, :options, :logger
|
6
|
-
attr_writer :failed_message
|
7
|
-
|
8
|
-
def initialize(input_file, options, logger)
|
9
|
-
@input_file = input_file
|
10
|
-
@options = options
|
11
|
-
@logger = logger
|
12
|
-
end
|
13
|
-
|
14
|
-
def run
|
15
|
-
raise NotImplementedError
|
16
|
-
end
|
17
|
-
|
18
|
-
def failed_message
|
19
|
-
@failed_message || "Reason not specified"
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def can_overwrite_output_file?(output_path)
|
25
|
-
logger.info "Do you wish to overwrite #{output_path}? (y/n)"
|
26
|
-
answer = $stdin.gets.chomp
|
27
|
-
unless answer == "y" || answer == "Y"
|
28
|
-
logger.warn "Skipping #{input_file}..."
|
29
|
-
self.failed_message = "Skipped as output file already exists"
|
30
|
-
return false
|
31
|
-
end
|
32
|
-
true
|
33
|
-
end
|
34
|
-
|
35
|
-
def prompt_file_path
|
36
|
-
file = if options && options[:prompt_file_path]&.length&.positive?
|
37
|
-
options[:prompt_file_path]
|
38
|
-
else
|
39
|
-
File.join(File.dirname(File.expand_path(__FILE__)), "refactors", "prompts", "#{refactor_name}.md")
|
40
|
-
end
|
41
|
-
file.tap do |prompt|
|
42
|
-
raise "No prompt file '#{prompt}' found for #{refactor_name}" unless File.exist?(prompt)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def ai_client
|
47
|
-
@ai_client ||= OpenAI::Client.new
|
48
|
-
end
|
49
|
-
|
50
|
-
class << self
|
51
|
-
def command_line_options
|
52
|
-
[]
|
53
|
-
end
|
54
|
-
|
55
|
-
def refactor_name
|
56
|
-
name.split("::")
|
57
|
-
.last
|
58
|
-
.gsub(/::/, "/")
|
59
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
60
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
61
|
-
.tr("-", "_")
|
62
|
-
.downcase
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "tests/test_run_result"
|
4
|
-
require_relative "tests/rspec_runner"
|
5
|
-
require_relative "tests/minitest_runner"
|
6
|
-
require_relative "tests/test_run_diff_report"
|
7
|
-
|
8
|
-
module AIRefactor
|
9
|
-
module Refactors
|
10
|
-
class RspecToMinitestRails < BaseRefactor
|
11
|
-
def run
|
12
|
-
spec_runner = AIRefactor::Tests::RSpecRunner.new(input_file)
|
13
|
-
logger.verbose "Run spec #{input_file}... (#{spec_runner.command})"
|
14
|
-
|
15
|
-
spec_run = spec_runner.run
|
16
|
-
|
17
|
-
if spec_run.failed?
|
18
|
-
logger.warn "Skipping #{input_file}..."
|
19
|
-
logger.error "Failed to run #{input_file}, exited with status #{spec_run.exitstatus}. Stdout: #{spec_run.stdout}\n\nStderr: #{spec_run.stderr}\n\n"
|
20
|
-
self.failed_message = "Failed to run RSpec file, has errors"
|
21
|
-
return false
|
22
|
-
end
|
23
|
-
|
24
|
-
logger.debug "Original test run results:"
|
25
|
-
logger.debug ">> Examples: #{spec_run.example_count}, Failures: #{spec_run.failure_count}, Pendings: #{spec_run.pending_count}"
|
26
|
-
|
27
|
-
output_path = input_file.gsub("_spec.rb", "_test.rb").gsub("spec/", "test/")
|
28
|
-
|
29
|
-
processor = AIRefactor::FileProcessor.new(
|
30
|
-
input_path: input_file,
|
31
|
-
output_path: output_path,
|
32
|
-
prompt_file_path: prompt_file_path,
|
33
|
-
ai_client: ai_client,
|
34
|
-
logger: logger
|
35
|
-
)
|
36
|
-
|
37
|
-
if processor.output_exists?
|
38
|
-
return false unless can_overwrite_output_file?(output_path)
|
39
|
-
end
|
40
|
-
|
41
|
-
logger.verbose "Converting #{input_file}..."
|
42
|
-
|
43
|
-
begin
|
44
|
-
output_content, finished_reason, usage = processor.process!(options) do |content|
|
45
|
-
content.gsub("```", "")
|
46
|
-
end
|
47
|
-
rescue => e
|
48
|
-
logger.error "Request to OpenAI failed: #{e.message}"
|
49
|
-
logger.warn "Skipping #{input_file}..."
|
50
|
-
self.failed_message = "Request to OpenAI failed"
|
51
|
-
return false
|
52
|
-
end
|
53
|
-
|
54
|
-
logger.verbose "OpenAI finished, with reason '#{finished_reason}'..."
|
55
|
-
logger.verbose "Used tokens: #{usage["total_tokens"]}".colorize(:light_black) if usage
|
56
|
-
|
57
|
-
if finished_reason == "length"
|
58
|
-
logger.warn "Translation may contain an incomplete output as the max token length was reached. You can try using the '--continue' option next time to increase the length of generated output."
|
59
|
-
logger.warn "Continuing to test the translated file... but it is likely to fail."
|
60
|
-
end
|
61
|
-
|
62
|
-
if !output_content || output_content.length == 0
|
63
|
-
logger.warn "Skipping #{input_file}, no translated output..."
|
64
|
-
logger.error "Failed to translate #{input_file}, finished reason #{finished_reason}"
|
65
|
-
self.failed_message = "AI conversion failed, no output was generated"
|
66
|
-
return false
|
67
|
-
end
|
68
|
-
|
69
|
-
logger.verbose "Converted #{input_file} to #{output_path}..."
|
70
|
-
|
71
|
-
minitest_runner = AIRefactor::Tests::MinitestRunner.new(processor.output_path)
|
72
|
-
|
73
|
-
logger.verbose "Run generated test file #{output_path} (#{minitest_runner.command})..."
|
74
|
-
test_run = minitest_runner.run
|
75
|
-
|
76
|
-
if test_run.failed?
|
77
|
-
logger.warn "Skipping #{input_file}..."
|
78
|
-
logger.error "Failed to run translated #{output_path}, exited with status #{test_run.exitstatus}. Stdout: #{test_run.stdout}\n\nStderr: #{test_run.stderr}\n\n"
|
79
|
-
logger.error "Conversion failed!", bold: true
|
80
|
-
self.failed_message = "Generated test file failed to run correctly"
|
81
|
-
return false
|
82
|
-
end
|
83
|
-
|
84
|
-
logger.debug "Translated test file results:"
|
85
|
-
logger.debug ">> Runs: #{test_run.example_count}, Failures: #{test_run.failure_count}, Skips: #{test_run.pending_count}"
|
86
|
-
|
87
|
-
report = AIRefactor::Tests::TestRunDiffReport.new(spec_run, test_run)
|
88
|
-
|
89
|
-
if report.no_differences?
|
90
|
-
logger.verbose "Done converting #{input_file} to #{output_path}..."
|
91
|
-
logger.success "No differences found! Conversion worked!"
|
92
|
-
true
|
93
|
-
else
|
94
|
-
logger.warn report.diff.colorize(:yellow)
|
95
|
-
logger.verbose "Done converting #{input_file} to #{output_path}..."
|
96
|
-
logger.error "Differences found! Conversion failed!", bold: true
|
97
|
-
self.failed_message = "Generated test file run output did not match original RSpec spec run output"
|
98
|
-
false
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
File without changes
|