appium_failure_helper 1.3.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a20267977f0afde8bb695938eebce5b191dc3cba987e5c282a6035e07d881621
4
- data.tar.gz: abc7bbfb5dbaa920db3c4830bf93089c39874bc3c1d093e9490ac65e3f58e9de
3
+ metadata.gz: 3b1148ccbdea9b7b8446bf489a8f325e6dd4255cbeeba75ed58469f21169a126
4
+ data.tar.gz: 646ef386ee881d2f9cccf4ca3e85f8a79bd3cd132221c537e6db3f07c719f91f
5
5
  SHA512:
6
- metadata.gz: 9f890998e4660b52c93b034e6237e73b11022430807dba957ed6bfaff38245eee55fda60a1dcf04191ac955e967d9a5a174976d1345196c3b049970f7602c05a
7
- data.tar.gz: c0514430f06deae0ede268aedcc2b3ca56fce697e26b0f612ac4bdace28afda15d0c14dffce72b5d94898cb3c7384a17d78a5bca6e822b4ac3fc3047d0c02ae0
6
+ metadata.gz: f345294b82fad66aa0b47e3455a85063caef1f292225f9954d5bd10a0370f29e9ba51c15d7caeed219c4e587b84f115e4e762e7b16f9408bacdc91dbce8aaf55
7
+ data.tar.gz: 505c2e690da3d723c5afb43a7afb1f219bca682e45e1c8c14068c98072c1331c90fecbe764312fe4ad3071d95df57106068b4feea5c4ca68c736b5fcbcd647dd
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/README.md CHANGED
@@ -1,144 +1,155 @@
1
- # Appium Failure Helper: Diagnóstico Inteligente de Falhas
2
-
3
- ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
4
- ![Gem Version](https://img.shields.io/badge/gem-v3.0.0-blue)
5
- ![License](https://img.shields.io/badge/license-MIT-lightgrey)
6
-
7
- Uma GEM de diagnóstico para testes Appium em Ruby, projetada para transformar falhas de automação em insights acionáveis. Quando um teste falha por não encontrar um elemento, esta ferramenta gera um relatório HTML detalhado, identificando a causa provável do erro e acelerando drasticamente o tempo de depuração.
8
-
9
- ## ✨ Principais Funcionalidades
10
-
11
- * **Diagnóstico por Triagem de Erros:** Identifica inteligentemente o *tipo* de falha (`NoSuchElementError`, `TimeoutError`, `Erro de Código Ruby`, `Falha de Asserção`, etc.) e gera um relatório específico e útil para cada cenário.
12
- * **Análise de Código-Fonte:** Para erros "silenciosos" (onde a mensagem não contém o seletor), a GEM inspeciona o `stack trace` para encontrar o arquivo e a linha exatos do erro, extraindo o seletor diretamente do código-fonte.
13
- * **Análise de Atributos Ponderados:** Em vez de uma simples comparação de strings, a GEM "desmonta" o seletor que falhou e o compara atributo por atributo com os elementos na tela, dando pesos diferentes para `resource-id`, `text`, etc., para encontrar o "candidato mais provável".
14
- * **Relatórios Ricos e Interativos:** Gera um relatório HTML completo com:
15
- * Screenshot da falha.
16
- * Diagnóstico claro da causa provável, com sugestões acionáveis.
17
- * Abas com "Análise Avançada" e um "Dump Completo" de todos os elementos da tela.
18
- * **Altamente Configurável:** Permite a customização de caminhos para se adaptar a diferentes estruturas de projeto.
19
-
20
- ## 🚀 Instalação
21
-
22
- Adicione esta linha ao `Gemfile` do seu projeto de automação:
23
-
24
- ```ruby
25
- gem 'appium_failure_helper', git: 'URL_DO_SEU_REPOSITORIO_GIT' # Exemplo de instalação via Git
26
- ```
27
-
28
- E então execute no seu terminal:
29
-
30
- ```sh
31
- bundle install
32
- ```
33
-
34
- ## 🛠️ Uso e Configuração
35
-
36
- A integração ideal envolve 3 passos:
37
-
38
- ### Passo 1: Configurar a GEM (Opcional)
39
-
40
- No seu arquivo de inicialização (ex: `features/support/env.rb`), carregue a GEM e, se necessário, configure os caminhos onde seus elementos estão mapeados. Se nenhuma configuração for fornecida, a ferramenta usará os valores padrão.
41
-
42
- ```ruby
43
- # features/support/env.rb
44
- require 'appium_failure_helper'
45
-
46
- AppiumFailureHelper.configure do |config|
47
- # Padrão: 'features/elements'
48
- config.elements_path = 'caminho/para/sua/pasta/de/elementos'
49
-
50
- # Padrão: 'elementLists.rb'
51
- config.elements_ruby_file = 'meu_arquivo_de_elementos.rb'
52
- end
53
- ```
54
-
55
- ### Passo 2: Enriquecer as Exceções (Altamente Recomendado)
56
-
57
- Para que a GEM consiga extrair o máximo de detalhes de uma falha (especialmente de erros genéricos como `TimeoutError` ou `NoSuchElementError` sem detalhes), é crucial que a exceção que ela recebe seja rica em informações. A melhor maneira de garantir isso é ajustar seus métodos de busca de elementos.
58
-
59
- Crie ou ajuste um arquivo de helpers (ex: `features/support/appiumCustom.rb`) com a seguinte estrutura:
60
-
61
- ```ruby
62
- # features/support/appiumCustom.rb
63
-
64
- # Métodos públicos que seus Page Objects irão chamar
65
- def find(el)
66
- find_element_with_enriched_error(el)
67
- end
68
-
69
- def clickElement(el)
70
- find_element_with_enriched_error(el).click
71
- end
72
-
73
- def waitForElementExist(el, timeout = 10)
74
- wait = Selenium::WebDriver::Wait.new(timeout: timeout)
75
- begin
76
- wait.until { $driver.find_elements(el['tipoBusca'], el['value']).size > 0 }
77
- rescue Selenium::WebDriver::Error::TimeoutError => e
78
- # Relança o erro com uma mensagem rica que a GEM entende
79
- new_message = "Timeout de #{timeout}s esperando pelo elemento: using \"#{el['tipoBusca']}\" with value \"#{el['value']}\""
80
- raise e.class, new_message
81
- end
82
- end
83
-
84
- private # --- Helper Interno ---
85
-
86
- # Este método é o coração da solução. Ele captura erros e os enriquece.
87
- def find_element_with_enriched_error(el)
88
- begin
89
- return $driver.find_element(el['tipoBusca'], el['value'])
90
- rescue Selenium::WebDriver::Error::NoSuchElementError => e
91
- # Cria uma nova mensagem explícita no formato "using... with value..."
92
- new_message = "using \"#{el['tipoBusca']}\" with value \"#{el['value']}\""
93
-
94
- # Recria a exceção original com a nova mensagem.
95
- new_exception = e.class.new(new_message)
96
- new_exception.set_backtrace(e.backtrace) # Preserva o stack trace
97
- raise new_exception
98
- end
99
- end
100
- ```
101
-
102
- ### Passo 3: Integrar com o Cucumber
103
-
104
- Finalmente, no seu `hooks.rb`, acione a GEM no hook `After` em caso de falha.
105
-
106
- ```ruby
107
- # features/support/hooks.rb
108
-
109
- After do |scenario|
110
- if scenario.failed? && $driver&.session_id
111
- AppiumFailureHelper.handler_failure($driver, scenario.exception)
112
- end
113
- end
114
- ```
115
-
116
- ## 📄 O Relatório Gerado
117
-
118
- A cada falha, uma nova pasta é criada em `reports_failure/`, contendo o relatório `.html` e outros artefatos. O relatório pode ter dois formatos principais:
119
-
120
- 1. **Relatório de Diagnóstico Simples:** Gerado para erros que não são de seletor (ex: falha de conexão, erro de código Ruby, falha de asserção). Ele mostra um diagnóstico direto, a mensagem de erro original e o `stack trace`.
121
-
122
- 2. **Relatório Detalhado (para problemas de seletor):**
123
- * **Coluna da Esquerda:** Mostra o "Elemento com Falha" (extraído da exceção ou do código), "Sugestões Encontradas no Código" e o "Screenshot".
124
- * **Coluna da Direita:** Contém abas interativas:
125
- * **Análise Avançada:** Apresenta o "candidato mais provável" encontrado na tela e uma análise comparativa de seus atributos (`resource-id`, `text`, etc.), com uma sugestão acionável.
126
- * **Dump Completo:** Uma lista de todos os elementos da tela e seus possíveis seletores.
127
-
128
- ## 🏛️ Arquitetura do Código
129
-
130
- A GEM é dividida em módulos com responsabilidades únicas para facilitar a manutenção e a extensibilidade (Handler, Analyzer, ReportGenerator, XPathFactory, etc.).
131
-
132
- ## 🔄 Fluxo Interno da GEM
133
-
134
- Abaixo o fluxo de como os módulos conversam entre si durante o diagnóstico de uma falha:
135
-
136
- ![Fluxo Interno](img\fluxo_appium_failure_helper.png)
137
-
138
- ## 🤝 Como Contribuir
139
-
140
- Pull Requests são bem-vindos. Para bugs ou sugestões, por favor, abra uma *Issue* no repositório.
141
-
142
- ## 📜 Licença
143
-
144
- Este projeto é distribuído sob a licença MIT.
1
+
2
+ # Appium Failure Helper: Diagnóstico Inteligente de Falhas
3
+
4
+ ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
5
+ ![Gem Version](https://badge.fury.io/rb/appium_failure_helper.svg)
6
+ ![License](https://img.shields.io/badge/license-MIT-lightgrey)
7
+
8
+ Uma GEM de diagnóstico para testes Appium em Ruby, projetada para transformar falhas de automação em **insights acionáveis**. Quando um teste falha por não encontrar um elemento, a ferramenta gera um relatório HTML detalhado, identificando a causa provável e acelerando drasticamente o tempo de depuração.
9
+
10
+ ---
11
+
12
+ ## Principais Funcionalidades
13
+
14
+ - **Diagnóstico Inteligente de Falhas:** Identifica automaticamente o tipo de erro (`NoSuchElementError`, `TimeoutError`, falha de asserção ou erro de código Ruby) e gera relatórios personalizados para cada caso.
15
+ - **Análise de Código-Fonte:** Para erros "silenciosos", inspeciona o `stack trace` e extrai o seletor diretamente do código, apontando arquivo e linha exatos.
16
+ - **Comparação Avançada de Atributos:** Compara atributo por atributo (`resource-id`, `text`, etc.) para encontrar o candidato mais provável na tela, evitando análises superficiais.
17
+ - **Relatórios Interativos:** HTML completo com:
18
+ - Screenshot da falha
19
+ - Diagnóstico claro e sugestões acionáveis
20
+ - Abas com "Análise Avançada" e "Dump Completo" de todos os elementos da tela
21
+ - **Configuração Flexível:** Personalize caminhos e arquivos de elementos para se adaptar a diferentes estruturas de projeto.
22
+
23
+ ---
24
+
25
+ ## 🚀 Instalação
26
+
27
+ Adicione ao `Gemfile` do seu projeto de automação:
28
+
29
+ ```ruby
30
+ gem 'appium_failure_helper', git: 'URL_DO_SEU_REPOSITORIO_GIT'
31
+ ```
32
+
33
+ Depois execute:
34
+
35
+ ```sh
36
+ bundle install
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 🛠️ Uso e Configuração
42
+
43
+ ### 1️⃣ Configuração Inicial (Opcional)
44
+
45
+ No arquivo de inicialização (`features/support/env.rb`), configure os caminhos de elementos se necessário:
46
+
47
+ ```ruby
48
+ require 'appium_failure_helper'
49
+
50
+ AppiumFailureHelper.configure do |config|
51
+ config.elements_path = 'features/elements' # Pasta de elementos
52
+ config.elements_ruby_file = 'elementLists.rb' # Arquivo Ruby de elementos
53
+ end
54
+ ```
55
+
56
+ ---
57
+
58
+ ### 2️⃣ Enriquecer Exceções (Altamente Recomendado)
59
+
60
+ Para extrair o máximo de informações de falhas, ajuste seus métodos de busca de elementos:
61
+
62
+ ```ruby
63
+ def find(el)
64
+ find_element_with_enriched_error(el)
65
+ end
66
+
67
+ def clickElement(el)
68
+ find_element_with_enriched_error(el).click
69
+ end
70
+
71
+ def waitForElementExist(el, timeout = 10)
72
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
73
+ begin
74
+ wait.until { $driver.find_elements(el['tipoBusca'], el['value']).size > 0 }
75
+ rescue Selenium::WebDriver::Error::TimeoutError => e
76
+ raise e.class, "Timeout de #{timeout}s esperando pelo elemento: using \"\#{el['tipoBusca']}\" with value \"\#{el['value']}\""
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def find_element_with_enriched_error(el)
83
+ $driver.find_element(el['tipoBusca'], el['value'])
84
+ rescue Selenium::WebDriver::Error::NoSuchElementError => e
85
+ new_exception = e.class.new("using \"\#{el['tipoBusca']}\" with value \"\#{el['value']}\"")
86
+ new_exception.set_backtrace(e.backtrace)
87
+ raise new_exception
88
+ end
89
+ ```
90
+
91
+ ---
92
+
93
+ ### 3️⃣ Integração com Cucumber
94
+
95
+ No `hooks.rb`, acione a GEM após cada cenário com falha:
96
+
97
+ ```ruby
98
+ After do |scenario|
99
+ if scenario.failed? && $driver&.session_id
100
+ AppiumFailureHelper.handler_failure($driver, scenario.exception)
101
+ end
102
+ end
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 📄 Relatório Gerado
108
+
109
+ A cada falha, a GEM cria uma pasta em `reports_failure/` com:
110
+
111
+ 1. **Relatório Simples:** Para falhas genéricas, mostrando erro, stack trace e diagnóstico direto.
112
+ 2. **Relatório Detalhado:** Para problemas de seletor:
113
+ - **Coluna Esquerda:** Elemento com falha, seletores sugeridos e screenshot.
114
+ - **Coluna Direita:** Abas interativas:
115
+ - **Análise Avançada:** Mostra o candidato mais provável, atributos comparados e sugestões acionáveis.
116
+ - **Dump Completo:** Lista todos os elementos e possíveis seletores da tela.
117
+
118
+ ---
119
+
120
+ ## 🏛️ Arquitetura
121
+
122
+ - **Handler:** Captura falhas e aciona o fluxo de análise.
123
+ - **SourceCodeAnalyzer:** Extrai seletores diretamente do código-fonte.
124
+ - **PageAnalyzer:** Analisa o `page_source` e sugere nomes e locators alternativos.
125
+ - **XPathFactory:** Gera estratégias de localização (diretas, combinatórias, parent-based, relativas, parciais, booleanas e posicionais).
126
+ - **ReportGenerator:** Cria relatórios HTML, XML e YAML ricos e interativos.
127
+
128
+ ---
129
+
130
+ ## 🔄 Fluxo Interno da GEM
131
+
132
+ ```
133
+ Falha Appium
134
+
135
+ ├─► SourceCodeAnalyzer → {selector_type, selector_value}
136
+
137
+ └─► PageAnalyzer → [{name, locators, attributes}, ...]
138
+
139
+ └─► XPathFactory → [estratégias alternativas]
140
+
141
+
142
+ ReportGenerator HTML / XML / YAML
143
+ ```
144
+
145
+ ---
146
+
147
+ ## 🤝 Contribuindo
148
+
149
+ Pull requests e issues são bem-vindos! Abra uma *Issue* para bugs ou sugestões.
150
+
151
+ ---
152
+
153
+ ## 📜 Licença
154
+
155
+ MIT License
@@ -6,6 +6,9 @@ module AppiumFailureHelper
6
6
  Selenium::WebDriver::Error::TimeoutError,
7
7
  Selenium::WebDriver::Error::UnknownCommandError
8
8
  :locator_issue
9
+ when Selenium::WebDriver::Error::TimeoutError,
10
+ Appium::Core::Wait::TimeoutError
11
+ :locator_issue
9
12
  when Selenium::WebDriver::Error::ElementNotInteractableError
10
13
  :visibility_issue
11
14
  when Selenium::WebDriver::Error::StaleElementReferenceError
@@ -32,21 +32,24 @@ module AppiumFailureHelper
32
32
  }
33
33
 
34
34
  if triage_result == :locator_issue
35
- page_source = @driver.page_source
35
+ page_source = @driver.page_source rescue nil
36
36
  doc = Nokogiri::XML(page_source)
37
37
 
38
+ # Inicializa failed_info primeiro
38
39
  failed_info = Analyzer.extract_failure_details(@exception) || {}
39
- if failed_info.empty?
40
- failed_info = SourceCodeAnalyzer.extract_from_exception(@exception) || {}
41
- end
42
-
43
- if failed_info.empty?
44
- report_data[:triage_result] = :unidentified_locator_issue
45
- else
40
+ failed_info = SourceCodeAnalyzer.extract_from_exception(@exception) || {} if failed_info.empty?
41
+ failed_info = { selector_type: 'unknown', selector_value: 'unknown' } if failed_info.empty?
42
+
43
+ # Monta o report_data
44
+ report_data[:page_source] = page_source
45
+ report_data[:failed_element] = failed_info
46
+
47
+ # Analisa elementos similares, alternative xpaths, de_para, code search etc
48
+ unless failed_info.empty?
46
49
  page_analyzer = PageAnalyzer.new(page_source, report_data[:platform].to_s)
47
50
  all_page_elements = page_analyzer.analyze || []
48
51
  similar_elements = Analyzer.find_similar_elements(failed_info, all_page_elements) || []
49
-
52
+
50
53
  alternative_xpaths = []
51
54
  if !similar_elements.empty?
52
55
  target_suggestion = similar_elements.first
@@ -60,21 +63,22 @@ module AppiumFailureHelper
60
63
  de_para_result = Analyzer.find_de_para_match(failed_info, unified_element_map)
61
64
  code_search_results = CodeSearcher.find_similar_locators(failed_info) || []
62
65
 
63
- report_data.merge!({
64
- page_source: page_source,
65
- failed_element: failed_info,
66
+ report_data.merge!(
66
67
  similar_elements: similar_elements,
67
68
  alternative_xpaths: alternative_xpaths,
68
69
  de_para_analysis: de_para_result,
69
70
  code_search_results: code_search_results,
70
71
  all_page_elements: all_page_elements
71
- })
72
+ )
72
73
  end
73
- end
74
74
 
75
- ReportGenerator.new(@output_folder, report_data).generate_all
76
- Utils.logger.info("Relatórios gerados com sucesso em: #{@output_folder}")
77
-
75
+ # Gera o relatório
76
+ ReportGenerator.new(@output_folder, report_data).generate_all
77
+ Utils.logger.info("Relatórios gerados com sucesso em: #{@output_folder}")
78
+
79
+ report_data
80
+ return
81
+ end
78
82
  rescue => e
79
83
  Utils.logger.error("Erro fatal na GEM de diagnóstico: #{e.message}\n#{e.backtrace.join("\n")}")
80
84
  end
@@ -1,3 +1,3 @@
1
1
  module AppiumFailureHelper
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
data/release_gem.rb CHANGED
@@ -1,9 +1,16 @@
1
- #!/usr/bin/env ruby
2
1
  require 'fileutils'
3
-
2
+ require 'selenium-webdriver'
3
+ require_relative 'lib/appium_failure_helper'
4
4
  # Caminho do arquivo de versão
5
5
  VERSION_FILE = 'lib/appium_failure_helper/version.rb'
6
6
 
7
+ # Executa os testes e retorna true se todos passarem
8
+ def tests_pass?
9
+ puts "Rodando testes..."
10
+ system('bundle exec rspec')
11
+ $?.success?
12
+ end
13
+
7
14
  # Lê a versão atual da gem
8
15
  def current_version
9
16
  content = File.read(VERSION_FILE)
@@ -56,17 +63,20 @@ def git_commit_and_tag(new_version)
56
63
  end
57
64
 
58
65
  # Publicar a GEM
59
- def push_gem
66
+ def push_gem(new_version)
60
67
  `gem build appium_failure_helper.gemspec`
61
- `gem push appium_failure_helper-#{current_version.join('.')}.gem`
68
+ `gem push appium_failure_helper-#{new_version.join('.')}.gem`
62
69
  end
63
70
 
64
71
  # Fluxo principal
65
- version = current_version
66
- type = change_type
67
- new_version = increment_version(version, type)
68
- update_version_file(new_version)
69
- git_commit_and_tag(new_version)
70
- push_gem
71
-
72
- puts "GEM publicada com sucesso! Nova versão: #{new_version.join('.')}"
72
+ if tests_pass?
73
+ version = current_version
74
+ type = change_type
75
+ new_version = increment_version(version, type)
76
+ update_version_file(new_version)
77
+ git_commit_and_tag(new_version)
78
+ push_gem(new_version)
79
+ puts "GEM publicada com sucesso! Nova versão: #{new_version.join('.')}"
80
+ else
81
+ puts "Testes falharam! Commit e push cancelados."
82
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_failure_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Nascimento
@@ -90,11 +90,10 @@ executables: []
90
90
  extensions: []
91
91
  extra_rdoc_files: []
92
92
  files:
93
+ - ".rspec"
93
94
  - LICENSE.txt
94
95
  - README.md
95
96
  - Rakefile
96
- - appium_failure_helper-1.2.3.gem
97
- - appium_failure_helper-1.2.4.gem
98
97
  - elements/cadastro.yaml
99
98
  - elements/login.yaml
100
99
  - img/fluxo_appium_failure_helper.png
Binary file
Binary file