Robot Framework 使用總結

最近項目上使用了RF快速實現了一些驗收測試的自動化case,感受不錯,很好用,下面就記錄一下使用RF實現自動化的過程。python

 

什麼是RF?

RF是一種測試框架,幫助測試人員在其框架下快速實現驗收測試的自動化。提供不少的擴展庫供你使用,在沒有任何一種語言編程基礎的狀況下也能實現一些自動化測試用例。web

說白了,任何一種框架的做用就是幫你完成一些基礎的工做,使你更加關注於要測試的業務邏輯,而不是關心技術細節,這些技術細節包括用例如何運行、如何組織、日誌怎麼記錄,怎麼展示,如何與CI集成等等。編程

使用RF框架與Jenkins CI工具結合,能夠很容易的實現測試的遠程部署、運行與結果展示。比起重寫造輪子,本身寫一套系統,這種方式仍是快得多,最適合剛剛起步的項目。json

 

RF能作什麼?

RF能作什麼取決於使用什麼樣的擴展框架,RF提供的默認內置庫與外部擴展庫,固然也能夠本身寫擴展庫來定製功能。基本提供的庫已經能夠知足通常的測試需求了,包括對手機端、網頁端的自動化測試,還有API接口的測試。app

 

編寫RF文件

RF文件一般以robot爲後綴名,而且提供了不少的編輯工具,方便的進行robot文件的編輯。我使用的是pycharm的RF插件進行編輯,由於須要使用python寫大量的擴展庫,因此在pycharm裏面統一進行robot與py文件的編輯,仍是很方便的。或者使用官方的RIDE也是很好的選擇,純圖形化界面,方便團隊沒有開發經驗的人蔘與其中。框架

 

RF文件的結構

先看一個RF文件示例:
函數

如上所示,一個RF文件一般包括三個節點: 工具

  • Settings節點:
    1. 設置此test suite的setup與tearndown操做
    2. 此test suite 中每一個test case的setup與tearndown操做
    3. 指定測試模板test template
    4. 指定此test suite引用的資源文件的位置
    5. 使用Library關鍵字引用RF標準庫,或者自定義庫:
    測試

  • Test Cases節點:
    1. 能夠定義一個普通的測試用例
    2. 也能夠調用模板,並給模板傳入它所須要的參數
    3. 測試用例裏面所調用的關鍵詞可能來自下面三個地方:
    * 當前test suite文件的keywords節點中定義的keyword
    * Setttings節點指定的資源文件中所定義的keyword
    * 內建的BuiltIn庫中定義的keyword ui

  • Keywords節點:
    1. keyword能夠理解爲一個公用的方法,供test case使用
    2. keyword能夠傳入參數,返回結果
    3. RF也提供不少邏輯判斷IF,循環FOR等關鍵詞

 

 

Resource資源文件的結構

其實resource文件與普通robot文件沒多大區別,只不過它是被導入的庫文件,一般用來定義一些公用的變量和keywords:

 

 

編寫本身的Library文件

RF運行使用不少語言編寫本身的Library文件,這裏選擇python編寫,首先看一下對已存在的庫文件的擴展

對selenium2library庫文件的擴展:

 1 # 導入Selenium2Library模塊
 2 from Selenium2Library import Selenium2Library模塊
 3 from selenium.common.exceptions import StaleElementReferenceException
 4 import time
 5 
 6 
 7 def _get_table_field_value(element, field):
 8     return element.find_element_by_xpath("./td[@field='" + field + "']").text.strip()
 9 
10 # 繼承Selenium2Library
11 class CustomSeleniumLibrary(Selenium2Library):
12     def get_table_row_count(self, table_locator):
13         attempts = 0
14         while True:
15             try:
16                 table = self._table_element_finder.find(self._current_browser(), table_locator)
17                 return len(table.find_elements_by_xpath("./tbody/tr"))
18             except StaleElementReferenceException:
19                 time.sleep(1)
20                 if attempts >= 1:
21                     raise AssertionError("Cell in table %s could not be found." % table_locator)
22                 else:
23                     pass
24             attempts += 1
25 
26     def get_user_search_results(self, table_locator, row_index):
27         table = self._table_element_finder.find(self._current_browser(), table_locator)
28         ret = []
29         if table is not None:
30             rows = table.find_elements_by_xpath("./tbody/tr")
31             if len(rows) <= 0:
32                 return None
33             row_index = int(row_index)
34             if len(rows)-1 < row_index:
35                 raise AssertionError("The row index '%s' is large than row length '%s'." % (row_index, len(rows)))
36             for row in rows:
37                 dic = {
38                     'userId': _get_table_field_value(row, 'userId'),
39                     'nickName': _get_table_field_value(row, 'nickName'),
40                     'realName': _get_table_field_value(row, 'realName'),
41                     'mobile': _get_table_field_value(row, 'mobile'),
42                     'idNo': _get_table_field_value(row, 'idNo'),
43                     'userType': _get_table_field_value(row, 'userType'),
44                     'verifyUserStatus': _get_table_field_value(row, 'verifyUserStatus'),
45                     'operator': _get_table_field_value(row, 'operater'),
46                     'operateTime': _get_table_field_value(row, 'operateTime'),
47                 }
48                 ret.append(dic)
49             return ret[row_index]
50         else:
51             return None
52 
53     ...

 

 

建立全新的庫文件:

 1 # -*- coding: utf-8 -*-
 2 
 3 from libs.DB_utils.utils import *
 4 from libs.request_utils import utils
 5 from libs.request_utils import flow_task_manage
 6 from libs.global_enum import *
 7 from libs.model import user_search_result
 8 from robot.libraries.BuiltIn import BuiltIn
 9 import time
10 
11 
12 class VerifyLibrary(object):
13 
14     def __init__(self, base_URL, username, dubbo_web_base_URL=None):
15         self.base_URL = base_URL
16         self.username = username
17         self.request_utils = utils.RequestUtil(base_URL, username)
18         self.flow_task_request_utils = flow_task_manage.FlowTaskManage(base_URL, username)
19         self.built_in = BuiltIn()
20         if dubbo_web_base_URL is not None:
21             self.dubbo_web_request_utils = utils.RequestUtil(dubbo_web_base_URL)
22 
23     def update_verify_user_role(self, email, dept_id, role_id, amount_limit=5000):
24         real_name = get_verify_user_name_by_email(email)
25         verify_user_id = get_verify_user_id_by_email(email)
26         self.request_utils.login()
27         response = self.request_utils.update_verify_user(real_name, verify_user_id, amount_limit, dept_id, role_id)
28         return response.json()

 

 

注意VerifyLibrary的構造函數,須要最少傳入兩個參數,這是在robot文件引用此庫文件的時候傳入的:

 

 

RF框架與Jenkins CI集成

使用Jenkins來運行RF寫的test case很簡單,首先須要在Jenkins上安裝RF擴展插件:

而後,使用pybot命令行去運行寫好的RF測試用例:

最後執行完測試後,能夠在jenkins上很好的解析出測試結果的走勢與具體的每一個build的測試結果:

相關文章
相關標籤/搜索