Sikuli Selenium Robotframework 集成
来源:互联网 发布:编程:字符串压缩 编辑:程序博客网 时间:2024/05/16 07:54
Sikuli Selenium Robotfraamework 集成
原文:http://www.8bitavenue.com/2012/04/sikuli-selenium-robot-framework-integration/
1、需要的所有安装包
sikuli
selenium(webdriver)
RobotFramework
python(2.7.2版本)
Java Run Time Installation
Jython
Easy Install setuptools-0.6c11.win32-py2.7.exe
pip 下载后放入C:\Python\Scripts 进入cmd 输入
easy_install pip python ez_setup.py
2、设置环境变量
C:\python27C:\Python27\ScriptsC:\jython2.5.2\binC:\Program Files (x86)\Java\jre6\bin
3、安装
easy_install robotframeworkeasy_install wxPythoneasy_install robotframework-rideeasy_install robotframework-selenium2library
4、Sikuli selenium和RobotFrameWork开始工作了
按照以下的步骤配置,就可以在RobotFramework中同时应用sikuli和selenium一直写case了。其中seleniumlibrary运行在python环境下,sikuli需要Jython支持才能通过python解析。通过RPC-xml服务使本地python和远端机器运行Jython来实现本地selenium和远端机器的sikuli共同工作。
- 创建 [C:\robot] [C:\robot\data] [C:\robot\libs] [C:\robot\suites]
下载Python远端服务放到[C:\robot\libs]下robotremoteserver.py googlecode有可能已经被墙了,下面代码可以自行保存成robotremoteserver.py
# Copyright 2008-2014 Nokia Solutions and Networks## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.__version__ = 'devel'import errnoimport reimport selectimport sysimport inspectimport tracebackfrom StringIO import StringIOfrom SimpleXMLRPCServer import SimpleXMLRPCServerfrom xmlrpclib import Binarytry:import signalexcept ImportError:signal = Nonetry:from collections import Mappingexcept ImportError:Mapping = dictBINARY = re.compile('[\x00-\x08\x0B\x0C\x0E-\x1F]')NON_ASCII = re.compile('[\x80-\xff]')class RobotRemoteServer(SimpleXMLRPCServer):allow_reuse_address = True_generic_exceptions = (AssertionError, RuntimeError, Exception)_fatal_exceptions = (SystemExit, KeyboardInterrupt)def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, allow_stop=True):"""Configure and start-up remote server.:param library: Test library instance or module to host.:param host:Address to listen. Use ``'0.0.0.0'`` to listento all available interfaces.:param port:Port to listen. Use ``0`` to select a free portautomatically. Can be given as an integer or asa string.:param port_file: File to write port that is used. ``None`` meansno such file is written.:param allow_stop: Allow/disallow stopping the server using``Stop Remote Server`` keyword."""SimpleXMLRPCServer.__init__(self, (host, int(port)), logRequests=False)self._library = libraryself._allow_stop = allow_stopself._shutdown = Falseself._register_functions()self._register_signal_handlers()self._announce_start(port_file)self.serve_forever()def _register_functions(self):self.register_function(self.get_keyword_names)self.register_function(self.run_keyword)self.register_function(self.get_keyword_arguments)self.register_function(self.get_keyword_documentation)self.register_function(self.stop_remote_server)def _register_signal_handlers(self):def stop_with_signal(signum, frame):self._allow_stop = Trueself.stop_remote_server()for name in 'SIGINT', 'SIGTERM', 'SIGHUP':if hasattr(signal, name):signal.signal(getattr(signal, name), stop_with_signal)def _announce_start(self, port_file=None):host, port = self.server_addressself._log('Robot Framework remote server at %s:%s starting.' % (host, port))if port_file:pf = open(port_file, 'w')try:pf.write(str(port))finally:pf.close()def serve_forever(self):if hasattr(self, 'timeout'):self.timeout = 0.5elif sys.platform.startswith('java'):self.socket.settimeout(0.5)while not self._shutdown:try:self.handle_request()except (OSError, select.error), err:if err.args[0] != errno.EINTR:raisedef stop_remote_server(self):prefix = 'Robot Framework remote server at %s:%s ' % self.server_addressif self._allow_stop:self._log(prefix + 'stopping.')self._shutdown = Trueelse:self._log(prefix + 'does not allow stopping.', 'WARN')return self._shutdowndef get_keyword_names(self):get_kw_names = getattr(self._library, 'get_keyword_names', None) or \ getattr(self._library, 'getKeywordNames', None)if self._is_function_or_method(get_kw_names):names = get_kw_names()else:names = [attr for attr in dir(self._library) if attr[0] != '_' and self._is_function_or_method(getattr(self._library, attr))]return names + ['stop_remote_server']def _is_function_or_method(self, item):# Cannot use inspect.isroutine because it returns True for# object().__init__ with Jython and IronPythonreturn inspect.isfunction(item) or inspect.ismethod(item)def run_keyword(self, name, args, kwargs=None):args, kwargs = self._handle_binary_args(args, kwargs or {})result = {'status': 'FAIL'}self._intercept_std_streams()try:return_value = self._get_keyword(name)(*args, **kwargs)except:exc_type, exc_value, exc_tb = sys.exc_info()self._add_to_result(result, 'error',self._get_error_message(exc_type, exc_value))self._add_to_result(result, 'traceback',self._get_error_traceback(exc_tb))self._add_to_result(result, 'continuable',self._get_error_attribute(exc_value, 'CONTINUE'),default=False)self._add_to_result(result, 'fatal',self._get_error_attribute(exc_value, 'EXIT'),default=False)else:try:self._add_to_result(result, 'return',self._handle_return_value(return_value))except:exc_type, exc_value, _ = sys.exc_info()self._add_to_result(result, 'error',self._get_error_message(exc_type, exc_value))else:result['status'] = 'PASS'self._add_to_result(result, 'output', self._restore_std_streams())return resultdef _handle_binary_args(self, args, kwargs):args = [self._handle_binary_arg(a) for a in args]kwargs = dict([(k, self._handle_binary_arg(v)) for k, v in kwargs.items()])return args, kwargsdef _handle_binary_arg(self, arg):if isinstance(arg, Binary):return arg.datareturn argdef _add_to_result(self, result, key, value, default=''):if value != default:result[key] = valuedef get_keyword_arguments(self, name):kw = self._get_keyword(name)if not kw:return []return self._arguments_from_kw(kw)def _arguments_from_kw(self, kw):args, varargs, kwargs, defaults = inspect.getargspec(kw)if inspect.ismethod(kw):args = args[1:] # drop 'self'if defaults:args, names = args[:-len(defaults)], args[-len(defaults):]args += ['%s=%s' % (n, d) for n, d in zip(names, defaults)]if varargs:args.append('*%s' % varargs)if kwargs:args.append('**%s' % kwargs)return argsdef get_keyword_documentation(self, name):if name == '__intro__':return inspect.getdoc(self._library) or ''if name == '__init__' and inspect.ismodule(self._library):return ''return inspect.getdoc(self._get_keyword(name)) or ''def _get_keyword(self, name):if name == 'stop_remote_server':return self.stop_remote_serverkw = getattr(self._library, name, None)if not self._is_function_or_method(kw):return Nonereturn kwdef _get_error_message(self, exc_type, exc_value):if exc_type in self._fatal_exceptions:self._restore_std_streams()raisename = exc_type.__name__message = self._get_message_from_exception(exc_value)if not message:return nameif exc_type in self._generic_exceptions \or getattr(exc_value, 'ROBOT_SUPPRESS_NAME', False):return messagereturn '%s: %s' % (name, message)def _get_message_from_exception(self, value):# UnicodeError occurs below 2.6 and if message contains non-ASCII bytestry:msg = unicode(value)except UnicodeError:msg = ' '.join([self._str(a, handle_binary=False) for a in value.args])return self._handle_binary_result(msg)def _get_error_traceback(self, exc_tb):# Latest entry originates from this class so it can be removedentries = traceback.extract_tb(exc_tb)[1:]trace = ''.join(traceback.format_list(entries))return 'Traceback (most recent call last):\n' + tracedef _get_error_attribute(self, exc_value, name):return bool(getattr(exc_value, 'ROBOT_%s_ON_FAILURE' % name, False))def _handle_return_value(self, ret):if isinstance(ret, basestring):return self._handle_binary_result(ret)if isinstance(ret, (int, long, float)):return retif isinstance(ret, Mapping):return dict([(self._str(key), self._handle_return_value(value)) for key, value in ret.items()])try:return [self._handle_return_value(item) for item in ret]except TypeError:return self._str(ret)def _handle_binary_result(self, result):if not self._contains_binary(result):return resulttry:result = str(result)except UnicodeError:raise ValueError("Cannot represent %r as binary." % result)return Binary(result)def _contains_binary(self, result):return (BINARY.search(result) or isinstance(result, str) andsys.platform != 'cli' and NON_ASCII.search(result))def _str(self, item, handle_binary=True):if item is None:return ''if not isinstance(item, basestring):item = unicode(item)if handle_binary:return self._handle_binary_result(item)return itemdef _intercept_std_streams(self):sys.stdout = StringIO()sys.stderr = StringIO()def _restore_std_streams(self):stdout = sys.stdout.getvalue()stderr = sys.stderr.getvalue()close = [sys.stdout, sys.stderr]sys.stdout = sys.__stdout__sys.stderr = sys.__stderr__for stream in close:stream.close()if stdout and stderr:if not stderr.startswith(('*TRACE*', '*DEBUG*', '*INFO*', '*HTML*', '*WARN*')):stderr = '*INFO* %s' % stderrif not stdout.endswith('\n'):stdout += '\n'return self._handle_binary_result(stdout + stderr)def _log(self, msg, level=None):if level:msg = '*%s* %s' % (level.upper(), msg)self._write_to_stream(msg, sys.stdout)if sys.__stdout__ is not sys.stdout:self._write_to_stream(msg, sys.__stdout__)def _write_to_stream(self, msg, stream):stream.write(msg + '\n')stream.flush()if __name__ == '__main__':import xmlrpclibdef stop(uri):server = test(uri, log_success=False)if server is not None:print 'Stopping remote server at %s.' % uriserver.stop_remote_server()def test(uri, log_success=True):server = xmlrpclib.ServerProxy(uri)try:server.get_keyword_names()except:print 'No remote server running at %s.' % urireturn Noneif log_success:print 'Remote server running at %s.' % urireturn serverdef parse_args(args):actions = {'stop': stop, 'test': test}if not args or len(args) > 2 or args[0] not in actions:sys.exit('Usage: python -m robotremoteserver test|stop [uri]')uri = len(args) == 2 and args[1] or 'http://127.0.0.1:8270'if '://' not in uri:uri = 'http://' + urireturn actions[args[0]], uriaction, uri = parse_args(sys.argv[1:])action(uri)
下载SikuliRemoteLibrary.py放到[C:\robot\libs]里面 无语了sikuli好像也上去了,代码如下自行保存成SikuliRemoteLibrary
import sys, osfrom robotremoteserver import RobotRemoteServer# from org.sikuli.script import *class SikuliRemoteLibrary:def __init__(self):self.log = ''# self.SS = Screen() self.PT = Pattern()def count_items_in_directory(self, path):"""Returns the number of items in the directory specified by `path`."""return len([i for i in os.listdir(path) if not i.startswith('.')])def strings_should_be_equal(self, str1, str2):print "Comparing '%s' to '%s'" % (str1, str2)if str1 != str2:raise AssertionError("Given strings are not equal")# def _wait(self, imgFile, timeOut, similarity):# try:# self.PT = Pattern(imgFile)# self.PT = self.PT.similar(float(similarity))# self.SS.wait(self.PT, float(timeOut))# except FindFailed, err:# print "ERR: _wait"# raise AssertionError(err)# def click_object(self, imgFile, timeOut, similarity):# try:# self._wait(imgFile, timeOut, similarity)# self.SS.click(imgFile)# except FindFailed, err:# raise AssertionError("Cannot click [" + imgFile + "]")# def object_exists(self, imgFile, similarity, timeOut):# try:# self._wait(imgFile, timeOut, similarity)# except FindFailed, err:# raise AssertionError("Could not find [" + imgFile + "]")# def type_at_object(self, imgFile, txt, timeOut, similarity):# try:# self._wait(imgFile, timeOut, similarity)# self.SS.type(imgFile, txt)# except FindFailed, err:# raise AssertionError("Cannot type at [" + imgFile + "]")# def paste_at_object(self, imgFile, txt, timeOut, similarity):# try:# self._wait(imgFile, timeOut, similarity)# self.SS.paste(imgFile, txt)# except FindFailed, err:# raise AssertionError("Cannot paste at [" + imgFile + "]")if __name__ == '__main__':SRL = SikuliRemoteLibrary()RobotRemoteServer(SRL, *sys.argv[1:])
- 复制 C:\Program Files\Sikuli X\sikuli-script.jar 到 C:\robot\libs
- C:\robot\libs\sikuli-script.jar加入JAVA_PATH
- 运行远端服务 cmd进入c:\robot\libs 然后
Jython.bat SikuliRemoteLibrary.py
- 进入RIDE
- create 项目
- create testsuit
脚本如下:
*** Settings *** Documentation Integrating Selenium, Sikuli into Robot Framework Test SetupLogin To Yahoo Mail${user_name}${password} Test Teardown Tear Test Down Library Selenium2Library15# Selenium library Library Remotehttp://localhost:${port}# Sikuli Library Screenshot# Taking screenshots when a test fails *** Variables *** ${url}http://mail.yahoo.com# Yahoo mail URL ${browser}ff# Browser ${user_name} user_name# User name ${password} password# Password ${port} 8270# Default port number for the remote server ${data_path} c:\robot\data# Sikuli images ${similarity} 0.90# Used in Sikuli image comparison ${timeout}10# Time to wait for objects *** Testcases *** login To Yahoo Mail Test Case Wait Until Page Contains Elementyuhead-sform-searchfield${timeout} Input Textyuhead-sform-searchfieldENGLISH Object Exists${data_path}\search_box_left.png${similarity} *** Keywords *** Login To Yahoo Mail [Arguments]${user}${pass} [Documentation]This keyword logs user into Yahoo mail Open Browser${url}${browser} Wait Until Page Contains Elementusername Input Textusername${user} Input Passwordpasswd${pass} Click Button.save Wait Until Page Contains Elementtoolbar Click Object${data_path}\maximize.png Sleep1 Tear Test Down Run Keyword If Test FailedTake Screenshot Close All Browsers
应用sikuli remote library的python脚本如下
import sys from robotremoteserver import RobotRemoteServer from org.sikuli.script import * class SikuliRemoteLibrary: def __init__(self): self.SS = Screen() self.PT = Pattern() def _wait(self, imgFile, timeOut, similarity): try: self.PT = Pattern(imgFile) self.PT = self.PT.similar(float(similarity)) self.SS.wait(self.PT, float(timeOut)) except FindFailed, err: print "ERR: _wait" raise AssertionError(err) def click_object(self, imgFile, timeOut, similarity): try: self._wait(imgFile, timeOut, similarity) self.SS.click(imgFile) except FindFailed, err: raise AssertionError("Cannot click [" + imgFile + "]") def object_exists(self, imgFile, similarity, timeOut): try: self._wait(imgFile, timeOut, similarity) except FindFailed, err: raise AssertionError("Could not find [" + imgFile + "]") def type_at_object(self, imgFile, txt, timeOut, similarity): try: self._wait(imgFile, timeOut, similarity) self.SS.type(imgFile, txt) except FindFailed, err: raise AssertionError("Cannot type at [" + imgFile + "]") def paste_at_object(self, imgFile, txt, timeOut, similarity): try: self._wait(imgFile, timeOut, similarity) self.SS.paste(imgFile, txt) except FindFailed, err: raise AssertionError("Cannot paste at [" + imgFile + "]") if __name__ == '__main__': SRL = SikuliRemoteLibrary() RobotRemoteServer(SRL, *sys.argv[1:])
3、搭建持续集成环境CI(Continuous Intergration)
新建 [C:\robot\arg] 存放要传入的变量
新建C:\robot\argarg.txt 内容如下:
–variable user_name:user_name
–variable password:pass_word
–outputdir ..\out新建 C:\robot\run
创建 run.bat内容如下:
call pybot.bat –argumentfile C:\robotarg\arg.txt C:\robot\suites\test.txt
安装Jenkins
- 下载地址:jenkins.war
- 运行jenkins
java -jar jenkins.war --httpPort=80
Robotframwork集成Jenkins Plugin
- 下载https://code.google.com/p/robotframework-javatools/downloads/detail?name=robotframework.hpi
- 运行java -jar jenkins.war -httpport=80
- 浏览器访问http://localhost:8080
- 进入manage Jenkins
- 进入Mange Plugins
- 点击 Advanced
- 点击Upload Plugins选择robotframework.hpi后点击upload
- 重启jenkins
创建Jenkins 任务
- 进入http://localhost:8080
- 点击NewJob
- 输入 任务名称,选择”Build a free-style software project”
- 选择 Add build step
- 点击 Execute windows batch command
输入 :
cd C:\robot\run
call run.bat选择Add post-build action
- 点击Publish Robot Framework test results
- 设置”Directory of Robot output” as “..\out”
- 设置 “Log/Report link” as “log.html”
- 设置Output xml name” as “output.xml”
- 设置 “Report html name” as “report.html”
- 设置 “Log html name” as “log.html”
到现在,我们已经jenkins已经可以开始工作了。确保Sikuliremotelibrary已经运行,现在可以开始build测试任务了。
- Sikuli Selenium Robotframework 集成
- selenium集成sikuli
- sikuli-maven,selenium集成环境
- Sikuli Selenium Robot Framework Integration
- selenium结合Sikuli-Script使用
- sikuli在selenium的应用
- RobotFramework+Selenium视频教程
- robotframework+selenium环境安装
- robotframework+selenium安装配置
- robotFramework 与testlink集成
- selenium结合最新版的sikuli使用
- Sikuli 结合selenium的一些使用
- RobotFramework+Selenium实现web自动化
- selenium + robotframework的运行原理
- RF+Selenium2Library+Sikuli集成环境搭建
- sikuli
- Sikuli
- Ubuntu下搭建Robotframework+Selenium环境
- sphinx支持php
- java与数据库的链接
- memcache分布式
- php 环境安装(源码包)
- 栈&&括号匹配
- Sikuli Selenium Robotframework 集成
- Eclipse 查看项目部署位置
- hdu 1016 prime ring 简单dfs输出
- memcache的集群、高可用
- Partition-Wise Join of List-Partitioned Tables
- cell属性改变后又快速恢复初始化属性的解决方法
- oracle分区表之交换分区 altertable exchange partition with table
- -----oc基础语法---oc特有语法(1)
- Ubuntu安装Emacs出现到依赖问题及解决方案