Robot Framework 自動化框架 - 定制自己的library


Robot 自動化框架內置提供了一些library,如OperatingSystem(包含一些常用的的文件操作關鍵字,如copy文件,創建目錄),Telent,Screenshot,String,另外還有一些第三提供的library ,比較常用的如SeleniumLibrary,用於Web自動化測試。但如何定制適合自己項目需求的library呢?

  • 支持的編程語言

支持的語言包括:Python & Java. Robot框架本身就是有Python開發,理所當然支持Python來實現library。當運行時,選擇了Jybot,那么你也可以用Java來實現library。

  • Robot框架提供了三種不同的實現library的API
  1. 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中如何導入:

2012-09-15_231402

因為Python module名和class的名字是一樣的,所以可以直接用module名,如果不一樣,就需要以這樣的格式來導入mymodule.myclass來導入library。看下這個參數,這個參數是傳遞給構造函數的。

2012-09-15_231424

如果你的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__,從而實現委派調用。

 

參考資料:http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.4#remote-library-interface


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM