Skip to content

Commit

Permalink
Add support for timeouts for attach applications
Browse files Browse the repository at this point in the history
Fixes #149
  • Loading branch information
Jani Mikkonen committed Jul 4, 2019
1 parent 82de0e3 commit 9c373ca
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 24 deletions.
3 changes: 3 additions & 0 deletions atests/attach_application.robot
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Attach To A Running Application By Id
Attach Application By Id ${test application id}
Application Should Be Attached

Attach To A Running Application By Invalid Name
Attach Application By Name ${INVALID TEST APPLICATION NAME}

*** Keywords ***
Start Test Application
${handle} = Start Process ${TEST APPLICATION}
Expand Down
11 changes: 10 additions & 1 deletion atests/configuration.robot
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Library OperatingSystem
Library String
Library WhiteLibrary
Suite Setup None
Suite Teardown White Configuration Parameters Restore
Test Teardown White Configuration Parameters Restore

*** Test Cases ***
Set White Busy Timeout
Expand All @@ -29,11 +29,20 @@ Set White Drag Step Count
${WHITE_DRAG_STEP_COUNT} Get White Drag Step Count
Should Be Equal ${WHITE_DRAG_STEP_COUNT} ${3}

Set White Attach Application Timeout
Set White Attach Application Timeout 10 s
${ATTACH_APPLICATION_TIMEOUT} Get White Attach Application Timeout
Should Be Equal ${ATTACH_APPLICATION_TIMEOUT} 10000 milliseconds

Get Default Attach Application Timeout
${ATTACH_APPLICATION_TIMEOUT} Get White Attach Application Timeout
Should Be Equal ${ATTACH_APPLICATION_TIMEOUT} 30000 milliseconds

*** Keywords ***
White Configuration Parameters Restore
#These defaults are defined in White Stack source code.
Set White Busy Timeout 5000 ms
Set White Find Window Timeout 30000 ms
Set White Double Click Interval 0 ms
Set White Attach Application Timeout 30 s

