Module: AppiumFailureHelper::Analyzer
- Defined in:
- lib/appium_failure_helper/analyzer.rb
Class Method Summary collapse
- .extract_failure_details(exception) ⇒ Object
- .find_de_para_match(failed_info, element_map) ⇒ Object
- .find_similar_elements(failed_info, all_page_suggestions) ⇒ Object
- .triage_error(exception) ⇒ Object
Class Method Details
.extract_failure_details(exception) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/appium_failure_helper/analyzer.rb', line 27 def self.extract_failure_details(exception) = exception..to_s info = {} patterns = [ /using "([^"]+)" with value "([^"]+)"/, /element with locator ['"]?(#?\w+)['"]?/i, /(?:could not be found|cannot find element) using (.+?)=['"]?([^'"]+)['"]?/i, /no such element: Unable to locate element: {"method":"([^"]+)","selector":"([^"]+)"}/i, ] patterns.each do |pattern| match = .match(pattern) if match if match.captures.size == 2 info[:selector_type], info[:selector_value] = match.captures.map(&:strip) else info[:selector_value] = match.captures.first.strip info[:selector_type] = 'logical_name' end return info end end info end |
.find_de_para_match(failed_info, element_map) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/appium_failure_helper/analyzer.rb', line 51 def self.find_de_para_match(failed_info, element_map) failed_value = (failed_info || {})[:selector_value].to_s return nil if failed_value.empty? logical_name_key = failed_value.gsub(/^#/, '') if element_map.key?(logical_name_key) return { logical_name: logical_name_key, correct_locator: element_map[logical_name_key] } end cleaned_failed_locator = failed_value.gsub(/[:\-\/@=\[\]'"()]/, ' ').gsub(/\s+/, ' ').downcase.strip element_map.each do |name, locator_info| mapped_locator = (locator_info || {})['valor'].to_s cleaned_mapped_locator = mapped_locator.gsub(/[:\-\/@=\[\]'"()]/, ' ').gsub(/\s+/, ' ').downcase.strip distance = DidYouMean::Levenshtein.distance(cleaned_failed_locator, cleaned_mapped_locator) max_len = [cleaned_failed_locator.length, cleaned_mapped_locator.length].max next if max_len.zero? similarity_score = 1.0 - (distance.to_f / max_len) if similarity_score > 0.85 return { logical_name: name, correct_locator: locator_info } end end nil end |
.find_similar_elements(failed_info, all_page_suggestions) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/appium_failure_helper/analyzer.rb', line 73 def self.find_similar_elements(failed_info, all_page_suggestions) failed_locator_value = (failed_info || {})[:selector_value] failed_locator_type = (failed_info || {})[:selector_type] return [] unless failed_locator_value && failed_locator_type normalized_failed_type = failed_locator_type.to_s.downcase.include?('id') ? 'id' : failed_locator_type.to_s cleaned_failed_locator = failed_locator_value.to_s.gsub(/[:\-\/@=\[\]'"()]/, ' ').gsub(/\s+/, ' ').downcase.strip similarities = [] all_page_suggestions.each do |suggestion| candidate_locator = (suggestion[:locators] || []).find { |loc| loc[:strategy] == normalized_failed_type } next unless candidate_locator cleaned_candidate_locator = candidate_locator[:locator].gsub(/[:\-\/@=\[\]'"()]/, ' ').gsub(/\s+/, ' ').downcase.strip distance = DidYouMean::Levenshtein.distance(cleaned_failed_locator, cleaned_candidate_locator) max_len = [cleaned_failed_locator.length, cleaned_candidate_locator.length].max next if max_len.zero? similarity_score = 1.0 - (distance.to_f / max_len) if similarity_score > 0.85 similarities << { name: suggestion[:name], locators: suggestion[:locators], score: similarity_score, attributes: suggestion[:attributes] } end end similarities.sort_by { |s| -s[:score] }.first(5) end |
.triage_error(exception) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/appium_failure_helper/analyzer.rb', line 3 def self.triage_error(exception) case exception when Selenium::WebDriver::Error::NoSuchElementError, Selenium::WebDriver::Error::TimeoutError, Selenium::WebDriver::Error::UnknownCommandError :locator_issue when Selenium::WebDriver::Error::ElementNotInteractableError :visibility_issue when Selenium::WebDriver::Error::StaleElementReferenceError :stale_element_issue when defined?(RSpec::Expectations::ExpectationNotMetError) ? RSpec::Expectations::ExpectationNotMetError : Class.new :assertion_failure when NoMethodError, NameError, ArgumentError, TypeError :ruby_code_issue when Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED :session_startup_issue when Selenium::WebDriver::Error::WebDriverError return :app_crash_issue if exception..include?('session deleted because of page crash') :unknown_appium_issue else :unknown_issue end end |