Skip to content

Instantly share code, notes, and snippets.

@eeejay
Created March 28, 2023 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eeejay/81c3a9ef2984935d94a23bb59fa9527f to your computer and use it in GitHub Desktop.
Save eeejay/81c3a9ef2984935d94a23bb59fa9527f to your computer and use it in GitHub Desktop.
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
import pyax
import time
import psutil
URL = "https://en.wikipedia.org/wiki/World_War_I"
# URL = "https://html.spec.whatwg.org/"
FIREFOX_BINARY = "/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin"
ATTRIBUTES = [
"AXChildren",
"AXParent",
"AXRole",
"AXRoleDescription",
"AXSubrole",
"AXTitle",
"AXDescription",
"AXHelp",
"AXValue",
"AXValueDescription",
"AXSize",
"AXPosition",
"AXEnabled",
"AXFocused",
"AXWindow",
"AXFrame",
"AXTitleUIElement",
"AXTopLevelUIElement",
"AXHasPopup",
"AXARIACurrent",
"AXSelected",
"AXRequired",
"AXElementBusy",
"AXLinkedUIElements",
"AXARIAControls",
"AXDOMIdentifier",
"AXURL",
"AXLinkUIElements",
"AXPopupValue",
"AXVisited",
"AXExpanded",
"AXMain",
"AXMinimized",
"AXSelectedChildren",
"AXTabs",
"AXContents",
"AXOrientation",
"AXMenuItemMarkChar",
"AXLoaded",
"AXLoadingProgress",
"AXMinValue",
"AXMaxValue",
"AXRowCount",
"AXColumnCount",
"AXRows",
"AXColumns",
"AXIndex",
"AXRowIndexRange",
"AXColumnIndexRange",
"AXRowHeaderUIElements",
"AXColumnHeaderUIElements",
"AXIdentifier",
"AXVisibleChildren",
"AXDisclosing",
"AXDisclosedByRow",
"AXDisclosureLevel",
"AXDisclosedRows",
"AXSelectedRows",
"AXMathRootRadicand",
"AXMathRootIndex",
"AXMathFractionNumerator",
"AXMathFractionDenominator",
"AXMathLineThickness",
"AXMathBase",
"AXMathSubscript",
"AXMathSuperscript",
"AXMathUnder",
"AXMathOver",
"AXInvalid",
"AXSelectedText",
"AXSelectedTextRange",
"AXNumberOfCharacters",
# "AXVisibleCharacterRange",
"AXInsertionPointLineNumber",
"AXEditableAncestor",
"AXHighestEditableAncestor",
"AXFocusableAncestor",
"AXARIAAtomic",
"AXARIALive",
"AXARIARelevant",
]
# ATTRIBUTE_TIMES = {}
def tree_scrape(element, indent=0):
global ATTRIBUTES
global ATTRIBUTE_TIMES
total = 1
# for attr in ATTRIBUTES:
# starttime = time.time()
# element[attr]
# ATTRIBUTE_TIMES[attr] = ATTRIBUTE_TIMES.get(attr, 0) + (time.time() - starttime)
element.get_multiple_attribute_values(*ATTRIBUTES)
for child in element:
total += tree_scrape(child, indent + 1)
return total
def big_task(acc):
starttime = time.time()
total = tree_scrape(acc)
return total, time.time() - starttime
def load_firefox(caching, binary=None):
fo = webdriver.FirefoxOptions()
# fo.set_preference("accessibility.force_disabled", -1)
fo.set_preference("accessibility.cache.enabled", caching)
if binary:
fo.binary = FirefoxBinary(binary)
driver = webdriver.Firefox(options=fo)
driver.get("data:text/html,hello")
driver_process = psutil.Process(driver.service.process.pid)
browser_process = driver_process.children(recursive=False)[0]
return driver, browser_process.pid
def load_chrome():
driver = webdriver.Chrome()
driver.get("data:text/html,hello")
driver_process = psutil.Process(driver.service.process.pid)
browser_process = driver_process.children(recursive=False)[0]
return driver, browser_process.pid
def load_safari():
driver = webdriver.Safari()
driver.get("data:text/html,hello")
f = filter(
lambda p: p.info["name"] == "Safari",
[proc for proc in psutil.process_iter(["pid", "name"])],
)
browser_process = list(f)[0]
return driver, browser_process.pid
def callback(observer, element, notificationName, info):
url = element["AXURL"]
if not url or str(url) == URL:
pyax.stop()
def run_test(driver, pid, sample_count = 3):
samples = []
app = pyax.get_application_from_pid(pid)
app["AXEnhancedUserInterface"] = True
acc = pyax.get_web_root(app)
observer = pyax.create_observer(app.pid, callback)
# Register all knowns events
observer.add_notifications("AXLoadComplete")
starttime = time.time()
driver.get(URL)
pyax.start()
print("* Page load/cache time: %f" % (time.time() - starttime))
acc = pyax.get_web_root(app)
print("* Doing task %d times: " % sample_count)
for i in range(sample_count):
total, duration = big_task(acc)
samples.append(duration)
last = i + 1 == sample_count
print(" * %f" % duration)
print("* Average: %f" % (sum(samples) / len(samples)))
driver.close()
def test_firefox_without_cache(binary=None):
print("## Firefox - caching disabled")
driver, pid = load_firefox(False, binary)
run_test(driver, pid)
def test_firefox_with_cache(binary=None):
print("## Firefox - caching enabled")
driver, pid = load_firefox(True, binary)
run_test(driver, pid)
def test_safari():
print("## Safari")
driver, pid = load_safari()
run_test(driver, pid)
def test_chrome():
print("## Chrome")
driver, pid = load_chrome()
run_test(driver, pid)
print("# Mac Accessibility Tree Dump Benchmark")
test_firefox_without_cache(FIREFOX_BINARY)
test_safari()
test_chrome()
test_firefox_with_cache(FIREFOX_BINARY)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment