omochi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/DESIGN.md +7 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.md +189 -0
- data/Rakefile +4 -0
- data/exe/omochi +5 -0
- data/lib/omochi/cli.rb +58 -0
- data/lib/omochi/util.rb +257 -0
- data/lib/omochi/version.rb +5 -0
- data/lib/omochi.rb +5 -0
- data/sig/omochi.rbs +4 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a34b2f4942b833cad4251d39b655591949025be459aa5433e352ec5daa467cd
|
4
|
+
data.tar.gz: 381bd6ca1e03d74e26e76773d1a9d61c14c0521f6b026230a4558652e9984d10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 582c88432f47a69d2822f92f1b8a4ccd4c3c1bae42f072bb2fa85d296d7ec6cc613f8451781f5d59b449b66b43e3a13a08cca2b036a96650666be934e69bd1c0
|
7
|
+
data.tar.gz: 5d1515d85ac400cf4b029bd04e0082b6bb48c8273e47028786e4e7b9f231b3652ecd50d026f2b774acad6991192ebe8344a6333f4e20b3a27fe2b328fb043d49
|
data/DESIGN.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
This library has 5 major steps.
|
2
|
+
|
3
|
+
1. Fetch Ruby files from diffs, including spec files
|
4
|
+
2. Parse them to AST
|
5
|
+
3. Get all methods and spec `describe`s and compare
|
6
|
+
4. If every method is covered, successfully return, otherwise print their names
|
7
|
+
5. If `--create` option is given, generate skeletons for missing specs
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Hashino Mikiko
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
# Omochi
|
2
|
+
|
3
|
+
Omochi is a CLI tool to support Ruby on Rails development with RSpec. It detects methods uncovered by tests and prints the test code generated by LLM.
|
4
|
+
|
5
|
+
There are two advantages of using Omochi. We can make sure every method is covered by tests with GitHub Actions support. We can also generate spec files for uncovered methods so that we can reduce time to write them manually.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem specific_install -l https://github.com/mikik0/omochi.git
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
```
|
16
|
+
$ omochi --help
|
17
|
+
Commands:
|
18
|
+
omochi help [COMMAND] # Describe available commands or one specific command
|
19
|
+
omochi verify local_path # verify spec created for all of new methods and functions
|
20
|
+
```
|
21
|
+
|
22
|
+
## Commands
|
23
|
+
### verify
|
24
|
+
|
25
|
+
When you execute Omochi locally, you can confirm that you have spec coverage for uncommitted diff.
|
26
|
+
|
27
|
+
```
|
28
|
+
# Local
|
29
|
+
$ omochi verify local_path
|
30
|
+
```
|
31
|
+
|
32
|
+
You can skip check with ignore comment.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
#omochi:ignore:
|
36
|
+
```
|
37
|
+
|
38
|
+
### --create option
|
39
|
+
|
40
|
+
You can generate spec files with LLM by giving `-c` or `--create` option. It outputs to STDOUT.
|
41
|
+
|
42
|
+
```
|
43
|
+
# Generate spec files
|
44
|
+
$ omochi verify local_path -c
|
45
|
+
# Or
|
46
|
+
$ omochi verify local_path --create
|
47
|
+
```
|
48
|
+
|
49
|
+
### --github option
|
50
|
+
|
51
|
+
With `-h` option you can check uncovered methods against given Pull Request with GitHub Actions.
|
52
|
+
It uses `gh pr diff` command internally.
|
53
|
+
|
54
|
+
```
|
55
|
+
$ omochi verify local_path -h
|
56
|
+
# Or
|
57
|
+
$ omochi verify local_path --github
|
58
|
+
```
|
59
|
+
|
60
|
+
## Samples
|
61
|
+
|
62
|
+
```
|
63
|
+
$ omochi verify -c
|
64
|
+
"Verify File List: [\"lib/omochi/cli.rb\", \"lib/omochi/util.rb\"]"
|
65
|
+
"specファイルあり"
|
66
|
+
"There are spec files."
|
67
|
+
===================================================================
|
68
|
+
verifyのテストを以下に表示します。
|
69
|
+
We will show the test of verify below.
|
70
|
+
require 'rspec'
|
71
|
+
|
72
|
+
describe 'exit_on_failure?' do
|
73
|
+
it 'returns true' do
|
74
|
+
expect(exit_on_failure?).to eq(true)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
======= RESULT: lib/omochi/cli.rb =======
|
78
|
+
- exit_on_failure?
|
79
|
+
"specファイルなし"
|
80
|
+
======= RESULT: lib/omochi/util.rb =======
|
81
|
+
- local_diff_path
|
82
|
+
- github_diff_path
|
83
|
+
- remote_diff_path
|
84
|
+
- get_ast
|
85
|
+
- dfs
|
86
|
+
- find_spec_file
|
87
|
+
- get_pure_function_name
|
88
|
+
- dfs_describe
|
89
|
+
- print_result
|
90
|
+
- get_ignore_methods
|
91
|
+
- create_spec_by_bedrock
|
92
|
+
===================================================================
|
93
|
+
lib/omochi/util.rbのテストを以下に表示します。
|
94
|
+
We will show the test of lib/omochi/util.rb below.
|
95
|
+
require "spec_helper"
|
96
|
+
|
97
|
+
describe "local_diff_path" do
|
98
|
+
it "returns array of diff paths from git" do
|
99
|
+
allow(Open3).to receive(:capture3).with("git diff --name-only", any_args).and_return(["path1", "path2"], "", double(success?: true))
|
100
|
+
expect(local_diff_path).to eq(["path1", "path2"])
|
101
|
+
end
|
102
|
+
|
103
|
+
it "returns empty array if git command fails" do
|
104
|
+
allow(Open3).to receive(:capture3).with("git diff --name-only", any_args).and_return("", "error", double(success?: false))
|
105
|
+
expect(local_diff_path).to eq([])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "github_diff_path" do
|
110
|
+
it "returns array of diff paths from gh" do
|
111
|
+
allow(Open3).to receive(:capture3).with("gh pr diff --name-only", any_args).and_return(["path1", "path2"], "", double(success?: true))
|
112
|
+
expect(github_diff_path).to eq(["path1", "path2"])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "returns empty array if gh command fails" do
|
116
|
+
allow(Open3).to receive(:capture3).with("gh pr diff --name-only", any_args).and_return("", "error", double(success?: false))
|
117
|
+
expect(github_diff_path).to eq([])
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "remote_diff_path" do
|
122
|
+
it "returns array of diff paths from remote" do
|
123
|
+
allow(Open3).to receive(:capture3).with(/git diff --name-only .*${{ github\.sha }}/, any_args).and_return(["path1", "path2"], "", double(success?: true))
|
124
|
+
expect(remote_diff_path).to eq(["path1", "path2"])
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns empty array if git command fails" do
|
128
|
+
allow(Open3).to receive(:capture3).with(/git diff --name-only .*${{ github\.sha }}/, any_args).and_return("", "error", double(success?: false))
|
129
|
+
expect(remote_diff_path).to eq([])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "get_ast" do
|
134
|
+
it "returns AST for given file" do
|
135
|
+
allow(File).to receive(:read).with("file.rb").and_return("code")
|
136
|
+
allow(Parser::CurrentRuby).to receive(:parse_with_comments).with("code").and_return(["ast"], ["comments"])
|
137
|
+
expect(get_ast("file.rb")).to eq([{ast: "ast", filename: "file.rb"}])
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "dfs" do
|
142
|
+
let(:node) { double(:node, type: :def, children: [double(:child, children: ["name"])]) }
|
143
|
+
let(:result) { {} }
|
144
|
+
|
145
|
+
it "traverses node and captures def names" do
|
146
|
+
dfs(node, "file.rb", result)
|
147
|
+
expect(result).to eq({"name" => "def name\nend"})
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "find_spec_file" do
|
152
|
+
before do
|
153
|
+
allow(File).to receive(:exist?).with("spec/app/file_spec.rb").and_return(true)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "returns spec file path if exists" do
|
157
|
+
expect(find_spec_file("app/file.rb")).to eq("spec/app/file_spec.rb")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "returns nil if spec file does not exist" do
|
161
|
+
allow(File).to receive(:exist?).with("spec/app/file_spec.rb").and_return(false)
|
162
|
+
expect(find_spec_file("app/file.rb")).to be_nil
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# similarly test other functions
|
167
|
+
```
|
168
|
+
|
169
|
+
## Contributing
|
170
|
+
|
171
|
+
Bug reports and Pull Requests are accepted on GitHub (https://github.com/mikik0/omochi).
|
172
|
+
This project should be a safe place for collaboration.
|
173
|
+
|
174
|
+
### Design
|
175
|
+
|
176
|
+
See [DESIGN.md](https://github.com/mikik0/omochi/blob/master/DESIGN.md)
|
177
|
+
|
178
|
+
### Development
|
179
|
+
|
180
|
+
#### Requirement
|
181
|
+
|
182
|
+
- ruby3.x
|
183
|
+
- AWS Credentials (for `--create`)
|
184
|
+
|
185
|
+
```
|
186
|
+
git clone https://github.com/mikik0/omochi.git
|
187
|
+
bundle install
|
188
|
+
bundle exec bin/omochi verify
|
189
|
+
```
|
data/Rakefile
ADDED
data/exe/omochi
ADDED
data/lib/omochi/cli.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'omochi'
|
4
|
+
require 'thor'
|
5
|
+
require 'omochi/util'
|
6
|
+
require 'yaml'
|
7
|
+
require 'aws-sdk-bedrockruntime'
|
8
|
+
require 'dotenv/load'
|
9
|
+
require 'unparser'
|
10
|
+
|
11
|
+
module Omochi
|
12
|
+
class CLI < Thor
|
13
|
+
include Omochi::Util
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def exit_on_failure?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'verify local_path', 'verify spec created for all of new methods and functions'
|
22
|
+
method_option :github, aliases: '-h', desc: 'Running on GitHub Action'
|
23
|
+
method_option :create, aliases: '-c', desc: 'Create Spec for Untested Method'
|
24
|
+
def verify
|
25
|
+
is_gh_action = options[:github] == 'github'
|
26
|
+
is_gl_ci_runner = false
|
27
|
+
create_spec = options[:create] == 'create'
|
28
|
+
perfect = true
|
29
|
+
|
30
|
+
diff_paths = case [is_gh_action, is_gl_ci_runner]
|
31
|
+
when [true, false]
|
32
|
+
github_diff_path
|
33
|
+
when [false, true]
|
34
|
+
remote_diff_path
|
35
|
+
when [false, false]
|
36
|
+
local_diff_path
|
37
|
+
end
|
38
|
+
|
39
|
+
# Ruby 以外のファイル(yamlやmdなど)を除外 specファイルも除外(テストにはテストない)
|
40
|
+
diff_paths.reject! { |s| !s.end_with?('.rb') || s.end_with?('_spec.rb') }
|
41
|
+
p "Verify File List: #{diff_paths}"
|
42
|
+
|
43
|
+
# diff_paths 例: ["lib/omochi/cli.rb", "lib/omochi/util.rb"]
|
44
|
+
diff_paths.each do |diff_path|
|
45
|
+
if find_spec_file(diff_path)
|
46
|
+
p 'specファイルあり'
|
47
|
+
p 'There are spec files.'
|
48
|
+
perfect = process_spec_file(diff_path, create_spec, perfect)
|
49
|
+
else
|
50
|
+
p 'specファイルなし'
|
51
|
+
p 'There is no spec file.'
|
52
|
+
perfect = process_missing_spec_file(diff_path, create_spec, perfect)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
exit(perfect ? 0 : 1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/omochi/util.rb
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'parser/current'
|
5
|
+
require 'json'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
module Omochi
|
9
|
+
module Util
|
10
|
+
include AST::Processor::Mixin
|
11
|
+
|
12
|
+
def local_diff_path
|
13
|
+
# Gitがインストールされているか確認
|
14
|
+
unless system('git --version > /dev/null 2>&1')
|
15
|
+
puts 'Error: Git is not installed. Please install Git.'
|
16
|
+
return []
|
17
|
+
end
|
18
|
+
|
19
|
+
# ローカルのdiffを取得する
|
20
|
+
diff_command = 'git diff --diff-filter=d --name-only'
|
21
|
+
diff_output, _diff_error, _diff_status = Open3.capture3(diff_command, chdir: '.')
|
22
|
+
|
23
|
+
# エラーチェック
|
24
|
+
unless _diff_status.success?
|
25
|
+
puts "Error: Failed to run 'git diff' command."
|
26
|
+
return []
|
27
|
+
end
|
28
|
+
|
29
|
+
# 取得したdiffのpathを返却する
|
30
|
+
diff_output.split("\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
def github_diff_path
|
34
|
+
diff_command = 'gh pr diff --name-only'
|
35
|
+
diff_output, _diff_error, _diff_status = Open3.capture3(diff_command, chdir: '.')
|
36
|
+
|
37
|
+
# エラーチェック
|
38
|
+
unless _diff_status.success?
|
39
|
+
puts "Error: Failed to run 'gh pr diff' command."
|
40
|
+
return []
|
41
|
+
end
|
42
|
+
# 取得したdiffのpathを返却する
|
43
|
+
diff_output.split("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def remote_diff_path
|
47
|
+
# リモートのdiffを取得する
|
48
|
+
diff_command = 'git diff --name-only origin/${{ github.event.pull_request.base.ref }}..${{ github.sha }}'
|
49
|
+
diff_output, _diff_error, _diff_status = Open3.capture3(diff_command, chdir: '.')
|
50
|
+
|
51
|
+
# エラーチェック
|
52
|
+
unless _diff_status.success?
|
53
|
+
puts "Error: Failed to run 'git diff' command."
|
54
|
+
return []
|
55
|
+
end
|
56
|
+
|
57
|
+
# 取得したdiffのpathを返却する
|
58
|
+
diff_output.split("\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_spec_file(diff_path)
|
62
|
+
spec_path = File.join('spec', diff_path.gsub(/\.rb$/, '_spec.rb').gsub('app/', ''))
|
63
|
+
File.exist?(spec_path) ? spec_path : nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_spec_file(diff_path, create_spec, perfect)
|
67
|
+
# 対応するSpecファイルが存在した場合のロジック
|
68
|
+
result = {}
|
69
|
+
spec_def_name_arr = []
|
70
|
+
spec_file_path = find_spec_file(diff_path)
|
71
|
+
# スペックファイルがあれば、specfileの中身を確認していく。
|
72
|
+
# defメソッド名だけ切り出す {:call => {code}, :verify => {code}, ....}
|
73
|
+
# ASTを再帰的に探索し、メソッド名とコードを取得
|
74
|
+
get_ast(diff_path).each do |expr|
|
75
|
+
dfs(expr[:ast], expr[:filename], result)
|
76
|
+
end
|
77
|
+
result = result.transform_keys(&:to_s)
|
78
|
+
# describeメソッド [call]
|
79
|
+
# []の中にastが入る
|
80
|
+
get_ast(spec_file_path).each do |expr|
|
81
|
+
spec_def_name_arr = dfs_describe(expr[:ast], expr[:filename], spec_def_name_arr)
|
82
|
+
end
|
83
|
+
|
84
|
+
# resultのHashでSpecが存在するものをTrueに更新
|
85
|
+
spec_def_name_arr.each do |spec_def_name|
|
86
|
+
next unless result.key?(spec_def_name)
|
87
|
+
|
88
|
+
result[spec_def_name] = true
|
89
|
+
|
90
|
+
next unless create_spec
|
91
|
+
|
92
|
+
method_code = result[spec_def_name]
|
93
|
+
puts '==================================================================='
|
94
|
+
puts "#{spec_def_name} のテストを以下に表示します。"
|
95
|
+
puts "We will show the test of #{spec_def_name} below."
|
96
|
+
create_spec_by_bedrock(method_code)
|
97
|
+
end
|
98
|
+
|
99
|
+
get_ignore_methods(diff_path).each do |def_name|
|
100
|
+
result[def_name] = true if result.key?(def_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
return perfect = false if print_result(diff_path, result).size > 0
|
104
|
+
end
|
105
|
+
|
106
|
+
def process_missing_spec_file(diff_path, create_spec, perfect)
|
107
|
+
# 対応するSpecファイルが存在しない場合のロジック
|
108
|
+
result = {}
|
109
|
+
ignored_def_names = get_ignore_methods(diff_path)
|
110
|
+
get_ast(diff_path).each do |expr|
|
111
|
+
dfs(expr[:ast], expr[:filename], result)
|
112
|
+
end
|
113
|
+
result = result.transform_keys(&:to_s)
|
114
|
+
|
115
|
+
ignored_def_names.each do |def_name|
|
116
|
+
result[def_name] = true if result.key?(def_name)
|
117
|
+
end
|
118
|
+
|
119
|
+
if create_spec
|
120
|
+
# exprs[0] の AST からメソッド内のコードを生成
|
121
|
+
ast_code = get_ast(diff_path)[0][:ast]
|
122
|
+
method_code = Unparser.unparse(ast_code)
|
123
|
+
|
124
|
+
puts '==================================================================='
|
125
|
+
puts "#{diff_path} のテストを以下に表示します。"
|
126
|
+
puts "We will show the test of #{diff_path} below."
|
127
|
+
create_spec_by_bedrock(method_code)
|
128
|
+
end
|
129
|
+
return perfect = false if print_result(diff_path, result).size > 0
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def get_ast(diff_path)
|
135
|
+
exprs = []
|
136
|
+
ast = Parser::CurrentRuby.parse(File.read(diff_path))
|
137
|
+
exprs << { ast: ast, filename: diff_path }
|
138
|
+
end
|
139
|
+
|
140
|
+
def dfs(node, filename, result)
|
141
|
+
return unless node.is_a?(Parser::AST::Node)
|
142
|
+
|
143
|
+
# ノードの種類に応じて処理を実行
|
144
|
+
case node.type
|
145
|
+
when :def
|
146
|
+
# :def ノードの場合、メソッド定義に関する処理を実行
|
147
|
+
# ファイル名とメソッド名をつめてます。
|
148
|
+
child_value = node.children[0]
|
149
|
+
code = Unparser.unparse(node)
|
150
|
+
result[child_value] = code
|
151
|
+
end
|
152
|
+
|
153
|
+
# 子ノードに対して再帰的に深さ優先探索
|
154
|
+
node.children.each { |child| dfs(child, filename, result) }
|
155
|
+
end
|
156
|
+
|
157
|
+
# rspecのdescribeでは、通常 # または . の直後に関数名を書くため
|
158
|
+
def get_pure_function_name(str)
|
159
|
+
if str.start_with?('#', '.')
|
160
|
+
str[1..-1] # 2番目以降の文字列を返す
|
161
|
+
else
|
162
|
+
str # 変更が不要な場合はそのまま返す
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def dfs_describe(node, filename, def_name_arr)
|
167
|
+
return unless node.is_a?(Parser::AST::Node)
|
168
|
+
|
169
|
+
# ノードの種類に応じて処理を実行
|
170
|
+
case node.type
|
171
|
+
when :send
|
172
|
+
method_node = node.children[1]
|
173
|
+
if node.children[1] == :describe
|
174
|
+
def_name = node.children[2].children[0] # "Omochi::CLI"
|
175
|
+
if !def_name.nil? && def_name.is_a?(String)
|
176
|
+
def_name = get_pure_function_name(def_name)
|
177
|
+
def_name_arr.push(def_name)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# 子ノードに対して再帰的に深さ優先探索
|
183
|
+
node.children.each { |child| dfs_describe(child, filename, def_name_arr) }
|
184
|
+
def_name_arr
|
185
|
+
end
|
186
|
+
|
187
|
+
def print_result(filename, result)
|
188
|
+
puts "\e[31m======= RESULT: #{filename} =======\e[0m"
|
189
|
+
method_list = result.reject { |_key, value| value == true }.keys
|
190
|
+
method_list.each do |file|
|
191
|
+
puts "- \e[32m#{file}\e[0m"
|
192
|
+
end
|
193
|
+
|
194
|
+
method_list
|
195
|
+
end
|
196
|
+
|
197
|
+
def get_ignore_methods(diff_path)
|
198
|
+
ignore_methods = []
|
199
|
+
code = File.open(diff_path, 'r').read
|
200
|
+
lines = code.split("\n")
|
201
|
+
ignore_next_function = false
|
202
|
+
|
203
|
+
lines.each do |line|
|
204
|
+
if line.match(/omochi:ignore:*/) && line.strip.start_with?('#')
|
205
|
+
ignore_next_function = true
|
206
|
+
next
|
207
|
+
end
|
208
|
+
|
209
|
+
if ignore_next_function && line.match(/\s*def\s+(\w+)/)
|
210
|
+
ignore_methods << Regexp.last_match(1)
|
211
|
+
ignore_next_function = false
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
ignore_methods
|
216
|
+
end
|
217
|
+
|
218
|
+
def create_spec_by_bedrock(code)
|
219
|
+
# 必要な関数だけ渡すのと比較する。
|
220
|
+
bedrock_client = Aws::BedrockRuntime::Client.new(region: 'us-east-1')
|
221
|
+
comment = "You are a brilliant Ruby programmer.
|
222
|
+
You have been assigned to a project to automate QA testing for a system.
|
223
|
+
Please write the Ruby function you want to test inside the <code> XML tags.
|
224
|
+
Write the tests using RSpec to cover all branches of the function comprehensively.
|
225
|
+
Include many test cases to thoroughly verify the function.
|
226
|
+
You must output the test code inside the <test> XML tags absolutely.
|
227
|
+
Do not include any content besides the test code. <code> #{code} </code>"
|
228
|
+
body_data = {
|
229
|
+
"anthropic_version": 'bedrock-2023-05-31',
|
230
|
+
"max_tokens": 4000,
|
231
|
+
"temperature": 0.0,
|
232
|
+
"messages": [
|
233
|
+
{
|
234
|
+
"role": 'user',
|
235
|
+
"content": "#{comment}"
|
236
|
+
}
|
237
|
+
]
|
238
|
+
}
|
239
|
+
response = bedrock_client.invoke_model({
|
240
|
+
accept: '*/*',
|
241
|
+
content_type: 'application/json',
|
242
|
+
body: body_data.to_json,
|
243
|
+
model_id: 'anthropic.claude-3-sonnet-20240229-v1:0'
|
244
|
+
})
|
245
|
+
|
246
|
+
string_io_object = response.body
|
247
|
+
data = JSON.parse(string_io_object.string)
|
248
|
+
code_html = data['content'][0]['text']
|
249
|
+
|
250
|
+
# nokogiri を使用して HTML を解析し、<test> タグの中身を取得
|
251
|
+
doc = Nokogiri::HTML(code_html)
|
252
|
+
code_content = doc.at('test').content.strip
|
253
|
+
|
254
|
+
puts code_content
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
data/lib/omochi.rb
ADDED
data/sig/omochi.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omochi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mikiko.hashino
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-bedrockruntime
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dotenv
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: parser
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
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: thor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
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: unparser
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Omochi is a CLI tool to support Ruby on Rails development with RSpec.
|
112
|
+
email:
|
113
|
+
- mikko.1222.u@gmail.com
|
114
|
+
executables:
|
115
|
+
- omochi
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- DESIGN.md
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- exe/omochi
|
125
|
+
- lib/omochi.rb
|
126
|
+
- lib/omochi/cli.rb
|
127
|
+
- lib/omochi/util.rb
|
128
|
+
- lib/omochi/version.rb
|
129
|
+
- sig/omochi.rbs
|
130
|
+
homepage: https://github.com/mikik0/omochi
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata:
|
134
|
+
homepage_uri: https://github.com/mikik0/omochi
|
135
|
+
source_code_uri: https://github.com/mikik0/omochi
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 2.6.0
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubygems_version: 3.5.11
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: Omochi is a CLI tool to support Ruby on Rails development with RSpec.
|
155
|
+
test_files: []
|