Robot 自動化框架內置提供了一些library,如OperatingSystem(包含一些常用的的文件操作關鍵字,如copy文件,創建目錄),Telent,Screenshot,String,另外還有一些第三提供的library ,比較常用的如SeleniumLibrary,用於Web自動化測試。但如何定制適合自己項目需求的library呢?
- 支持的編程語言
支持的語言包括:Python & Java. Robot框架本身就是有Python開發,理所當然支持Python來實現library。當運行時,選擇了Jybot,那么你也可以用Java來實現library。
- Robot框架提供了三種不同的實現library的API
- Static API
這是最簡單的方式,實現一個python module,在這個module里面有一些functions,或則在module里面有個python 的類,里面有一些方法。通過Java來實現的話,提供一個Class,里面有些public 的method。當import 這個python module, python class或java class這些method就會自動映射為keyword。
有一點需要注意的是,如何判斷一個keyword的狀態,當執行這個keyword時,是Pass,還是Fail呢?如果在方法里面拋出了異常,那么這個keyword的狀態就是Fail.
下面先來看看之前寫的一個library,截取了一段代碼:
class RemoveSMDLibrary(RuntimeError):
'''A test library providing keyword for SMLD uninstallation related tasks.
'''
#Test library scope
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
#specifiying library version
ROBOT_LIBRARY_VERSION = '0.2'
ROBOT_EXIT_ON_FAILURE = True
def __init__(self,is_windows=-1):
self._is_windows=is_windows
sys.path.append("MyConfigParser.py")
logger.console('Add MyConfigParser.py file into Python path!')
def get_smdsys_path(self,msg=None):
logger.console('Get smdsys.ini File...')
winsmdsysPath = os.path.expandvars('$systemroot\\smdsys.ini')
nonwinsmdsysPath = "/etc/smdsysV2.ini"
if os.path.isfile(winsmdsysPath):
self._is_windows = 1
self._smdsyspath = winsmdsysPath
elif os.path.isfile(nonwinsmdsysPath):
self._is_windows = 0
self._smdsyspath = nonwinsmdsysPath
if self._is_windows ==-1:
if not msg:
msg="File '%s' does not exist" %winsmdsysPath
raise AssertionError(msg)
def _get_windows_path(self,smdsysPath):
config = ConfigParser()
config.read(smdsysPath)
productPath = config.get("SMDConf","ProductPath")
notesiniPath = config.get("DomSvr0","DomSvr0NotesIniPath")
return productPath,notesiniPath
def _get_nonwindows_path(self,smdsysPath):
config = ConfigParser()
config.read(smdsysPath)
SMDInstanceList = config.get("SMDInstances","SMDInstanceList")
productPath = config.get(SMDInstanceList,"ProductPath")
DomSvr = config.get(SMDInstanceList,"DomSvrISMDSecs")
notesiniPath = config.get(SMDInstanceList,DomSvr)
return productPath,notesiniPath
def get_notesini_path(self):
if self._is_windows == 1:
return self._get_windows_path(self._smdsyspath)
else:
return self._get_nonwindows_path(self._smdsyspath)
當一個Pyhton class中,會忽略以_開頭的function,不認為是keyword。
看一下實際應用在ride中如何導入:
因為Python module名和class的名字是一樣的,所以可以直接用module名,如果不一樣,就需要以這樣的格式來導入mymodule.myclass來導入library。看下這個參數,這個參數是傳遞給構造函數的。
如果你的library導入成功了,那么這些library中的keyword顏色就會變成這樣,把鼠標放上去,按ctrl就是出現提示。
2. Dynamic API
在keywords狀態,logging和返回值方面,dynamic library API 和static library API是一樣的。唯一的不同是Robot Framework如何判別導入的library里面的keywords。static library API是通過反射機制來實現的,dynamic library采用一種特別的方式。
就static library keywords而言,所有的keywords必須在一個class,或modules中。而dynamic library API,你的keywords可以分布在不同的class中。
Dynamic API中必須實現兩個方法:run_keyword 和 get_keyword_names,Robot Framework通過這兩個方法,得知在library實現了哪些keyword,怎么調用這些keyword.
有個第三方的庫JavalibCore,實現了run_keyword和get_keyword_names,用戶只需要實現自己的keyword就可以了。這里就不舉例子了,建議看javalibcore的源碼。
3. Hybrid API
Hybrid library API是間於static API, dynamic API之間的。
和dynamic library API 一樣,你需要提供一個get_keyword_names方法,來返回這個library 可以提供的所有keywords的名字。還有一點,Hybrid library API 只適用於Python,對於Java不可以的。
下面之間看一個例子,這個library的實現就是采用的Hybrid API方式。
class Smdauto(RuntimeError):
'''A test library providing keywords for SMLD Automation
'''
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
ROBOT_LIBRARY_VERSION = '0.1'
ROBOT_EXIT_ON_FAILURE = True
def __init__(self):
locator=KeywordsServiceLocator()
#kw={ 'tracefile' : sys.stdout, 'auth' : ( AUTH.httpbasic, 'test1', '111111' ) }
#self._port_type=locator.getKeywords(**kw)
self._port_type=locator.getKeywords()
self._notes_mail = None
self._lib_kws=self._notes_mail_kws=None
def get_keyword_names(self):
return self._get_library_keywords() + self._get_notes_mail_keywords()
def _get_library_keywords(self):
if self._lib_kws is None:
self._lib_kws = [ name for name in dir(self)
if not name.startswith('_') and name != 'get_keyword_names'
and inspect.ismethod(getattr(self, name)) ]
return self._lib_kws
def _get_notes_mail_keywords(self):
if self._notes_mail_kws is None:
notes_mail=self._get_notes_mail()
self._notes_mail_kws=[ name for name in dir(notes_mail)
if not name.startswith('_') and inspect.ismethod(getattr(notes_mail, name)) ]
return self._notes_mail_kws
def __getattr__(self,name):
if name not in self._get_notes_mail_keywords():
raise AttributeError(name)
notes_mail = self._notes_mail is None and self._get_notes_mail() or self._notes_mail
print dir(notes_mail)
return getattr(notes_mail,name)
def _get_notes_mail(self):
return NotesMail()
其實,Hybrid API的實質就是應用Python中委派機制,即__getattr__內置函數,當嘗試調用一個不存在的方法時,Python會默認調用__getattr__。
首先,先來看get_keyword_names,這個方法返回了這個libray包含的所有的keywords,它調用了有兩個method,第一個返回這個class中所有不是以_開頭的方法名,另一個返回一個額外的class中的方法。當執行的method不在這個class中的時候,就會調用__getattr__,從而實現委派調用。

