appium_failure_helper 0.6.6 → 0.6.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af82bef9bc09a790faa2882a886325c2da1ae7cfbd4a25541b0025f0bb9bb479
4
- data.tar.gz: 3fe174544dba0f9453d017900968fa84f07444337b4d910648f289a81e5fa5ef
3
+ metadata.gz: a599f36b97e9ca76cfe763ad26526ea1b80e829128e95667b1020bf29cb9cb41
4
+ data.tar.gz: 58f249a54a0410b9927bbb14b4551375cd77de49eb35db282cad16a9e0b7817d
5
5
  SHA512:
6
- metadata.gz: 1c338bf9158ab769f74dbaa3be08a42581b8bcacdd997d61a27751a0cc5e4b349888e02124d8c70a2395643e46486e6213444e99a1b7222d231ed3ece9170cd4
7
- data.tar.gz: fb6f836aa0ed1b947658b787fff8768cfff589356440137265d7cf8ffd3a8e33664c298e881fa1b1b2850c691f5df9434a71cbd602fc7b1b058677eccf51741e
6
+ metadata.gz: b9c4ab54799677d260fa7939705fc074a2e9233026b696d2d4548da344b0464f8dcbbda5016a735939819e04c2b06e700ed14d23cde1c8ac55cbfb844cae9b10
7
+ data.tar.gz: d076e206ca68bd47560a95162428b1dc090df4890934f535de0c68f98b17206adb7229980175c1773dd542e65ac01dd9accbf4da83104cbb68ad893c0df773e0
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Diagnóstico Inteligente de Falhas Appium
2
2
 
3
3
  ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
