Module for interfacing with speedtest.net for internet speed tests using
Selenium.
This module contains the Speedtest class, which inherits from a generic
Provider class and implements methods to configure, run, and capture
results of internet speed tests from speedtest.net. The class manages
browser interactions, including dismissing notifications and accepting
necessary agreements, to ensure the test runs smoothly.
Dependencies: - traceback: For error logging and debugging. -
selenium: For automating web browser interaction.
Speedtest
A provider class for conducting internet speed tests using the
speedtest.net website.
The Speedtest class extends the Provider base class, encapsulating
methods specific to navigating and interacting with speedtest.net.
This includes accepting privacy policies, dismissing advertisements
or notifications, initiating the speed test, and capturing the
results as screenshots.
Attributes:
Name |
Type |
Description |
driver |
|
A driver instance that adheres to the DriverInterface, used
for web interactions with the browser.
|
Source code in src/speed_sleuth/provider/speedtest.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 | @Provider.register
class Speedtest:
"""A provider class for conducting internet speed tests using the
speedtest.net website.
The Speedtest class extends the Provider base class, encapsulating
methods specific to navigating and interacting with speedtest.net.
This includes accepting privacy policies, dismissing advertisements
or notifications, initiating the speed test, and capturing the
results as screenshots.
Attributes:
driver: A driver instance that adheres to the DriverInterface, used
for web interactions with the browser.
"""
def __init__(self, driver: DriverInterface):
"""Initializes the Speedtest provider with a browser instance.
Parameters:
driver: A driver instance that adheres to the DriverInterface, used
for web interactions with the browser.
"""
driver.get("https://www.speedtest.net/")
self.driver = driver
def __str__(self) -> str:
"""Provides a string representation of the Speedtest instance.
Returns:
str: A simple string representation for this provider.
"""
return "speedtest"
def setup(self):
"""Prepares the speedtest.net environment for testing.
This method attempts to dismiss the cookie/license agreement
modal and any other initial pop-ups to ensure the test page is
ready for interaction.
"""
try:
eula_reject_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "button#onetrust-reject-all-handler"),
timeout=5,
)
if eula_reject_btn:
eula_reject_btn.click()
except NoSuchElementException:
# onetrust-accept-btn-handler
eula_accept_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "button#onetrust-accept-btn-handler"),
timeout=5,
)
if eula_accept_btn:
eula_accept_btn.click()
except Exception:
pass
def dismiss_notification(self):
"""Dismisses notifications or banners that may interfere with the test.
This method ensures that no overlay elements prevent interaction
with the test start button or the results.
"""
try:
dismiss_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "a.notification-dismiss")
)
if dismiss_btn:
print("dismissing notification...")
dismiss_btn.click()
except NoSuchElementException:
pass # Silently ignore this exception which can occur.
def run(self, filename: str = "speedtest-result.png"):
"""Executes the speed test on speedtest.net and captures a screenshot
of the results.
This method orchestrates the test execution, from setup to
result capture, handling possible UI elements and exceptions
along the way.
Parameters:
filename: The file path where the result screenshot will be saved.
Defaults to 'speedtest-result.png'.
"""
code = 0
try:
self.setup()
self.dismiss_notification()
start_test_btn = self.driver.wait_for_button_clickable(
(By.CSS_SELECTOR, "#container div.start-button > a"), timeout=5
)
start_test_btn.click()
print("[+] running speedtest.net, please wait")
# Block until the result is displayed on screen.
results = self.driver.wait_for_element(
(
By.CSS_SELECTOR,
"div.result-container-speed.result-container-speed-active",
)
)
print("[+] done, taking snapshot of the website results")
# self.dismiss_notification()
if results:
results.screenshot(filename)
# Dismiss speedtest modal.
except ElementNotInteractableException as e:
print("Did not find element: ", e)
code = -1
except Exception as e:
print(f"An error occurred: {e}")
traceback.print_exc()
code = -1
finally:
self.driver.cleanup(code)
def parse_results(self):
"""Parses the captured results of the speed test.
This method is intended for future implementation, where results
obtained from the screenshot or directly from the page will be
extracted and structured for further processing or analysis.
Currently, this method does not perform any actions.
"""
|
__init__(driver)
Initializes the Speedtest provider with a browser instance.
Parameters:
Name |
Type |
Description |
Default |
driver |
DriverInterface
|
A driver instance that adheres to the DriverInterface, used
for web interactions with the browser.
|
required
|
Source code in src/speed_sleuth/provider/speedtest.py
47
48
49
50
51
52
53
54
55
56 | def __init__(self, driver: DriverInterface):
"""Initializes the Speedtest provider with a browser instance.
Parameters:
driver: A driver instance that adheres to the DriverInterface, used
for web interactions with the browser.
"""
driver.get("https://www.speedtest.net/")
self.driver = driver
|
__str__()
Provides a string representation of the Speedtest instance.
Returns:
Name | Type |
Description |
str |
str
|
A simple string representation for this provider.
|
Source code in src/speed_sleuth/provider/speedtest.py
| def __str__(self) -> str:
"""Provides a string representation of the Speedtest instance.
Returns:
str: A simple string representation for this provider.
"""
return "speedtest"
|
dismiss_notification()
Dismisses notifications or banners that may interfere with the test.
This method ensures that no overlay elements prevent interaction
with the test start button or the results.
Source code in src/speed_sleuth/provider/speedtest.py
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 | def dismiss_notification(self):
"""Dismisses notifications or banners that may interfere with the test.
This method ensures that no overlay elements prevent interaction
with the test start button or the results.
"""
try:
dismiss_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "a.notification-dismiss")
)
if dismiss_btn:
print("dismissing notification...")
dismiss_btn.click()
except NoSuchElementException:
pass # Silently ignore this exception which can occur.
|
parse_results()
Parses the captured results of the speed test.
This method is intended for future implementation, where results
obtained from the screenshot or directly from the page will be
extracted and structured for further processing or analysis.
Currently, this method does not perform any actions.
Source code in src/speed_sleuth/provider/speedtest.py
156
157
158
159
160
161
162
163
164
165 | def parse_results(self):
"""Parses the captured results of the speed test.
This method is intended for future implementation, where results
obtained from the screenshot or directly from the page will be
extracted and structured for further processing or analysis.
Currently, this method does not perform any actions.
"""
|
run(filename='speedtest-result.png')
Executes the speed test on speedtest.net and captures a screenshot
of the results.
This method orchestrates the test execution, from setup to
result capture, handling possible UI elements and exceptions
along the way.
Parameters:
Name |
Type |
Description |
Default |
filename |
str
|
The file path where the result screenshot will be saved.
Defaults to 'speedtest-result.png'.
|
'speedtest-result.png'
|
Source code in src/speed_sleuth/provider/speedtest.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 | def run(self, filename: str = "speedtest-result.png"):
"""Executes the speed test on speedtest.net and captures a screenshot
of the results.
This method orchestrates the test execution, from setup to
result capture, handling possible UI elements and exceptions
along the way.
Parameters:
filename: The file path where the result screenshot will be saved.
Defaults to 'speedtest-result.png'.
"""
code = 0
try:
self.setup()
self.dismiss_notification()
start_test_btn = self.driver.wait_for_button_clickable(
(By.CSS_SELECTOR, "#container div.start-button > a"), timeout=5
)
start_test_btn.click()
print("[+] running speedtest.net, please wait")
# Block until the result is displayed on screen.
results = self.driver.wait_for_element(
(
By.CSS_SELECTOR,
"div.result-container-speed.result-container-speed-active",
)
)
print("[+] done, taking snapshot of the website results")
# self.dismiss_notification()
if results:
results.screenshot(filename)
# Dismiss speedtest modal.
except ElementNotInteractableException as e:
print("Did not find element: ", e)
code = -1
except Exception as e:
print(f"An error occurred: {e}")
traceback.print_exc()
code = -1
finally:
self.driver.cleanup(code)
|
setup()
Prepares the speedtest.net environment for testing.
This method attempts to dismiss the cookie/license agreement
modal and any other initial pop-ups to ensure the test page is
ready for interaction.
Source code in src/speed_sleuth/provider/speedtest.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 | def setup(self):
"""Prepares the speedtest.net environment for testing.
This method attempts to dismiss the cookie/license agreement
modal and any other initial pop-ups to ensure the test page is
ready for interaction.
"""
try:
eula_reject_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "button#onetrust-reject-all-handler"),
timeout=5,
)
if eula_reject_btn:
eula_reject_btn.click()
except NoSuchElementException:
# onetrust-accept-btn-handler
eula_accept_btn = self.driver.wait_for_element(
(By.CSS_SELECTOR, "button#onetrust-accept-btn-handler"),
timeout=5,
)
if eula_accept_btn:
eula_accept_btn.click()
except Exception:
pass
|