Class: Bddgenx::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/bddgenx/reports/tracer.rb

Overview

Classe responsável por rastrear os artefatos gerados pela gem e exportá-los em arquivos CSV, um por funcionalidade.

Para cada grupo de passos (do ‘.txt`), associa os dados com o cenário equivalente gerado no arquivo `.feature`.

Class Method Summary collapse

Class Method Details

.adicionar_entrada(historia, feature_path) ⇒ void

This method returns an undefined value.

Adiciona entradas de rastreabilidade a um CSV baseado na feature gerada.

  • Cada funcionalidade recebe um arquivo CSV próprio, salvo em: ‘reports/output/funcionalidade_<nome>.csv`

  • A coluna “BDD” contém o cenário completo extraído diretamente do ‘.feature`, preservando a sintaxe original do Gherkin (cenário, steps, tags).

Parameters:

  • historia (Hash)

    Hash representando a história extraída do ‘.txt`, contendo:

    • :quero → nome da funcionalidade

    • :grupos → lista de blocos com :tipo, :tag e :passos

  • feature_path (String)

    Caminho do arquivo ‘.feature` já gerado no sistema



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/bddgenx/reports/tracer.rb', line 38

def self.adicionar_entrada(historia, feature_path)
  FileUtils.mkdir_p('reports/output')

  nome_funcionalidade = historia[:quero].gsub(/^Quero\s*/, '').strip
  nome_funcionalidade_sanitizado = nome_funcionalidade.downcase.gsub(/[^a-z0-9]+/, '_')
  arquivo_csv = "reports/output/funcionalidade_#{nome_funcionalidade_sanitizado}.csv"

  cabecalho = ['Funcionalidade', 'Tipo', 'Tag', 'Cenário', 'Passo', 'Origem', 'BDD']
  linhas = []

  # Leitura real da feature gerada
  blocos_gherkin = extrair_cenarios_gherkin(feature_path)

  historia[:grupos].each_with_index do |grupo, idx|
    tipo  = grupo[:tipo]
    tag   = grupo[:tag] || '-'
    passos = grupo[:passos] || []
    nome_cenario = "Cenário #{idx + 1}"

    # Bloco Gherkin real do cenário gerado
    gherkin_bloco = blocos_gherkin[idx] || ''

    passos.each do |passo|
      linhas << [
        nome_funcionalidade,
        tipo,
        tag,
        nome_cenario,
        passo,
        File.basename(feature_path),
        gherkin_bloco
      ]
    end
  end

  escrever_csv(arquivo_csv, cabecalho, linhas)
end

.escrever_csv(caminho, cabecalho, novas_linhas) ⇒ void

This method returns an undefined value.

Escreve ou anexa dados em um arquivo CSV.

  • Cria o cabeçalho caso seja a primeira escrita.

  • Evita duplicações com base na combinação “Passo + Origem”.

Parameters:

  • caminho (String)

    Caminho completo do arquivo CSV a ser salvo

  • cabecalho (Array<String>)

    Títulos das colunas do CSV

  • novas_linhas (Array<Array>)

    Linhas de conteúdo a serem gravadas



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/bddgenx/reports/tracer.rb', line 86

def self.escrever_csv(caminho, cabecalho, novas_linhas)
  novo_arquivo = !File.exist?(caminho)

  existentes = []
  if File.exist?(caminho)
    existentes = CSV.read(caminho, col_sep: ';', headers: true).map do |row|
      [row['Passo'], row['Origem']]
    end
  end

  CSV.open(caminho, 'a+', col_sep: ';', force_quotes: true) do |csv|
    csv << cabecalho if novo_arquivo

    novas_linhas.each do |linha|
      passo, origem = linha[4], linha[5]
      next if existentes.include?([passo, origem])
      csv << linha
    end
  end
end

.extrair_cenarios_gherkin(feature_path) ⇒ Array<String>

Extrai todos os cenários completos do arquivo ‘.feature` gerado, preservando a estrutura Gherkin original (cenários, tags, steps).

Um novo bloco é iniciado quando uma das palavras-chave de título de cenário é encontrada.

Parameters:

  • feature_path (String)

    Caminho completo do arquivo ‘.feature`

Returns:

  • (Array<String>)

    Lista de blocos Gherkin, um por cenário



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/bddgenx/reports/tracer.rb', line 116

def self.extrair_cenarios_gherkin(feature_path)
  return [] unless File.exist?(feature_path)

  content = File.read(feature_path)
  linhas = content.lines

  blocos = []
  bloco_atual = []
  capturando = false

  linhas.each_with_index do |linha, i|
    if linha.strip =~ /^(Scenario|Scenario Outline|Cenário|Esquema do Cenário):/i
      # Novo cenário → salva anterior
      blocos << bloco_atual.join if bloco_atual.any?
      bloco_atual = [linha]
      capturando = true
    elsif capturando
      bloco_atual << linha
    end
  end

  blocos << bloco_atual.join if bloco_atual.any?
  blocos
end