4
- ![Gem Version](https://img.shields.io/badge/gem-v1.0.0-blue)
4
+ ![Gem Version](https://img.shields.io/badge/gem-v1.1.0-blue)
5
5
  ![License](https://img.shields.io/badge/license-MIT-lightgrey)
6
6
 
7
7
  Uma ferramenta robusta para diagnosticar falhas em testes automatizados com Appium, transformando erros de `NoSuchElementException` em relatórios interativos e inteligentes. Chega de perder tempo depurando seletores quebrados; deixe que a análise automatizada faça o trabalho pesado por você.
@@ -10,9 +10,10 @@ Uma ferramenta robusta para diagnosticar falhas em testes automatizados com Appi
10
10
 
11
11
  * **Relatório HTML Interativo:** Gera um relatório visual completo a cada falha, com screenshot, análise detalhada e dump de todos os elementos da tela.
12
12
  * **Análise de Mapeamento ("De/Para"):** Verifica automaticamente se o elemento que falhou está definido em alguma fonte de dados do projeto, como:
13
- * **Arquivos `.yaml`** gerados dinamicamente durante a execução.
14
- * **Arquivos de elementos Ruby (`.rb`)** estáticos.
15
- * **Sugestão por Similaridade:** Utiliza o algoritmo de Levenshtein para encontrar elementos na tela que são "parecidos" com o localizador que falhou, sugerindo correções para erros de digitação.
13
+ * **Arquivos `.yaml`** gerados dinamicamente.
14
+ * **Arquivos de elementos Ruby (`.rb`)** customizáveis.
15
+ * **Sugestão por Similaridade:** Utiliza o algoritmo de Levenshtein para encontrar elementos na tela que são "parecidos" com o localizador que falhou, sugerindo correções.
16
+ * **Altamente Configurável:** Permite que os projetos definam seus próprios caminhos e nomes de arquivos de elementos, tornando a ferramenta totalmente reutilizável.
16
17
  * **Arquitetura Modular:** O código é limpo, organizado e fácil de estender, seguindo o Princípio da Responsabilidade Única.
17
18
  * **Suporte Multiplataforma:** A lógica de análise e sugestão funciona tanto para **Android** quanto para **iOS**.
18
19
 
@@ -30,12 +31,36 @@ E então execute no seu terminal:
30
31
  bundle install
31
32
  ```
32
33
 
33
- ## ⚙️ Configuração e Uso
34
+ ## ⚙️ Configuração (Opcional)
34
35
 
35
- A integração com projetos baseados em **Cucumber** é extremamente simples.
36
+ Para tornar a ferramenta flexível e adaptável a diferentes projetos, você pode configurar os caminhos onde os elementos são buscados. Crie um bloco de configuração no seu arquivo de inicialização (ex: `features/support/env.rb`).
36
37
 
37
- 1. No seu arquivo `features/support/env.rb`, adicione o `require` para carregar a ferramenta.
38
- 2. Dentro do hook `After`, adicione um bloco condicional para chamar o helper sempre que um cenário falhar.
38
+ **Se nenhuma configuração for fornecida, a ferramenta usará os valores padrão.**
39
+
40
+ ```ruby
41
+ # Em features/support/env.rb
42
+
43
+ AppiumFailureHelper.configure do |config|
44
+ # Caminho para a pasta que contém os arquivos de elementos.
45
+ # Padrão: 'features/elements'
46
+ config.elements_path = 'caminho/para/sua/pasta/de/elementos'
47
+
48
+ # Nome do arquivo principal de elementos Ruby.
49
+ # Padrão: 'elementLists.rb'
50
+ config.elements_ruby_file = 'meu_arquivo_de_elementos.rb'
51
+ end
52
+ ```
53
+
54
+ ### Opções Disponíveis
55
+
56
+ | Parâmetro | Descrição | Valor Padrão |
57
+ | --------------------- | ------------------------------------------------------------------------------ | ------------------------ |
58
+ | `elements_path` | Path relativo à raiz do projeto para a pasta que contém os arquivos de elementos. | `'features/elements'` |
59
+ | `elements_ruby_file` | Nome do arquivo Ruby principal que define os elementos dentro da `elements_path`. | `'elementLists.rb'` |
60
+
61
+ ## 🛠️ Uso no Cucumber
62
+
63
+ A integração é feita através de um hook `After` no seu ambiente de testes.
39
64
 
40
65
  **Exemplo completo para `features/support/env.rb`:**
41
66
 
@@ -45,52 +70,39 @@ A integração com projetos baseados em **Cucumber** é extremamente simples.
45
70
  require 'appium_lib'
46
71
  require 'cucumber'
47
72
 
48
- # 1. Carrega a sua ferramenta com uma única linha
73
+ # 1. Carrega a sua ferramenta
49
74
  require 'appium_failure_helper'
50
75
 
51
- # ... (outras configurações do seu ambiente) ...
76
+ # 2. (Opcional) Configura os caminhos se forem diferentes do padrão
77
+ AppiumFailureHelper.configure do |config|
78
+ config.elements_path = 'features/elements'
79
+ config.elements_ruby_file = 'elementLists.rb'
80
+ end
52
81
 
53
- # 2. Hook que executa após cada cenário de teste
82
+ # 3. Hook que executa após cada cenário de teste
54
83
  After do |scenario|
55
84
  # Se o cenário falhou, aciona o seu helper
56
85
  if scenario.failed?
57
86
  puts "\n--- CENÁRIO FALHOU! ACIONANDO O DIAGNÓSTICO INTELIGENTE ---"
58
87
 
59
- # A chamada é simples e direta.
60
- # Use a variável do seu driver (pode ser @driver, $driver, etc.)
88
+ # A chamada ao helper utiliza automaticamente as configurações definidas acima.
61
89
  AppiumFailureHelper.handler_failure(@driver, scenario.exception)
62
90
 
63
91
  puts "--- HELPER FINALIZOU. VERIFIQUE A PASTA 'reports_failure' ---"
64
92
  end
65
93
  end
66
-
67
- # ... (código para fechar o driver, etc.) ...
68
94
  ```
69
95
 
70
- E é isso! A ferramenta está pronta para agir.
71
-
72
96
  ## 📄 Entendendo o Relatório Gerado
73
97
 
74
- Após uma falha, uma nova pasta será criada na raiz do seu projeto, seguindo o padrão: `reports_failure/failure_[timestamp]`.
75
-
76
- Dentro dela, você encontrará 4 arquivos:
77
-
78
- ```
79
- reports_failure/failure_20250924_154010/
80
- |-- all_elements_dump_20250924_154010.yaml # Dump de todos os elementos da tela.
81
- |-- failure_analysis_20250924_154010.yaml # Resumo da análise em formato YAML.
82
- |-- page_source_20250924_154010.xml # O XML completo da tela no momento da falha.
83
- `-- report_20250924_154010.html # O relatório interativo para abrir no navegador.
84
- ```
85
-
86
- ### O Relatório HTML Interativo
98
+ Após uma falha, uma nova pasta será criada na raiz do seu projeto: `reports_failure/failure_[timestamp]`. Dentro dela, o arquivo mais importante é o `report_[...].html`.
87
99
 
88
- Este é o principal artefato. Ele é dividido em seções claras para um diagnóstico rápido:
100
+ O relatório HTML é dividido em seções claras para um diagnóstico rápido:
89
101
 
90
- #### Análise de Mapeamento (Blocos Verde/Amarelo)
91
- Estes blocos aparecem no topo e informam se o elemento que falhou foi encontrado nos arquivos de mapeamento do seu projeto.
92
- * **Bloco Verde (Sucesso):** Confirma que o elemento foi encontrado em um arquivo `.yaml` ou `.rb`, mostrando o caminho e/ou o localizador correto. Isso geralmente indica um problema de timing ou de visibilidade do elemento na tela, já que a definição dele está correta.
93
- * **Bloco Amarelo (Aviso):** Informa que o elemento **não foi encontrado** nos arquivos de mapeamento. Isso geralmente aponta para um erro de digitação no nome do elemento no seu código de teste.
102
+ #### Análise de Mapeamento (Bloco Verde/Amarelo)
103
+ Informa se o elemento que falhou foi encontrado nos seus arquivos de mapeamento (`.rb` ou `.yaml`).
104
+ * **Bloco Verde (Sucesso):** Confirma que o elemento foi encontrado. Isso sugere que a definição está correta, e o problema pode ser de timing ou visibilidade na tela.
105
+ * **Bloco Amarelo (Aviso):** Informa que o elemento **não foi encontrado**. Isso geralmente aponta para um erro de digitação no nome do elemento no seu código de teste.
94
106
 
95
107
  #### Elemento com Falha (Bloco Vermelho)
96
108
  Mostra exatamente qual `Tipo de Seletor` e `Valor Buscado` o Appium usou quando a falha ocorreu.
@@ -99,21 +111,22 @@ Mostra exatamente qual `Tipo de Seletor` e `Valor Buscado` o Appium usou quando
99
111
  Uma imagem exata da tela no momento do erro.
100
112
 
101
113
  #### Sugestões de Reparo (Análise de Similaridade)
102
- Se houver elementos na tela com localizadores parecidos com o que falhou, eles serão listados aqui com uma pontuação de similaridade. É extremamente útil para corrigir pequenos erros de digitação nos seus seletores.
114
+ Lista os elementos na tela com localizadores parecidos com o que falhou, com uma pontuação de similaridade. Ideal para corrigir erros de digitação nos seletores.
103
115
 
104
116
  #### Dump Completo da Página
105
- Uma lista interativa de **todos os elementos** visíveis na tela, com todos os seus possíveis localizadores. Útil para explorar a tela e encontrar seletores alternativos.
117
+ Uma lista interativa de **todos os elementos** visíveis na tela, com todos os seus possíveis localizadores.
106
118
 
107
119
  ## 🏛️ Arquitetura do Código
108
120
 
109
- O código foi reestruturado em módulos com responsabilidades únicas para facilitar a manutenção e a extensibilidade.
121
+ O código é modular para facilitar a manutenção e a extensibilidade.
110
122
 
111
- * `handler.rb`: O **Maestro**. Orquestra as chamadas para os outros módulos na ordem correta.
112
- * `analyzer.rb`: O **Analista**. Processa a mensagem de erro e calcula a similaridade dos elementos.
113
- * `element_repository.rb`: O **Repositório**. É responsável por encontrar e carregar as definições de elementos de arquivos `.yaml` e `.rb`.
114
- * `page_analyzer.rb`: O **Leitor de Tela**. Processa o XML da página para extrair todos os elementos, sugerir nomes e gerar localizadores.
115
- * `report_generator.rb`: O **Gerador**. Consolida todos os dados analisados e cria os 4 arquivos de relatório.
116
- * `utils.rb`: Funções auxiliares, como o Logger.
123
+ * `configuration.rb`: Classe que armazena as opções configuráveis e seus valores padrão.
124
+ * `handler.rb`: O **Maestro**. Orquestra as chamadas para os outros módulos.
125
+ * `analyzer.rb`: O **Analista**. Processa a mensagem de erro e calcula a similaridade.
126
+ * `element_repository.rb`: O **Repositório**. Encontra e carrega as definições de elementos de arquivos `.yaml` e `.rb` usando os caminhos configurados.
127
+ * `page_analyzer.rb`: O **Leitor de Tela**. Processa o XML da página para extrair elementos e sugerir nomes/localizadores.
128
+ * `report_generator.rb`: O **Gerador**. Consolida todos os dados e cria os arquivos de relatório.
129
+ * `utils.rb`: Funções auxiliares (Logger, etc.).
117
130
 
118
131
  ## 🤝 Como Contribuir
119
132
 
@@ -121,4 +134,4 @@ Encontrou um bug ou tem uma ideia para uma nova funcionalidade? Abra uma *Issue*
121
134
 
122
135
  ## 📜 Licença
123
136
 
124
- Este projeto é distribuído sob a licença MIT. Veja o arquivo `LICENSE` para mais detalhes.
137
+ Este projeto é distribuído sob a licença MIT.
@@ -0,0 +1,13 @@
1
+ module AppiumFailureHelper
2
+ class Configuration
3
+ # Define as opções que o usuário poderá configurar
4
+ attr_accessor :elements_path, :elements_ruby_file
5
+
6
+ def initialize
7
+ # Define os valores PADRÃO.
8
+ # Se o usuário não configurar nada, a GEM usará estes valores.
9
+ @elements_path = 'features/elements'
10
+ @elements_ruby_file = 'elementLists.rb'
11
+ end
12
+ end
13
+ end
@@ -1,49 +1,57 @@
1
1
  module AppiumFailureHelper
2
2
  module ElementRepository
3
+
4
+ def self.load_all
5
+ elements_map = load_from_ruby_file
6
+ elements_map.merge!(load_all_from_yaml)
7
+ elements_map
8
+ end
9
+
10
+ private
11
+
12
+ def self.load_from_ruby_file
13
+ map = {}
14
+ # ALTERADO: Lê os caminhos a partir da configuração central.
15
+ config = AppiumFailureHelper.configuration
16
+ file_path = File.join(Dir.pwd, config.elements_path, config.elements_ruby_file)
17
+
18
+ return map unless File.exist?(file_path)
19
+
20
+ # ... (o resto do método continua igual)
21
+ begin
22
+ require file_path
23
+ instance = OnboardingElementLists.new
24
+ unless instance.respond_to?(:elements)
25
+ Utils.logger.warn("AVISO: A classe OnboardingElementLists não expõe um `attr_reader :elements`.")
26
+ return map
27
+ end
28
+ instance.elements.each do |key, value|
29
+ map[key.to_s] = { 'tipoBusca' => value[0], 'valor' => value[1] }
30
+ end
31
+ rescue => e
32
+ Utils.logger.warn("AVISO: Erro ao processar o arquivo #{file_path}: #{e.message}")
33
+ end
34
+
35
+ map
36
+ end
37
+
3
38
  def self.load_all_from_yaml
4
39
  elements_map = {}
5
- # Procura em todo o diretório de trabalho atual por arquivos .yaml
6
- glob_path = File.join(Dir.pwd, '**', '*.yaml')
40
+ # ALTERADO: o caminho base da configuração central.
41
+ config = AppiumFailureHelper.configuration
42
+ glob_path = File.join(Dir.pwd, config.elements_path, '**', '*.yaml')
7
43
 
8
44
  Dir.glob(glob_path).each do |file|
9
- # Evita ler os próprios relatórios gerados
45
+ # ... (o resto do método continua igual) ...
10
46
  next if file.include?('reports_failure')
11
-
12
47
  begin
13
48
  data = YAML.load_file(file)
14
- if data.is_a?(Hash)
15
- data.each do |key, value|
16
- if value.is_a?(Hash) && value['tipoBusca'] && value['value']
17
- elements_map[key] = value
18
- end
19
- end
20
- end
49
+ elements_map.merge!(data) if data.is_a?(Hash)
21
50
  rescue => e
22
51
  Utils.logger.warn("Aviso: Erro ao carregar o arquivo YAML #{file}: #{e.message}")
23
52
  end
24
53
  end
25
54
  elements_map
26
55
  end
27
-
28
- # NOVO: Método para verificar a existência de um elemento em um arquivo .rb
29
- def self.find_in_ruby_file(element_name, path = 'elements/elements.rb')
30
- return { found: false, path: path, reason: "Arquivo não encontrado" } unless File.exist?(path)
31
-
32
- begin
33
- content = File.read(path)
34
- # Regex flexível para encontrar definições como:
35
- # def nome_do_elemento
36
- # element :nome_do_elemento
37
- # element('nome_do_elemento')
38
- if content.match?(/def #{element_name}|element[ |\(]['|:]#{element_name}/)
39
- return { found: true, path: path }
40
- else
41
- return { found: false, path: path, reason: "Definição não encontrada" }
42
- end
43
- rescue => e
44
- Utils.logger.warn("Aviso: Erro ao ler o arquivo Ruby #{path}: #{e.message}")
45
- return { found: false, path: path, reason: "Erro de leitura" }
46
- end
47
- end
48
56
  end
49
57
  end
@@ -17,28 +17,17 @@ module AppiumFailureHelper
17
17
  platform = @driver.capabilities['platformName']&.downcase || 'unknown'
18
18
 
19
19
  failed_info = Analyzer.extract_failure_details(@exception)
20
-
21
- # ALTERADO: Agora busca em todas as fontes de dados
22
- logical_name_key = failed_info[:selector_value].to_s.gsub(/^#/, '')
23
-
24
- # 1. Busca nos arquivos YAML dinâmicos
25
- element_map_yaml = ElementRepository.load_all_from_yaml
26
- de_para_yaml_result = Analyzer.find_de_para_match(failed_info, element_map_yaml)
20
+ unified_element_map = ElementRepository.load_all
21
+ de_para_result = Analyzer.find_de_para_match(failed_info, unified_element_map)
27
22
 
28
- # 2. Busca no arquivo Ruby
29
- de_para_rb_result = ElementRepository.find_in_ruby_file(logical_name_key)
30
-
31
- # 3. Analisa a tela atual
32
23
  page_analyzer = PageAnalyzer.new(page_source, platform)
33
24
  all_page_elements = page_analyzer.analyze
34
25
  similar_elements = Analyzer.find_similar_elements(failed_info, all_page_elements)
35
26
 
36
- # Organiza TODOS os resultados para o relatório
37
27
  report_data = {
38
28
  failed_element: failed_info,
39
29
  similar_elements: similar_elements,
40
- de_para_yaml_analysis: de_para_yaml_result, # Resultado da análise YAML
41
- de_para_rb_analysis: de_para_rb_result, # Resultado da análise Ruby
30
+ de_para_analysis: de_para_result,
42
31
  all_page_elements: all_page_elements,
43
32
  screenshot_base64: @driver.screenshot_as(:base64),
44
33
  platform: platform,
@@ -46,7 +35,7 @@ module AppiumFailureHelper
46
35
  }
47
36
 
48
37
  ReportGenerator.new(@output_folder, page_source, report_data).generate_all
49
-
38
+
50
39
  Utils.logger.info("Relatórios gerados com sucesso em: #{@output_folder}")
51
40
  rescue => e
52
41
  Utils.logger.error("Erro ao capturar detalhes da falha: #{e.message}\n#{e.backtrace.join("\n")}")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppiumFailureHelper
4
- VERSION = "0.6.6"
4
+ VERSION = "0.6.8"
5
5
  end
@@ -15,8 +15,22 @@ require_relative 'appium_failure_helper/element_repository'
15
15
  require_relative 'appium_failure_helper/page_analyzer'
16
16
  require_relative 'appium_failure_helper/report_generator'
17
17
  require_relative 'appium_failure_helper/handler'
18
+ require_relative 'appium_failure_helper/configuration'
19
+
18
20
  module AppiumFailureHelper
19
21
  class Error < StandardError; end
22
+ class << self
23
+ attr_writer :configuration
24
+ end
25
+
26
+ def self.configuration
27
+ @configuration ||= Configuration.new
28
+ end
29
+
30
+ def self.configure
31
+ yield(configuration)
32
+ end
33
+
20
34
  def self.handler_failure(driver, exception)
21
35
  Handler.call(driver, exception)
22
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_failure_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Nascimento
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-24 00:00:00.000000000 Z
11
+ date: 2025-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -95,6 +95,7 @@ files:
95
95
  - Rakefile
96
96
  - lib/appium_failure_helper.rb
97
97
  - lib/appium_failure_helper/analyzer.rb
98
+ - lib/appium_failure_helper/configuration.rb
98
99
  - lib/appium_failure_helper/element_repository.rb
99
100
  - lib/appium_failure_helper/handler.rb
100
101
  - lib/appium_failure_helper/page_analyzer.rb