CMap=CtrlMap 控件地图
意图:①抽象控件:将 UI 自动化开发中的 “控件逻辑” 与 “控件信息” 进行隔离 ②自动回归:“控件信息” 有变化时可快速的识别出来进行适配。
主要解决:①简化 “控件逻辑” ②降低由 “控件信息” 变化时引起的适配成本。
如何解决:①控件抽象化:例如在 WEB 自动化中,将"text_field/radio/checkbox/select_list"这些抽象为一种控件,
那么假如有 20 个页面、平均每个页面 10 个控件,原本需要写 20*10 个控件逻辑的,用 CMap 模式后能简化为 20*1 个控件逻辑。
②地图化:例如有一个控件的对象名为"AccoCapac.Line_FastEdt_Name",可以知道它的跳转路径为"AccoCapac->AccoCapac.Line->AccoCapac.Line_FastEdt"
应用实例 1-抽象控件(以 TesterHome 的登录页面为例,先贴出部分关键代码):
from Selenium2Library import Selenium2Library
class CMap(object):
""" Singleton_Pattern extend Selenium2Library """
...
# end class
class Signin(object):
URL = CMap('https://testerhome.com/account/sign_in', CMap.NONE)
Commit = CMap('xpath=//input[@name="commit"]', CMap.BUTTON)
Remember = CMap('xpath=//input[@id="user_remember_me"]', CMap.CHECKBOX)
User = CMap('xpath=//input[@id="user_login"]', CMap.TEXT_FIELD)
Pwd = CMap('xpath=//input[@id="user_password"]', CMap.TEXT_FIELD)
FLAG = Commit # a special Ctrl<wait_until_element_is_visible>
@staticmethod
def GOTO_():
Signin.URL.go_to()
# end class
Signin.URL.open_browser(browser='firefox') # create browserObj<Singleton_Pattern>, and open
#Signin.GOTO_()
Signin.FLAG.wait_until_element_is_visible()
mysets = {'User': '123', 'Pwd': '456', 'Remember': True}
for ictrl, ivalue in mysets.items():
print(' ictrl=%r ivalue=%r' % (ictrl, ivalue))
getattr(Signin, ictrl).Set(ivalue)
ifact = getattr(Signin, ictrl).Get()
print(' ictrl.Get()=%r' % ifact)
assert ifact == ivalue, "ifact==%r, but=%r" % (ivalue, ifact)
应用实例 2-自动回归(下图是之前一个项目中,全自动生成的 “控件信息” 回归代码):
# 补充: 上面 class CMap 的完整代码:
class CMap(object):
""" Singleton_Pattern extend Selenium2Library """
B = None # browserObj<Singleton_Pattern>
def __init__(self, locator, ctrlCls, **kw):
if CMap.B is None:
CMap.B = Selenium2Library(**kw)
self._locator = locator
self._ctrlCls = ctrlCls
def __getattr__(self, attr):
return _CMapHelper_BrowserDo(method=attr, arg0=self._locator)
# Abstract_Methods
def Set(self, value=None):
self._ctrlCls(opt='Set', locator=self._locator, value=value)
def Get(self, value=None):
return self._ctrlCls(opt='Get', locator=self._locator)
# Abstract_Methods's real_method
@staticmethod
def __TEXT_FIELD__(opt, locator, value=None):
if opt == 'Set':
CMap.B.input_text(locator, value)
elif opt == 'Get':
return CMap.B.get_webelement(locator).get_attribute('value')
@staticmethod
def __BUTTON__(opt, locator, value=None):
if opt == 'Set':
CMap.B.click_element(locator)
elif opt == 'Get':
return CMap.B.get_text(locator)
@staticmethod
def __CHECKBOX__(opt, locator, value=None):
""" value==is_selected() # True/False """
elementGet = CMap.B.get_webelement(locator)
if opt == 'Set':
return elementGet.click() if elementGet.is_selected()!=value else None
elif opt == 'Get':
return elementGet.is_selected()
# ctrlCls
TEXT_FIELD = __TEXT_FIELD__
BUTTON = __BUTTON__
CHECKBOX = __CHECKBOX__
NONE = None
# end class
class _CMapHelper_BrowserDo(object):
def __init__(self, method, arg0):
self.method = method
self.arg0 = arg0
def __call__(self, *args, **kw):
return getattr(CMap.B, self.method)(self.arg0, *args, **kw)
# end class