tfb-fail-detector.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. """
  2. TFB Fail Detector Web Scraper
  3. Scrapes data from the last 3 complete runs and outputs the frameworks that have failed all of them with the same errors.
  4. Developed using selenium==4.10.0 and the selenium/standalone-chrome:4.10.0 docker image.
  5. USAGE: python tfb-fail-detector.py
  6. """
  7. from collections import defaultdict
  8. import re
  9. from selenium import webdriver
  10. from selenium.webdriver.chrome.options import Options
  11. from selenium.webdriver.common.by import By
  12. NUM_RUNS = 3
  13. def get_driver():
  14. """Gets the selenium webdriver for interacting with the website"""
  15. chrome_options = Options()
  16. chrome_options.add_argument("--headless")
  17. chrome_options.add_argument("--no-sandbox")
  18. chrome_options.add_argument("--disable-dev-shm-usage")
  19. chrome_prefs = {}
  20. chrome_options.experimental_options["prefs"] = chrome_prefs
  21. chrome_prefs["profile.default_content_settings"] = {"images": 2}
  22. driver = webdriver.Chrome(options=chrome_options)
  23. return driver
  24. def get_last_n_complete_runs(driver, n=3):
  25. """Scrape the last n complete runs"""
  26. rows = driver.find_elements(By.CSS_SELECTOR, "table.resultsTable > tbody > tr")
  27. complete_runs = []
  28. for row in rows:
  29. row_uuid = row.get_dom_attribute("data-uuid")
  30. run_stats = row.find_element(By.CSS_SELECTOR, "td:nth-of-type(2)")
  31. frameworks_tested_stats = re.search(r"([0-9]+)/([0-9]+) frameworks tested", run_stats.text)
  32. if not frameworks_tested_stats:
  33. # print("Unable to get info from run %s" % row_uuid)
  34. continue
  35. tested, total = frameworks_tested_stats.groups()
  36. if tested != total:
  37. # print("Found incomplete run %s. Tested: %s/%s" % (row_uuid, tested, total))
  38. continue
  39. # print("Found complete run %s. Tested: %s/%s" % (row_uuid, tested, total))
  40. complete_runs.append(row_uuid)
  41. if len(complete_runs) >= n:
  42. return complete_runs
  43. def find_failing_frameworks(driver, run_uuids):
  44. """Find frameworks that have failed all the given runs with the same error message"""
  45. failing_frameworks = defaultdict(lambda: 0)
  46. def process_failed_framework(framework_element):
  47. framework = re.search(r"\[\S+] [a-zA-Z][a-zA-Z:\_ ]*$", framework_element.text)
  48. framework_failure = framework.group(0)
  49. failing_frameworks[framework_failure] += 1
  50. for run_uuid in run_uuids:
  51. driver.get("https://tfb-status.techempower.com/results/%s" % run_uuid)
  52. assert "TFB Status" in driver.title
  53. failure_list = driver.find_element(By.CLASS_NAME, "failures")
  54. failures = failure_list.find_elements(By.TAG_NAME, "li")
  55. for failure in failures:
  56. process_failed_framework(failure)
  57. return failing_frameworks
  58. if __name__ == '__main__':
  59. driver = get_driver()
  60. driver.get("https://tfb-status.techempower.com/")
  61. assert "TFB Status" in driver.title
  62. complete_runs = get_last_n_complete_runs(driver, NUM_RUNS)
  63. failed_frameworks = find_failing_frameworks(driver, complete_runs)
  64. for failure_info, fail_count in failed_frameworks.items():
  65. if fail_count != NUM_RUNS:
  66. continue
  67. print(failure_info)