def terminate(self): """ Try to kill the process and close the **funq** object. """ if self.funq: if self._process is not None: # le process peut être mort, et ne pas nous l'avoir signalé try: wait_for(lambda: self._process.poll() is not None, 0.05, 0.01) except TimeOutError: pass if self._process.returncode is not None: # process fini de manière innatendue (-11: SegFault) LOG.critical("L'application testée [%s] s'est terminée de" " manière innatendue (code retour: %s)", self._process.pid, self._process.returncode) self._process = None else: # mode attache, on doit gerer la fin du process # demande de fermeture, gentiment (qApp->quit()). LOG.info("Fermeture de l'application testée [%s].", self._process.pid) try: self.funq.quit() except socket.error: pass try: self.funq.close() except socket.error: pass self.funq = None self._kill_process()
def terminate(self): """ Try to kill the process and close the **funq** object. """ if self.funq: if self._process is not None: # the process may be already dead try: wait_for(lambda: self._process.poll() is not None, 0.05, 0.01) except TimeOutError: pass if self._process.returncode is not None: # process terminated unexpectedly (-11: SegFault) LOG.critical("The tested application [%s] has terminated" " unexpectedly (return code: %s)", self._process.pid, self._process.returncode) self._process = None else: # try to exit nicely the tested application process # with a call to qApp->quit(). LOG.info("Closing tested application [%s].", self._process.pid) try: self.funq.quit() except socket.error: pass try: self.funq.close() except socket.error: pass self.funq = None self._kill_process()
def __init__(self, host=None, port=None, aliases=None, timeout_connection=10): if host is None: host = self.DEFAULT_HOST if port is None: port = self.DEFAULT_PORT if aliases is None: aliases = HooqAliases() elif isinstance(aliases, basestring): aliases = HooqAliases.from_file(aliases) elif not isinstance(aliases, HooqAliases): raise TypeError("aliases must be None or str or an" " instance of HooqAliases") self.aliases = aliases def connect(): """ try to connect """ try: self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket.connect((host, port)) return True except socket.error as e: if e.errno != errno.ECONNREFUSED: raise return e wait_for(connect, timeout_connection, 0.2) self._socket.settimeout(timeout_connection) self._fsocket = self._socket.makefile(mode="rwb")
def terminate(self): """ Try to kill the process and close the **funq** object. """ if self.funq: if self._process is not None: # the process may be already dead try: wait_for(lambda: self._process.poll() is not None, 0.05, 0.01) except TimeOutError: pass if self._process.returncode is not None: # process terminated unexpectedly (-11: SegFault) LOG.critical("The tested application [%s] has terminated" " unexpectedly (return code: %s)", self._process.pid, self._process.returncode) self._process = None else: # try to exit nicely the tested application process # with a call to qApp->quit(). LOG.info("Closing tested application [%s].", self._process.pid) try: self.funq.quit() except socket.error: pass try: self.funq.close() except socket.error: pass self.funq = None self._kill_process()
def active_widget(self, widget_type='window', timeout=10.0, timeout_interval=0.1, wait_active=True): """ Returns an instance of a :class:`funq.models.Widget` or derived that is the active widget of the application, or the widget that got the focus. Be careful, this method acts weidly under Xvfb. Example:: my_dialog = client.active_window('modal') :param widget_type: kind of widget. ('window', 'modal', 'popup' ou 'focus' -> see the QT documentation about QApplication::activeWindow, QApplication::activeModalWidget, QApplication::activePopupWidget or QApplication::focusWidget respectively) :param timeout: if > 0, tries to get the widget until timeout is reached (second) :param timeout_interval: time between two atempts to get a widget (seconds) :param wait_active: If true - the default -, wait until the widget become visible and enabled. """ wdata = [None] def get_widget(): """ Try to get the widget """ try: wdata[0] = self.send_command('active_widget', type=widget_type) return True except FunqError as err: if err.classname != 'NoActiveWindow': raise return err wait_for(get_widget, timeout, timeout_interval) widget = Widget.create(self, wdata[0]) if wait_active: if 'QWindow' in wdata[0]['classes']: # QWindow (Qt5) does not have the enabled property props = {'active': True, 'visible': True} else: props = {'enabled': True, 'visible': True} widget.wait_for_properties(props) return widget
def widget(self, alias=None, path=None, timeout=10.0, timeout_interval=0.1, wait_active=True): """ Returns an instance of a :class:`funq.models.Widget` or derived identified with an alias or with its complete path. Example:: widget = client.widget('my_alias') :param alias: alias defined in the aliases file. :param path: complete path for the widget :param timeout: if > 0, tries to get the widget until timeout is reached (second) :param timeout_interval: time between two atempts to get a widget (seconds) :param wait_active: If true - the default -, wait until the widget become visible and enabled. """ if not (alias or path): raise TypeError("alias or path must be defined") if alias: path = self.aliases[alias] wdata = [None] def get_widget(): """ Try to get the widget """ try: wdata[0] = self.send_command('widget_by_path', path=path) return True except FunqError as err: if err.classname != 'InvalidWidgetPath': raise return err wait_for(get_widget, timeout, timeout_interval) widget = Widget.create(self, wdata[0]) if wait_active: if 'QWindow' in wdata[0]['classes']: # QWindow (Qt5) does not have the enabled property props = {'active': True, 'visible': True} else: props = {'enabled': True, 'visible': True} widget.wait_for_properties(props) return widget
def _kill_process(self): """ Kill the application tested process """ if self._process: # wait for a nice exit try: wait_for(lambda: self._process.poll() is not None, 10, 0.05) except TimeOutError: pass if self._process.returncode is None: # application seems blocked ! try to terminate it ... LOG.warn("The tested application [%s] can not be stopped" " nicely.", self._process.pid) self._process.terminate() self._process.wait() self._process = None
def _kill_process(self): """ Tue le process de l'application de test """ if self._process: # attente de fermeture gentille try: wait_for(lambda: self._process.poll() is not None, 10, 0.05) except TimeOutError: pass if self._process.returncode is None: # application bloquée ! pas le choix ... LOG.warn("The tested application [%s] can not be stopped" " nicely.", self._process.pid) self._process.terminate() self._process.wait() self._process = None
def test_wait_for_some_time_with_snooze_factor(): tools.SNOOZE_FACTOR = 4.0 t = time.time() def func(): return t + 0.05 < time.time() assert_true(tools.wait_for(func, 0.025)) tools.SNOOZE_FACTOR = 1.0
def _kill_process(self): """ Kill the application tested process """ if self._process: # wait for a nice exit try: wait_for(lambda: self._process.poll() is not None, 10, 0.05) except TimeOutError: pass if self._process.returncode is None: # application seems blocked ! try to terminate it ... LOG.warn("The tested application [%s] can not be stopped" " nicely.", self._process.pid) self._process.terminate() self._process.wait() self._process = None
def action(self, alias=None, path=None, timeout=10.0, timeout_interval=0.1, wait_active=True): """ Returns an instance of a :class:`funq.models.Action` or derived identified with an alias or with its complete path. Example:: action = client.action('my_alias') :param alias: alias defined in the aliases file. :param path: complete path for the action :param timeout: if > 0, tries to get the action until timeout is reached (second) :param timeout_interval: time between two atempts to get an action (seconds) :param wait_active: If true - the default -, wait until the action become visible and enabled. """ if not (alias or path): raise TypeError("alias or path must be defined") if alias: path = self.aliases[alias] wdata = [None] def get_action(): """ Try to get the action """ try: wdata[0] = self.send_command('widget_by_path', path=path) return True except FunqError as err: if err.classname != 'InvalidWidgetPath': raise return err wait_for(get_action, timeout, timeout_interval) action = Action.create(self, wdata[0]) if wait_active: action.wait_for_properties({'enabled': True, 'visible': True}) return action
def wait_for_properties(self, props, timeout=10.0, timeout_interval=0.1): """ Wait for the properties to have the given values. Example:: self.wait_for_properties({'enabled': True, 'visible': True}) """ def check_props(): properties = self.properties() for k, v in props.iteritems(): if properties.get(k) != v: return False return True return wait_for(check_props, timeout, timeout_interval)
class FunqClient(object): """ Allow to communicate with a libFunq server. This is the main class used to manipulate tested application. """ DEFAULT_HOST = 'localhost' DEFAULT_PORT = 9999 def __init__(self, host=None, port=None, aliases=None, timeout_connection=10): if host is None: host = self.DEFAULT_HOST if port is None: port = self.DEFAULT_PORT if aliases is None: aliases = HooqAliases() elif isinstance(aliases, basestring): aliases = HooqAliases.from_file(aliases) elif not isinstance(aliases, HooqAliases): raise TypeError("aliases must be None or str or an" " instance of HooqAliases") self.aliases = aliases self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def connect(): """ try to connect """ try: self._socket.connect((host, port)) return True except socket.error, e: if e.errno != errno.ECONNREFUSED: raise return e wait_for(connect, timeout_connection, 0.2) self._socket.settimeout(timeout_connection) self._fsocket = self._socket.makefile(mode="rwb")
def test_wait_for_timeout(): def func(): return False tools.wait_for(func, 0.0)
if alias: path = self.aliases[alias] wdata = [None] def get_widget(): """ Try to get the widget """ try: wdata[0] = self.send_command('widget_by_path', path=path) return True except FunqError, err: if err.classname != 'InvalidWidgetPath': raise return err wait_for(get_widget, timeout, timeout_interval) widget = Widget.create(self, wdata[0]) if wait_active: widget.wait_for_properties({'enabled': True, 'visible': True}) return widget def active_widget(self, widget_type='window', timeout=10.0, timeout_interval=0.1, wait_active=True): """ Returns an instance of a :class:`funq.models.Widget` or derived that is the active widget of the application, or the widget that got the focus. Be careful, this method acts weidly under Xvfb.
def test_wait_for_custom_exc(): def func(): return Exception() tools.wait_for(func, 0.0)
def test_wait_for_some_time(): t = time.time() def func(): return t + 0.05 < time.time() assert_true(tools.wait_for(func, 0.1))
if alias: path = self.aliases[alias] wdata = [None] def get_widget(): """ Try to get the widget """ try: wdata[0] = self.send_command('widget_by_path', path=path) return True except FunqError, err: if err.classname != 'InvalidWidgetPath': raise return err wait_for(get_widget, timeout, timeout_interval) widget = Widget.create(self, wdata[0]) if wait_active: if 'QWindow' in wdata[0]['classes']: # QWindow (Qt5) does not have the enabled property props = {'active': True, 'visible': True} else: props = {'enabled': True, 'visible': True} widget.wait_for_properties(props) return widget def active_widget(self, widget_type='window', timeout=10.0, timeout_interval=0.1, wait_active=True): """ Returns an instance of a :class:`funq.models.Widget` or derived
def test_wait_for(): def func(): return True assert_true(tools.wait_for(func, 0.0))