bddgenx 1.0.0 → 2.1.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/README.md +146 -28
- data/Rakefile +33 -39
- data/VERSION +1 -1
- data/bin/bddgenx +1 -1
- data/lib/bddgenx/configuration.rb +35 -0
- data/lib/bddgenx/{generator.rb → generators/generator.rb} +42 -18
- data/lib/bddgenx/{runner.rb → generators/runner.rb} +9 -29
- data/lib/bddgenx/{steps_generator.rb → generators/steps_generator.rb} +27 -5
- data/lib/bddgenx/ia/chatgtp_cliente.rb +147 -0
- data/lib/bddgenx/ia/gemini_cliente.rb +27 -12
- data/lib/bddgenx/{utils → reports}/backup.rb +0 -4
- data/lib/bddgenx/{utils → reports}/pdf_exporter.rb +0 -5
- data/lib/bddgenx/{utils → reports}/tracer.rb +0 -4
- data/lib/bddgenx/{utils → support}/font_loader.rb +0 -4
- data/lib/bddgenx/support/gherkin_cleaner.rb +102 -0
- data/lib/bddgenx/support/remover_steps_duplicados.rb +81 -0
- data/lib/bddgenx/{utils → support}/validator.rb +0 -1
- data/lib/bddgenx/version.rb +4 -1
- data/lib/bddgenx.rb +11 -2
- data/lib/env.rb +51 -0
- data/lib/{bddgenx/utils/parser.rb → parser.rb} +1 -3
- metadata +71 -13
- data/lib/bddgenx/ia/gemini_generator.rb +0 -127
- data/lib/bddgenx/utils/gherkin_cleaner.rb +0 -57
- data/lib/bddgenx/utils/remover_steps_duplicados.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc08ad6528e8d4134da51f3f5b1adb28f58f23b0774f75c5b909532a89ffcf94
|
4
|
+
data.tar.gz: 93e5e417b5a8ccdda7f1b9e32be61079fcd4d42bf56fd0f17a2cf7d7cdbe30ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f89ff60aa9af4fc6fe1b81b95420b7a2c434aa1c746125f62ef4a164e8207352352ad398904541af5906750c01fd50f3f811c66eb35f684004b9ce1764fb37f2
|
7
|
+
data.tar.gz: d4ff2d93180bbde669cf4f9cb6bba2ace91b65d46d9a19c7cfb8c901074df5c592d6b7b2c3704c69d6ad610c847e13fb5dfb52034c0f3cccb778a582cdb8858a
|
data/README.md
CHANGED
@@ -3,7 +3,78 @@
|
|
3
3
|
|
4
4
|
## Visão Geral
|
5
5
|
|
6
|
-
Ferramenta Ruby para gerar automaticamente arquivos Gherkin (`.feature`) e definições de passos (`steps.rb`) a partir de histórias em texto. Atende aos padrões ISTQB, suporta parametrização com blocos de exemplos e fornece relatórios de QA (rastreabilidade, backups e PDF).
|
6
|
+
Ferramenta Ruby para gerar automaticamente arquivos Gherkin (`.feature`) e definições de passos (`steps.rb`) a partir de histórias em texto. Atende aos padrões ISTQB, suporta parametrização com blocos de exemplos e fornece relatórios de QA (rastreabilidade, backups e PDF). Também suporta geração via IA (OpenAI / Gemini) e configuração por ambiente.
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
## Estrutura do Projeto
|
11
|
+
|
12
|
+
```
|
13
|
+
bdd-generation/
|
14
|
+
├── .github/ # Workflows de CI/CD
|
15
|
+
│ └── workflows/
|
16
|
+
│ └── main.yml # Workflow de build/test
|
17
|
+
├── bin/ # Scripts CLI e de configuração
|
18
|
+
│ ├── bddgenx # Executável CLI para gerar BDD (static/chatgpt/gemini)
|
19
|
+
│ └── setup.rb # Script para preparar o ambiente local (gera .env, input/)
|
20
|
+
├── features/ # Gherkin gerados automaticamente
|
21
|
+
│ └── steps/ # Steps correspondentes aos cenários
|
22
|
+
├── input/ # Arquivos de entrada (.txt com histórias)
|
23
|
+
│ ├── historia.txt
|
24
|
+
│ ├── historia_en.txt
|
25
|
+
│ └── ...
|
26
|
+
├── lib/
|
27
|
+
│ ├── bddgenx/
|
28
|
+
│ │ ├── generators/ # Lógica de geração de features e execução geral
|
29
|
+
│ │ │ ├── generator.rb
|
30
|
+
│ │ │ ├── steps_generator.rb
|
31
|
+
│ │ │ └── runner.rb
|
32
|
+
│ │ │
|
33
|
+
│ │ ├── ia/ # Integração com APIs de IA
|
34
|
+
│ │ │ ├── chatgpt_cliente.rb
|
35
|
+
│ │ │ └── gemini_cliente.rb
|
36
|
+
│ │ │
|
37
|
+
│ │ ├── reports/ # Exportação de artefatos QA
|
38
|
+
│ │ │ ├── backup.rb
|
39
|
+
│ │ │ ├── pdf_exporter.rb
|
40
|
+
│ │ │ └── tracer.rb
|
41
|
+
│ │ │
|
42
|
+
│ │ ├── support/ # Utilitários auxiliares e validadores
|
43
|
+
│ │ │ ├── font_loader.rb
|
44
|
+
│ │ │ ├── gherkin_cleaner.rb
|
45
|
+
│ │ │ ├── remover_steps_duplicados.rb
|
46
|
+
│ │ │ └── validator.rb
|
47
|
+
│ │ │
|
48
|
+
│ │ ├── configuration.rb # Configuração global da gem (modo, ENV keys)
|
49
|
+
│ │ └── version.rb # Leitura da versão a partir do arquivo VERSION
|
50
|
+
│ │
|
51
|
+
│ ├── bddgenx.rb # Entrada principal da gem (require env)
|
52
|
+
│ └── parser.rb # Parser de arquivos de entrada
|
53
|
+
├── reports/ # Artefatos gerados
|
54
|
+
│ ├── pdf/ # Features exportadas em PDF
|
55
|
+
│ ├── backup/ # Versões antigas de features
|
56
|
+
│ └── rastreabilidade/ # Arquivos de rastreabilidade (se implementado)
|
57
|
+
├── spec/ # Testes unitários RSpec
|
58
|
+
│ ├── support/
|
59
|
+
│ ├── utils/
|
60
|
+
│ ├── ia/
|
61
|
+
│ ├── spec_helper.rb
|
62
|
+
│ └── version_spec.rb
|
63
|
+
├── .env # Arquivo com chaves reais (não versionado)
|
64
|
+
├── .env.example # Modelo para configurar variáveis de ambiente
|
65
|
+
├── .gitignore # Arquivos/pastas ignoradas pelo Git
|
66
|
+
├── bddgenx.gemspec # Especificação da gem
|
67
|
+
├── bump_version.sh # Script de versionamento automático (semântico)
|
68
|
+
├── Gemfile
|
69
|
+
├── Gemfile.lock
|
70
|
+
├── LICENSE
|
71
|
+
├── Rakefile # Tarefas automatizadas (static, chatgpt, gemini)
|
72
|
+
├── README.md # Documentação principal do projeto
|
73
|
+
└── VERSION # Arquivo contendo a versão atual da gem
|
74
|
+
|
75
|
+
```
|
76
|
+
|
77
|
+
---
|
7
78
|
|
8
79
|
## Instalação
|
9
80
|
|
@@ -13,44 +84,70 @@ Adicione ao seu `Gemfile`:
|
|
13
84
|
gem 'bddgenx'
|
14
85
|
```
|
15
86
|
|
16
|
-
|
87
|
+
Ou instale diretamente:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
gem install bddgenx
|
91
|
+
```
|
92
|
+
|
93
|
+
---
|
94
|
+
|
95
|
+
## 🔧 Configuração
|
96
|
+
|
97
|
+
### 1. Instale dependências
|
17
98
|
|
18
99
|
```bash
|
19
100
|
bundle install
|
20
101
|
```
|
21
102
|
|
22
|
-
|
103
|
+
### 2. Configure seu `.env`
|
23
104
|
|
24
105
|
```bash
|
25
|
-
|
106
|
+
cp .env.example .env
|
26
107
|
```
|
27
108
|
|
28
|
-
|
109
|
+
Edite o `.env`:
|
29
110
|
|
30
|
-
```
|
31
|
-
|
111
|
+
```env
|
112
|
+
OPENAI_API_KEY=sk-...
|
113
|
+
GEMINI_API_KEY=ya29-...
|
114
|
+
BDDGENX_MODE=chatgpt # static | chatgpt | gemini
|
115
|
+
```
|
32
116
|
|
33
|
-
|
34
|
-
|
117
|
+
> 🔐 Dica: nunca versionar o `.env` — ele já está no `.gitignore`
|
118
|
+
|
119
|
+
---
|
120
|
+
|
121
|
+
## 🚀 Uso com Rake
|
122
|
+
|
123
|
+
Com os arquivos `.txt` dentro da pasta `input/`, execute:
|
124
|
+
|
125
|
+
```bash
|
126
|
+
rake bddgenx:static # geração sem IA
|
127
|
+
rake bddgenx:chatgpt # usando ChatGPT
|
128
|
+
rake bddgenx:gemini # usando Gemini
|
35
129
|
```
|
36
130
|
|
37
|
-
|
131
|
+
> O modo pode ser sobrescrito via ENV ou `Bddgenx.configure`
|
132
|
+
|
133
|
+
---
|
38
134
|
|
39
|
-
|
135
|
+
## 📦 Geração manual via Ruby
|
40
136
|
|
41
137
|
```ruby
|
42
138
|
require 'bddgenx'
|
43
|
-
require 'rake'
|
44
139
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Bddgenx::Runner.execute
|
49
|
-
end
|
140
|
+
Bddgenx.configure do |config|
|
141
|
+
config.mode = :chatgpt
|
142
|
+
config.openai_api_key_env = 'OPENAI_API_KEY'
|
50
143
|
end
|
144
|
+
|
145
|
+
Bddgenx::Runner.execute
|
51
146
|
```
|
52
147
|
|
53
|
-
|
148
|
+
---
|
149
|
+
|
150
|
+
## 📝 Formato do Arquivo de Entrada (`.txt`)
|
54
151
|
|
55
152
|
```txt
|
56
153
|
# language: pt
|
@@ -63,19 +160,36 @@ Quando preencho <email> e <senha>
|
|
63
160
|
Então vejo a tela inicial
|
64
161
|
|
65
162
|
[EXAMPLES]
|
66
|
-
| email | senha |
|
67
|
-
| user@site.com | 123456 |
|
68
|
-
| errado@site.com | senha |
|
163
|
+
| email | senha |
|
164
|
+
| user@site.com | 123456 |
|
165
|
+
| errado@site.com | senha |
|
69
166
|
```
|
70
167
|
|
71
|
-
|
168
|
+
---
|
72
169
|
|
73
|
-
|
74
|
-
* **PDF**: exporta features em P/B para `reports/pdf` via `PDFExporter`
|
170
|
+
## 🧪 Setup Rápido para Novos Usuários
|
75
171
|
|
76
|
-
|
172
|
+
```bash
|
173
|
+
ruby bin/setup.rb
|
174
|
+
```
|
175
|
+
|
176
|
+
Esse comando:
|
177
|
+
|
178
|
+
- Cria `.env` a partir de `.env.example`
|
179
|
+
- Garante que `input/` existe
|
180
|
+
|
181
|
+
---
|
77
182
|
|
78
|
-
|
183
|
+
## 🧾 Artefatos Gerados
|
184
|
+
|
185
|
+
- ✅ `.feature` → dentro de `features/`
|
186
|
+
- ✅ `steps.rb` → dentro de `features/steps/`
|
187
|
+
- 🗂️ Backup automático → `reports/backup/`
|
188
|
+
- 📄 PDF das features → `reports/pdf/`
|
189
|
+
|
190
|
+
---
|
191
|
+
|
192
|
+
## ⚙️ CI/CD Exemplo com GitHub Actions
|
79
193
|
|
80
194
|
```yaml
|
81
195
|
jobs:
|
@@ -85,11 +199,15 @@ jobs:
|
|
85
199
|
- uses: actions/checkout@v3
|
86
200
|
- uses: ruby/setup-ruby@v1
|
87
201
|
with:
|
88
|
-
ruby-version: '3.
|
202
|
+
ruby-version: '3.1'
|
89
203
|
- run: bundle install
|
90
|
-
- run: bundle exec
|
204
|
+
- run: bundle exec rake bddgenx:chatgpt
|
205
|
+
env:
|
206
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
91
207
|
```
|
92
208
|
|
209
|
+
---
|
210
|
+
|
93
211
|
## Licença
|
94
212
|
|
95
213
|
MIT © 2025 David Nascimento
|
data/Rakefile
CHANGED
@@ -1,55 +1,49 @@
|
|
1
1
|
# Rakefile
|
2
|
-
|
3
|
-
|
2
|
+
require_relative 'lib/env'
|
4
3
|
require 'rake'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'bddgenx'
|
7
4
|
|
8
5
|
namespace :bddgenx do
|
9
|
-
desc '
|
10
|
-
task :
|
11
|
-
|
12
|
-
|
13
|
-
only_new = args.only_new == 'true'
|
14
|
-
input_dir = args.input_dir
|
15
|
-
|
16
|
-
files = FileList["#{input_dir}/*.txt"]
|
17
|
-
if files.empty?
|
18
|
-
puts "❌ Nenhum arquivo encontrado em \#{input_dir}"
|
19
|
-
next
|
20
|
-
end
|
6
|
+
desc 'Inicializar projeto'
|
7
|
+
task :setup do
|
8
|
+
Bddgenx::Setup.inicializar_projeto
|
9
|
+
end
|
21
10
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
next unless Bddgenx::Validator.validar(historia)
|
11
|
+
desc 'Executa a geração BDD usando o modo atual (static, chatgpt, gemini)'
|
12
|
+
task :generate do
|
13
|
+
puts "⚙️ Modo de geração: #{Bddgenx.configuration.mode}"
|
26
14
|
|
27
|
-
|
15
|
+
# Evita que ARGV contenha o nome da task (como "bddgenx:static")
|
16
|
+
ARGV.clear
|
28
17
|
|
29
|
-
|
30
|
-
|
18
|
+
Bddgenx::Runner.execute
|
19
|
+
end
|
31
20
|
|
32
|
-
|
33
|
-
|
21
|
+
desc 'Gera features no modo estático (sem IA)'
|
22
|
+
task :static do
|
23
|
+
Bddgenx.configure do |config|
|
24
|
+
config.mode = :static
|
34
25
|
end
|
35
|
-
|
36
|
-
|
26
|
+
ENV['BDDGENX_MODE'] = 'static'
|
27
|
+
Rake::Task['bddgenx:generate'].invoke
|
37
28
|
end
|
38
29
|
|
39
|
-
desc '
|
40
|
-
task :
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
desc 'Gera features usando ChatGPT'
|
31
|
+
task :chatgpt do
|
32
|
+
Bddgenx.configure do |config|
|
33
|
+
config.mode = :chatgpt
|
34
|
+
config.openai_api_key_env = 'OPENAI_API_KEY'
|
35
|
+
end
|
36
|
+
ENV['BDDGENX_MODE'] = 'chatgpt'
|
37
|
+
Rake::Task['bddgenx:generate'].invoke
|
44
38
|
end
|
45
39
|
|
46
|
-
desc '
|
47
|
-
task :
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
desc 'Gera features usando Gemini'
|
41
|
+
task :gemini do
|
42
|
+
Bddgenx.configure do |config|
|
43
|
+
config.mode = :gemini
|
44
|
+
config.gemini_api_key_env = 'GEMINI_API_KEY'
|
51
45
|
end
|
46
|
+
ENV['BDDGENX_MODE'] = 'gemini'
|
47
|
+
Rake::Task['bddgenx:generate'].invoke
|
52
48
|
end
|
53
49
|
end
|
54
|
-
|
55
|
-
task default: 'bddgenx:gerar'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
2.1.0
|
data/bin/bddgenx
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# lib/bddgenx/configuration.rb
|
2
|
+
module Bddgenx
|
3
|
+
class Configuration
|
4
|
+
# :static, :chatgpt ou :gemini
|
5
|
+
attr_accessor :mode
|
6
|
+
|
7
|
+
# Nomes das ENV vars para as chaves
|
8
|
+
attr_accessor :openai_api_key_env, :gemini_api_key_env
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@mode = :static
|
12
|
+
@openai_api_key_env = 'OPENAI_API_KEY'
|
13
|
+
@gemini_api_key_env = 'GEMINI_API_KEY'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Retorna a chave real, carregada do ENV
|
17
|
+
def openai_api_key
|
18
|
+
ENV[@openai_api_key_env]
|
19
|
+
end
|
20
|
+
|
21
|
+
def gemini_api_key
|
22
|
+
ENV[@gemini_api_key_env]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Singleton de configuração
|
27
|
+
def self.configuration
|
28
|
+
@configuration ||= Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
# DSL para configurar
|
32
|
+
def self.configure
|
33
|
+
yield(configuration)
|
34
|
+
end
|
35
|
+
end
|
@@ -6,30 +6,45 @@
|
|
6
6
|
# Suporta Gherkin em Português e Inglês, inclusão de tags, cenários simples
|
7
7
|
# e esquemas de cenário com exemplos.
|
8
8
|
|
9
|
-
require 'fileutils'
|
10
|
-
require 'set'
|
11
|
-
require_relative 'utils/gherkin_cleaner'
|
12
|
-
require_relative 'ia/gemini_cliente'
|
13
|
-
require_relative 'utils/remover_steps_duplicados'
|
14
|
-
# require_relative 'clients/chatgpt_cliente'
|
15
|
-
|
16
9
|
module Bddgenx
|
17
10
|
class Generator
|
11
|
+
# Palavras-chave do Gherkin em Português
|
18
12
|
GHERKIN_KEYS_PT = %w[Dado Quando Então E Mas].freeze
|
13
|
+
|
14
|
+
# Palavras-chave do Gherkin em Inglês
|
19
15
|
GHERKIN_KEYS_EN = %w[Given When Then And But].freeze
|
16
|
+
|
17
|
+
# Mapeamento de PT → EN
|
20
18
|
GHERKIN_MAP_PT_EN = GHERKIN_KEYS_PT.zip(GHERKIN_KEYS_EN).to_h
|
19
|
+
|
20
|
+
# Mapeamento de EN → PT
|
21
21
|
GHERKIN_MAP_EN_PT = GHERKIN_KEYS_EN.zip(GHERKIN_KEYS_PT).to_h
|
22
|
+
|
23
|
+
# Todas as palavras-chave reconhecidas
|
22
24
|
ALL_KEYS = GHERKIN_KEYS_PT + GHERKIN_KEYS_EN
|
23
25
|
|
26
|
+
##
|
27
|
+
# Extrai todas as linhas de exemplo de um array de strings.
|
28
|
+
#
|
29
|
+
# @param raw [Array<String>] um array contendo linhas de texto
|
30
|
+
# @return [Array<String>] apenas as linhas que começam com '|', ou seja, exemplos
|
24
31
|
def self.dividir_examples(raw)
|
25
32
|
raw.select { |l| l.strip.start_with?('|') }
|
26
33
|
end
|
27
34
|
|
35
|
+
##
|
36
|
+
# Gera o conteúdo de um arquivo `.feature` a partir de uma história.
|
37
|
+
# Pode operar em três modos: estático (hash ou arquivo estruturado),
|
38
|
+
# IA com Gemini, ou IA com ChatGPT.
|
39
|
+
#
|
40
|
+
# @param input [String, Hash] caminho para um arquivo .txt ou um hash estruturado
|
41
|
+
# @param override_path [String, nil] caminho alternativo para salvar o arquivo gerado
|
42
|
+
# @return [Array(String, String)] caminho do arquivo gerado e conteúdo do .feature
|
28
43
|
def self.gerar_feature(input, override_path = nil)
|
29
44
|
modo = ENV['BDD_MODE']&.to_sym || :static
|
30
45
|
|
31
|
-
# IA: Lê o arquivo txt e passa para IA → aplica limpeza
|
32
46
|
if input.is_a?(String) && input.end_with?('.txt') && [:gemini, :chatgpt].include?(modo)
|
47
|
+
# Modo com IA: gera cenários automaticamente com base no texto da história
|
33
48
|
raw_txt = File.read(input)
|
34
49
|
historia = {
|
35
50
|
idioma: 'pt',
|
@@ -50,15 +65,15 @@ module Bddgenx
|
|
50
65
|
tag: 'ia',
|
51
66
|
passos: GherkinCleaner.limpar(texto_gerado).lines.map(&:strip).reject(&:empty?)
|
52
67
|
}
|
53
|
-
|
54
68
|
else
|
55
|
-
#
|
69
|
+
# Modo estático: utiliza estrutura vinda do Parser ou de um hash diretamente
|
56
70
|
historia = input.is_a?(String) ? Parser.ler_historia(input) : input
|
57
71
|
end
|
58
72
|
|
59
73
|
idioma = historia[:idioma] || 'pt'
|
60
74
|
cont = 1
|
61
75
|
|
76
|
+
# Normaliza o nome base do arquivo
|
62
77
|
nome_base = historia[:quero]
|
63
78
|
.gsub(/[^a-z0-9]/i, '_')
|
64
79
|
.downcase
|
@@ -69,6 +84,7 @@ module Bddgenx
|
|
69
84
|
|
70
85
|
caminho = override_path || "features/#{nome_base}.feature"
|
71
86
|
|
87
|
+
# Define palavras-chave com base no idioma
|
72
88
|
palavras = {
|
73
89
|
feature: idioma == 'en' ? 'Feature' : 'Funcionalidade',
|
74
90
|
contexto: idioma == 'en' ? 'Background' : 'Contexto',
|
@@ -79,15 +95,13 @@ module Bddgenx
|
|
79
95
|
}
|
80
96
|
|
81
97
|
conteudo = <<~GHK
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
98
|
+
# language: #{idioma}
|
99
|
+
#{palavras[:feature]}: #{historia[:quero].sub(/^Quero\s*/i,'')}
|
100
|
+
# #{historia[:como]}
|
101
|
+
# #{historia[:quero]}
|
102
|
+
# #{historia[:para]}
|
88
103
|
GHK
|
89
104
|
|
90
|
-
# Set para rastrear steps únicos
|
91
105
|
passos_unicos = Set.new
|
92
106
|
pt_map = GHERKIN_MAP_PT_EN
|
93
107
|
en_map = GHERKIN_MAP_EN_PT
|
@@ -100,7 +114,6 @@ module Bddgenx
|
|
100
114
|
next if passos.empty?
|
101
115
|
|
102
116
|
tag_line = ["@#{grupo[:tipo].downcase}", ("@#{grupo[:tag]}" if grupo[:tag])].compact.join(' ')
|
103
|
-
|
104
117
|
conteudo << " #{tag_line}\n"
|
105
118
|
|
106
119
|
if exemplos.any?
|
@@ -137,11 +150,22 @@ module Bddgenx
|
|
137
150
|
[caminho, conteudo]
|
138
151
|
end
|
139
152
|
|
153
|
+
##
|
154
|
+
# Gera o caminho padrão de saída para um arquivo `.feature` com base no nome do `.txt`.
|
155
|
+
#
|
156
|
+
# @param arquivo_txt [String] caminho do arquivo .txt de entrada
|
157
|
+
# @return [String] caminho completo do arquivo .feature correspondente
|
140
158
|
def self.path_para_feature(arquivo_txt)
|
141
159
|
nome = File.basename(arquivo_txt, '.txt')
|
142
160
|
File.join('features', "#{nome}.feature")
|
143
161
|
end
|
144
162
|
|
163
|
+
##
|
164
|
+
# Salva o conteúdo gerado no disco, criando diretórios se necessário.
|
165
|
+
#
|
166
|
+
# @param caminho [String] caminho completo para salvar o arquivo
|
167
|
+
# @param conteudo [String] conteúdo do arquivo .feature
|
168
|
+
# @return [void]
|
145
169
|
def self.salvar_feature(caminho, conteudo)
|
146
170
|
FileUtils.mkdir_p(File.dirname(caminho))
|
147
171
|
File.write(caminho, conteudo)
|
@@ -4,16 +4,7 @@
|
|
4
4
|
# Este arquivo define a classe Runner (CLI) da gem bddgenx,
|
5
5
|
# responsável por orquestrar o fluxo de leitura de histórias,
|
6
6
|
# validação, geração de features, steps, backups e exportação de PDFs.
|
7
|
-
|
8
|
-
require 'fileutils'
|
9
|
-
require_relative 'utils/parser'
|
10
|
-
require_relative 'generator'
|
11
|
-
require_relative 'utils/pdf_exporter'
|
12
|
-
require_relative 'steps_generator'
|
13
|
-
require_relative 'utils/validator'
|
14
|
-
require_relative 'utils/backup'
|
15
|
-
require_relative 'ia/gemini_cliente'
|
16
|
-
require_relative 'utils/gherkin_cleaner'
|
7
|
+
require_relative '../../bddgenx'
|
17
8
|
|
18
9
|
module Bddgenx
|
19
10
|
# Ponto de entrada da gem: coordena todo o processo de geração BDD.
|
@@ -110,26 +101,15 @@ module Bddgenx
|
|
110
101
|
end
|
111
102
|
|
112
103
|
# Geração de feature
|
113
|
-
if modo == 'gemini'
|
114
|
-
puts "🤖 Gerando cenários com IA (
|
115
|
-
idioma = IA::GeminiCliente.detecta_idioma_arquivo(arquivo)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
sleep(0.4)
|
122
|
-
print "\r⏳ Aguardando resposta da IA#{'.' * (i + 1)} "
|
123
|
-
end
|
104
|
+
if modo == 'gemini' || modo == 'chatgpt'
|
105
|
+
puts "🤖 Gerando cenários com IA (#{modo.capitalize})..."
|
106
|
+
idioma = IA::GeminiCliente.detecta_idioma_arquivo(arquivo)
|
107
|
+
feature_text =
|
108
|
+
if modo == 'gemini'
|
109
|
+
IA::GeminiCliente.gerar_cenarios(historia, idioma)
|
110
|
+
else
|
111
|
+
IA::ChatGptCliente.gerar_cenarios(historia, idioma)
|
124
112
|
end
|
125
|
-
end
|
126
|
-
begin
|
127
|
-
feature_text = IA::GeminiCliente.gerar_cenarios(historia, idioma)
|
128
|
-
ensure
|
129
|
-
Thread.kill(spinner)
|
130
|
-
print "\r✅ Resposta da IA recebida! \n"
|
131
|
-
end
|
132
|
-
# feature_text = IA::GeminiCliente.gerar_cenarios(historia, idioma)
|
133
113
|
if feature_text
|
134
114
|
feature_path = Generator.path_para_feature(arquivo)
|
135
115
|
feature_content = Bddgenx::GherkinCleaner.limpar(feature_text)
|
@@ -6,26 +6,45 @@
|
|
6
6
|
# Suporta palavras-chave Gherkin em Português e Inglês e parametriza
|
7
7
|
# strings e números conforme necessário.
|
8
8
|
|
9
|
-
require 'fileutils'
|
10
|
-
require 'strscan' # Para uso de StringScanner
|
11
|
-
require 'set'
|
12
|
-
|
13
9
|
module Bddgenx
|
14
10
|
class StepsGenerator
|
11
|
+
# Palavras-chave Gherkin em Português
|
15
12
|
GHERKIN_KEYS_PT = %w[Dado Quando Então E Mas].freeze
|
13
|
+
|
14
|
+
# Palavras-chave Gherkin em Inglês
|
16
15
|
GHERKIN_KEYS_EN = %w[Given When Then And But].freeze
|
16
|
+
|
17
|
+
# Conjunto de todas as palavras-chave suportadas
|
17
18
|
ALL_KEYS = GHERKIN_KEYS_PT + GHERKIN_KEYS_EN
|
18
19
|
|
20
|
+
##
|
21
|
+
# Transforma uma string em estilo camelCase.
|
22
|
+
#
|
23
|
+
# @param str [String] A string a ser transformada.
|
24
|
+
# @return [String] A string convertida para camelCase.
|
25
|
+
#
|
19
26
|
def self.camelize(str)
|
20
27
|
partes = str.strip.split(/[^a-zA-Z0-9]+/)
|
21
28
|
partes.map.with_index { |palavra, i| i.zero? ? palavra.downcase : palavra.capitalize }.join
|
22
29
|
end
|
23
30
|
|
31
|
+
##
|
32
|
+
# Gera arquivos de passos do Cucumber a partir de um arquivo .feature.
|
33
|
+
#
|
34
|
+
# O método lê o arquivo, detecta o idioma, extrai os passos,
|
35
|
+
# parametriza as variáveis (números e strings), e escreve os métodos
|
36
|
+
# em um novo arquivo no diretório `steps/`.
|
37
|
+
#
|
38
|
+
# @param feature_path [String] Caminho para o arquivo .feature.
|
39
|
+
# @return [Boolean] Retorna true se os passos forem gerados com sucesso, false se não houver passos.
|
40
|
+
# @raise [ArgumentError] Se o caminho fornecido não for uma String.
|
41
|
+
#
|
24
42
|
def self.gerar_passos(feature_path)
|
25
43
|
raise ArgumentError, "Caminho esperado como String, recebeu #{feature_path.class}" unless feature_path.is_a?(String)
|
26
44
|
|
27
45
|
linhas = File.readlines(feature_path)
|
28
46
|
|
47
|
+
# Detecta o idioma com base na diretiva "# language:"
|
29
48
|
lang = if (m = linhas.find { |l| l =~ /^#\s*language:\s*(\w+)/i })
|
30
49
|
m[/^#\s*language:\s*(\w+)/i, 1].downcase
|
31
50
|
else
|
@@ -35,6 +54,7 @@ module Bddgenx
|
|
35
54
|
pt_para_en = GHERKIN_KEYS_PT.zip(GHERKIN_KEYS_EN).to_h
|
36
55
|
en_para_pt = GHERKIN_KEYS_EN.zip(GHERKIN_KEYS_PT).to_h
|
37
56
|
|
57
|
+
# Seleciona apenas linhas que começam com palavras-chave Gherkin
|
38
58
|
linhas_passos = linhas.map(&:strip).select do |linha|
|
39
59
|
ALL_KEYS.any? { |chave| linha.start_with?(chave + ' ') }
|
40
60
|
end
|
@@ -53,6 +73,7 @@ module Bddgenx
|
|
53
73
|
linhas_passos.each do |linha|
|
54
74
|
palavra_original, restante = linha.split(' ', 2)
|
55
75
|
|
76
|
+
# Tradução de palavras-chave se necessário
|
56
77
|
chave = case lang
|
57
78
|
when 'en' then pt_para_en[palavra_original] || palavra_original
|
58
79
|
else en_para_pt[palavra_original] || palavra_original
|
@@ -63,6 +84,7 @@ module Bddgenx
|
|
63
84
|
padrao = ''
|
64
85
|
tokens = []
|
65
86
|
|
87
|
+
# Analisa e parametriza o conteúdo dos passos
|
66
88
|
until scanner.eos?
|
67
89
|
if scanner.check(/"<([^>]+)>"/)
|
68
90
|
scanner.scan(/"<([^>]+)>"/)
|
@@ -87,7 +109,7 @@ module Bddgenx
|
|
87
109
|
|
88
110
|
padrao_seguro = padrao.gsub('"', '\\"')
|
89
111
|
|
90
|
-
# Impede
|
112
|
+
# Impede criação de métodos duplicados
|
91
113
|
next if passos_unicos.include?(padrao_seguro)
|
92
114
|
|
93
115
|
passos_unicos << padrao_seguro
|