Skip to content

Commit

Permalink
temp commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mtlynch committed Apr 12, 2016
1 parent daed832 commit c538484
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
76 changes: 53 additions & 23 deletions client_wrapper/html5_driver.py
Expand Up @@ -25,6 +25,9 @@
import names
import results

ERROR_NO_WEBSOCKETS_BUTTON = 'Could not find "WebSockets" mode button.'
ERROR_NO_START_TEST_BUTTON = 'Could not find "Start Test" button.'


class NdtHtml5SeleniumDriver(object):

Expand All @@ -51,13 +54,15 @@ def perform_test(self):
result.client = names.NDT_HTML5

with contextlib.closing(_create_browser(self._browser)) as driver:
result.start_time = datetime.datetime.now(pytz.utc)
result.browser = self._browser
result.browser_version = driver.capabilities['version']

if not _load_url(driver, self._url, result):
return result

_click_start_button(driver, result)
if not _click_start_button(driver, result.errors):
return result

if not _record_test_in_progress_values(result, driver,
self._timeout):
Expand Down Expand Up @@ -109,22 +114,31 @@ def _load_url(driver, url, result):
return True


def _click_start_button(driver, result):
def _click_start_button(driver, errors):
"""Clicks start test button and records start time.
Clicks the start test button for an NDT test and records the start time in
an NdtResult instance.
Args:
driver: An instance of a Selenium webdriver browser class.
result: An instance of an NdtResult class.
errors: A list of errors to append to if start button cannot be clicked.
"""
driver.find_element_by_id('websocketButton').click()

start_button = driver.find_elements_by_xpath(
"//*[contains(text(), 'Start Test')]")[0]
websocket_button = driver.find_element_by_id('websocketButton')
# Failure to find the websockets mode button is non-fatal since it is
# assumed to be the default option.
if websocket_button:
websocket_button.click()
else:
errors.append(results.TestError(ERROR_NO_WEBSOCKETS_BUTTON))

start_button = _find_element_containing_text(driver, 'Start Test')
# Failure to find the Start Test button is fatal.
if not start_button:
errors.append(results.TestError(ERROR_NO_START_TEST_BUTTON))
return False
start_button.click()
result.start_time = datetime.datetime.now(pytz.utc)
return True


def _record_test_in_progress_values(result, driver, timeout):
Expand All @@ -143,25 +157,33 @@ def _record_test_in_progress_values(result, driver, timeout):
Returns:
True if recording the measured values was successful, False if otherwise.
"""
result.c2s_result = results.NdtSingleTestResult()
result.s2c_result = results.NdtSingleTestResult()
try:
# wait until 'Now Testing your upload speed' is displayed
upload_speed_text = driver.find_elements_by_xpath(
"//*[contains(text(), 'your upload speed')]")[0]
result.c2s_result = results.NdtSingleTestResult()
result.c2s_result.start_time = _record_time_when_element_displayed(
upload_speed_text,
driver,
timeout=timeout)
result.c2s_result.end_time = datetime.datetime.now(pytz.utc)
upload_speed_text = _find_element_containing_text(driver,
'your upload speed')
if not upload_speed_text:
result.errors.append(results.TestError(
'Could not find banner indicating upload test in progress.'))
else:
result.c2s_result.start_time = _record_time_when_element_displayed(
upload_speed_text,
driver,
timeout=timeout)
result.c2s_result.end_time = datetime.datetime.now(pytz.utc)

# wait until 'Now Testing your download speed' is displayed
download_speed_text = driver.find_elements_by_xpath(
"//*[contains(text(), 'your download speed')]")[0]
result.s2c_result = results.NdtSingleTestResult()
result.s2c_result.start_time = _record_time_when_element_displayed(
download_speed_text,
driver,
timeout=timeout)
download_speed_text = _find_element_containing_text(
driver, 'your download speed')
if not download_speed_text:
result.errors.append(results.TestError(
'Could not find banner indicating upload test in progress.'))
else:
result.s2c_result.start_time = _record_time_when_element_displayed(
download_speed_text,
driver,
timeout=timeout)

# wait until the results page appears
results_text = driver.find_element_by_id('results')
Expand All @@ -176,6 +198,14 @@ def _record_test_in_progress_values(result, driver, timeout):
return True


def _find_element_containing_text(driver, text):
matching_elements = driver.find_elements_by_xpath(
'//*[contains(text(), \'%s\')]' % text)
if not matching_elements:
return None
return matching_elements[0]


def _record_time_when_element_displayed(element, driver, timeout):
"""Return the time when the specified element is displayed.
Expand Down
16 changes: 7 additions & 9 deletions client_wrapper/results.py
Expand Up @@ -59,10 +59,13 @@ class NdtResult(object):
"""Represents the results of a complete NDT HTML5 client test.
Attributes:
start_time: The datetime at which tests were initiated (i.e. the time
the driver pushed the 'Start Test' button).
end_time: The datetime at which the tests completed (i.e. the time the
results page loaded).
start_time: The datetime at which the NDT client was launched. This is
time at which the client wrapper begins running a particular client,
but is not necessarily the time at which the client itself initiated
a test.
end_time: The datetime at which the NDT client completed. This should be
equal to the end_time of the client's last test or the time of a
fatal error in the client.
errors: A list of TestError objects representing any errors encountered
during the tests (or an empty list if all tests were successful).
c2s_result: The NdtSingleResult for the c2s (upload) test (or None if no
Expand Down Expand Up @@ -100,8 +103,3 @@ def __init__(self,
self.client_version = None
self.browser = None
self.browser_version = None

def __str__(self):
return 'NDT Results:\n Start Time: %s,\n End Time: %s'\
',\n Latency: %s, \nErrors: %s' % (
self.start_time, self.end_time, self.latency, self.errors)
28 changes: 28 additions & 0 deletions tests/test_html5_driver.py
Expand Up @@ -125,6 +125,34 @@ def test_unrecognized_browser_raises_error(self):
with self.assertRaises(ValueError):
selenium_driver.perform_test()

def test_completes_with_error_when_there_is_no_websocket_button(self):
"""Missing WebSocket button on the UI should be a non-fatal error."""
self.mock_page_elements['websocketButton'] = None
result = html5_driver.NdtHtml5SeleniumDriver(
browser='firefox',
url='http://ndt.mock-server.com:7123/',
timeout=1000).perform_test()

self.assertEqual(1.0, result.c2s_result.throughput)
self.assertEqual(2.0, result.s2c_result.throughput)
self.assertEqual(3.0, result.latency)
self.assertErrorMessagesEqual(
[html5_driver.ERROR_NO_WEBSOCKETS_BUTTON], result.errors)

def test_fails_when_there_is_no_start_test_button(self):
self.mock_elements_by_text['Start Test'] = None

result = html5_driver.NdtHtml5SeleniumDriver(
browser='firefox',
url='http://ndt.mock-server.com:7123/',
timeout=1000).perform_test()

self.assertIsNone(result.c2s_result)
self.assertIsNone(result.s2c_result)
self.assertIsNone(result.latency)
self.assertErrorMessagesEqual(
[html5_driver.ERROR_NO_START_TEST_BUTTON], result.errors)

def test_results_page_displays_non_numeric_latency(self):
self.mock_page_elements['latency'] = mock.Mock(text='Non-numeric value')
result = html5_driver.NdtHtml5SeleniumDriver(
Expand Down

0 comments on commit c538484

Please sign in to comment.