1 change: 1 addition & 0 deletions atests/resource.robot
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Library WhiteLibrary
*** Variables ***
${TEST APPLICATION} ${EXECDIR}${/}UIAutomationTest${/}bin${/}Debug${/}UIAutomationTest.exe
${TEST APPLICATION NAME} UIAutomationTest
${INVALID TEST APPLICATION NAME} UIAutomationTestThatDoesNotExist
${TEST APPLICATION WINDOW TITLE} UI Automation Test Window
${TEST WHITE APPLICATION} ${EXECDIR}${/}WhiteTestApp${/}WpfTestApplication.exe
${TEST WHITE APPLICATION NAME} MainWindow
Expand Down
1 change: 1 addition & 0 deletions src/WhiteLibrary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def __init__(self, screenshot_dir=None):
self.screenshooter = None
self.ROBOT_LIBRARY_LISTENER = self # pylint: disable=invalid-name
self.screenshots_enabled = True
self._attach_application_timeout = 30000
self.libraries = [ApplicationKeywords(self),
ButtonKeywords(self),
KeyboardKeywords(self),
Expand Down
26 changes: 23 additions & 3 deletions src/WhiteLibrary/keywords/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from System.Diagnostics import ProcessStartInfo
from WhiteLibrary.keywords.librarycomponent import LibraryComponent
from WhiteLibrary.keywords.robotlibcore import keyword
from TestStack.White import Application
from WhiteLibrary.utils.wait import Wait
from TestStack.White import Application, WhiteException


class ApplicationKeywords(LibraryComponent):
Expand All @@ -26,6 +27,25 @@ def launch_application(self, sut_path, args=None):
else:
self.state.app = Application.Launch(sut_path)

def _attach_application(self, sut_identifier):
if self.state._attach_application_timeout == 0:
return Application.Attach(sut_identifier)

sut = None

def search_application():
try:
sut = Application.Attach(sut_identifier) # noqa: F841
return True
except WhiteException:
return False

Wait.until_true(lambda: search_application(),
self._get_milliseconds_as_timestr(self.state._attach_application_timeout),
"Unable to locate application via identifie: {}".format(sut_identifier))

return sut

@keyword
def attach_application_by_name(self, sut_name):
"""Attaches a running application by name.
Expand All @@ -35,7 +55,7 @@ def attach_application_by_name(self, sut_name):
Example:
| Attach Application By Name | UIAutomationTest |
"""
self.state.app = Application.Attach(sut_name)
self.state.app = self._attach_application(sut_name)

@keyword
def attach_application_by_id(self, sut_id):
Expand All @@ -46,7 +66,7 @@ def attach_application_by_id(self, sut_id):
Example:
| Attach Application By Id | 12188 |
"""
self.state.app = Application.Attach(int(sut_id))
self.state.app = self._attach_application(int(sut_id))

@keyword
def close_application(self):
Expand Down
24 changes: 24 additions & 0 deletions src/WhiteLibrary/keywords/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,30 @@ def set_white_drag_step_count(value):
logger.info("White DragStepCount set to" + str(CoreAppXmlConfiguration.Instance.DragStepCount))
return CoreAppXmlConfiguration.Instance.DragStepCount

@keyword
def set_white_attach_application_timeout(self, timeout):
"""Sets timeout for attach application keywords for White and returns original value.
``timeout`` is the timeout value as Robot time string.
Default timeout is 30 seconds.
Note: This is not core TestStack.White feature
"""
original_timeout = self.state._attach_application_timeout
self.state._attach_application_timeout = int(self._get_timestr_in_milliseconds(timeout))
logger.info("White Attach Application Timeout set to " + str(self.state._attach_application_timeout))
return original_timeout

@keyword
def get_white_attach_application_timeout(self):
"""Returns Attach Application Timeout value of White.
See also `Set White Attach Application Timeout`.
Note: This is not core TestStack.White feature
"""
return self._get_milliseconds_as_timestr(self.state._attach_application_timeout)

@staticmethod
@keyword
def get_white_drag_step_count():
Expand Down
29 changes: 9 additions & 20 deletions src/WhiteLibrary/keywords/items/uiitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from WhiteLibrary.keywords.librarycomponent import LibraryComponent
from WhiteLibrary.keywords.robotlibcore import keyword
from WhiteLibrary.utils.click import Clicks
import time
from WhiteLibrary.utils.wait import Wait


class UiItemKeywords(LibraryComponent):
Expand Down Expand Up @@ -98,10 +98,10 @@ def wait_until_item_exists(self, locator, timeout):
See `Waiting and timeouts` for more information about waiting in WhiteLibrary.
"""
self._wait_until_true(lambda: self._item_exists(locator),
timeout,
"Item with locator '{}' did not exist within {} seconds"
.format(locator, timestr_to_secs(timeout)))
Wait.until_true(lambda: self._item_exists(locator),
timeout,
"Item with locator '{}' did not exist within {} seconds"
.format(locator, timestr_to_secs(timeout)))

@keyword
def wait_until_item_does_not_exist(self, locator, timeout):
Expand All @@ -116,22 +116,11 @@ def wait_until_item_does_not_exist(self, locator, timeout):
See `Waiting and timeouts` for more information about waiting in WhiteLibrary.
"""
self._wait_until_true(lambda: not self._item_exists(locator),
timeout,
"Item with locator '{}' still existed after {} seconds"
.format(locator, timestr_to_secs(timeout)))
Wait.until_true(lambda: not self._item_exists(locator),
timeout,
"Item with locator '{}' still existed after {} seconds"
.format(locator, timestr_to_secs(timeout)))

def _item_exists(self, locator):
search_criteria = self.state._get_search_criteria(locator)
return self.state.window.Exists(search_criteria)

@staticmethod
def _wait_until_true(condition, timeout, error_msg):
timeout = timestr_to_secs(timeout)
max_wait = time.time() + timeout
while True:
if condition():
break
if time.time() > max_wait:
raise AssertionError(error_msg)
time.sleep(0.1)
16 changes: 16 additions & 0 deletions src/WhiteLibrary/utils/wait.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import time
from robot.utils import timestr_to_secs


class Wait:
@staticmethod
def until_true(condition, timeout, error_msg):
"""Helper to wait until given condition is met."""
timeout = timestr_to_secs(timeout)
max_wait = time.time() + timeout
while True:
if condition():
break
if time.time() > max_wait:
raise AssertionError(error_msg)
time.sleep(0.1)

0 comments on commit 9c373ca

Please sign in to comment.