跨端跨平台测试

QT4W的Browser抽象

QT4W将浏览器抽象为一个IBrowser对象,在该对象中定义了两个操作:

  • 打开一个URL指定的页面open_url()
  • 在打开的页面中查找和指定url匹配的页面。

在实现自己的IBrowser对象后,就可以通过该对象来操作浏览器。关于如何封装IBrowser接口参见Browser实现。 为了进一步消除,不同浏览器调用时的差异,QT4W提供了Browser类,该类继承自IBrowser。该类能够根据注册的浏览器名,获取到对应的实现实例。在QT4W中一般都通过,该类来调用具体的IBrowser实现。该类的实现,如下所示:

class Browser(IBrowser):
    '''对外的浏览器类
    '''
    browser_dict = {}  # 存储浏览器类型与浏览器类的对应关系
    def __init__(self, browser_name=None):
        '''创建具体的Browser实例
        :param browser_name: 要创建的浏览器类型
        :type browser_name:
        '''
        self._browser_name = browser_name
        self._browser = self._get_browser_cls()
    
    def _get_browser_cls(self):
        '''获取浏览器类
        '''
        if not self._browser_name:
            # 随机选择浏览器
            self._browser_name = random.choice(self.browser_dict.keys())
        browser_cls_path = self.browser_dict.get(self._browser_name)
        if not browser_cls_path:
            raise TypeError('Browser %s is not registered' % self._browser_name)
        logger.info('[Browser] Current browser type is %s' % self._browser_name)
        module = __import__('.'.join(browser_cls_path.split('.')[:-1]))
        for item in browser_cls_path.split('.')[1:]:
            module = getattr(module, item)
        return module()
    
    @staticmethod
    def register_browser(browser_name, browser_cls_path):
        '''注册浏览器
        
        :param browser_name:     浏览器名称
        :type browser_name:      string
        :param browser_cls_path: 浏览器类路径
        :type browser_cls_path:  string
        '''
        Browser.browser_dict[browser_name] = browser_cls_path
        
    def open_url(self, url, page_cls=None):
        '''打开一个url,返回page_cls类的实例
        :param url: 要打开页面的url
        :type url:  string
        :param page_cls: 要返回的具体WebPage类,为None表示返回WebPage实例
        :type page_cls: Class
        '''
        return self._browser.open_url(url, page_cls)
    
    def find_by_url(self, url, page_cls=None, timeout=10):
        '''在当前打开的页面中查找指定url,返回WebPage实例,如果未找到,返回None
        :param url: 要查找的页面url
        :type url:  string
        :param page_cls: 要返回的具体WebPage类,为None表示返回WebPage实例
        :type page_cls: Class
        :param timeout: 查找超时时间,单位:秒
        :type timeout: int/float
        '''
        page = self._browser.find_by_url(url, page_cls, timeout)
        if page == None: raise RuntimeError('Can\'t find page %s in browser %s' % (url, self._browser_name))
        return page

register_browser方法实现了浏览器名和浏览器封装实现的对应关系,并将该对应关系以字典的形式存储在类变量browser_dict中;_get_browser_cls方法会根据browser_dict变量中的信息来返回浏览器名的对应浏览器实现的Object对象。如果初始化的时候未传入浏览器名,会随机选择一个已注册的浏览器实现。如果未注册任何浏览器则会报错。这里的隐式的要求,在实现自己的IBrowser封装时,初始化时没有必传的参数。在QT4W自动化中,推荐使用该类的实例来打开或者查找页面。

Browser用法示例

在获取Browser类的实例前,先需要使用Browser.register_browser注册浏览器,在注册时,传入了两个参数:浏览器名和XXBrowser类的路径。然后再初始化Browser对象时传入注册的浏览器名,获取指定的浏览器对象,使用方法如下所示:

#注册浏览器并获取浏览器实例
 Browser.register_browser('TestBrowser', 'BrowserPath')
 browser=Browser('TestBrowser')
 
 #打开URL
 browser.open_url(https://qtacore.github.io/qt4w/demo.html,PageClass)

说明: 此处注册时传入的第二个参数指示浏览器实现所在的class,此处传入的TestBrowser给出的是TestBrowser浏览器封装的实现。

实现WORA(Write Once Run Anywhere)示例

下面以DemoPage为示例来说说明,如何使用使用Browser类实现一份QT4W测试用例,仅需做少许修改便可以在多个端上运行。

Android端执行DemoPage测试

在Android端,要想使用QT4W需要QT4A的支持。在Android端我们使用QT4A中封装的系统自带的浏览器来检查Demo页面是否运行正常。因此,我们实现了如下所示的测试用例:

class DemoTest(AndroidTestBase):
    '''QT4W示例测试用例
    '''
    owner = "testowner"
    timeout = 5
    priority = AndroidTestBase.EnumPriority.High
    status = AndroidTestBase.EnumStatus.Ready
    
    def pre_test(self):
        Browser.register_browser('TestBrowser', 'qt4a.browser.QT4ABrowser') 
        
    def run_test(self):
        self.startStep('1.设置信息并提交')
        browser = Browser("TestBrowser")
        page = browser.open_url('https://qtacore.github.io/qt4w/demo.html', DemoPage)
        page.set_name("qta")
        page.set_female()
        page.set_age(str(20))
        page.set_company("tencent")
        page.submit()

这里在pre_test中,将TestBrowser注册为QT4A中的QT4ABrowser。在具体的测试用例中,使用Browser(“TestBrowser”)获取到对应的浏览器实例类似执行DemoPage测试。

IOS端执行DemoPage测试

在IOS端,可以直接复制上述代码,然后修改一下浏览器注册部分的内容,将测试的基类改成使用IOS的测试基类即可运行。修改后如下所示:

class DemoTest(iTestCase):
    '''IOS QT4W示例测试用例
    '''
    owner = "testowner"
    timeout = 5
    priority = iTestCase.EnumPriority.High
    status = iTestCase.EnumStatus.Ready
    
    def pre_test(self):
        Browser.register_browser('TestBrowser', 'qt4i.app.Safari') 
        
    def run_test(self):
        self.startStep('1.设置信息并提交')
        browser = Browser("TestBrowser")
        page = browser.open_url('https://qtacore.github.io/qt4w/demo.html', DemoPage)
        print page.url
        page.set_name("qta")
        page.set_age(str(20))
        page.set_company("tencent")
        page.set_female()
        page.submit()

这里仅仅是将TestBrowser重新注册为了qt4i.app.Safari,同时为了用例能够在IOS平台上顺利执行,需要将DemoTest的测试基类改为继承QT4I提供的iTestCase。即可在IOS上顺利执行。

高级用法

更加方便的用法是在各端分别封装一个测试基类,并在测试基类中注册对应的浏览器。例如Android端可以封装如下测试基类,继承自Android自动化的测试基类AndroidTestBase:

class BrowserTestCase(AndroidTestBase):
    '''Browser测试用例基类
    '''
    def pre_test(self):
        super(BrowserTestCases, self).pre_test()
        # 注册Android浏览器类路径
        Browser.register_browser('TestBrowser', 'qt4a.browser.QT4ABrowser')

IOS端同样也封装一个BrowserTestCase,继承IOS自动化的测试基类iTestCase,如下:

class BrowserTestCase(iTestCase):
    '''Browser测试用例基类
    '''
    def pre_test(self):
        super(BrowserTestCases, self).pre_test()
        # 注册IOS浏览器类路径
        Browser.register_browser('TestBrowser', 'qt4i.app.Safari') 

经过如此封装后,Android和IOS两端的DemoPage自动化便可统一使用下面的测试用例:

class DemoTest(BrowserTestCase):
    '''QT4W示例测试用例
    '''
    owner = "testowner"
    timeout = 5
    priority = BrowserTestCase.EnumPriority.High
    status = BrowserTestCase.EnumStatus.Ready
    
    def run_test(self):
        self.startStep('1.设置信息并提交')
        browser = Browser("TestBrowser")
        page = browser.open_url('https://qtacore.github.io/qt4w/demo.html', DemoPage)
        page.set_name("qta")
        page.set_female()
        page.set_age(str(20))
        page.set_company("tencent")
        page.submit()

在上面的示例中,在不同端上,需要手动的去修改所引入的BrowserTestCase,Android端引入Android端封装的BrowserTestCase,IOS端运行时,需要修改为IOS端的BrowserTestCase封装。如果不想所动修改的话,可以在测试用例前使用__import__方法动态引入,package.moudle指代BrowserTestCase的路径,如果两端的实现,在同一路径下,便不需做任何更改。

BrowserTestCase=__import__(package.moudle)

跨终端的具体用例写法可以参考QT4WDemo项目

内嵌页面如何实现WORA

内嵌页面,实际上也是一个隐形的浏览器,内嵌页面实现WORA,同样必须为内嵌页面封装IBrowser类,然后使用Browser.register_browser(),方法注册该内嵌页面的浏览器封装即可。使用方式和上面相同。如何实现IBrowser封装,Android端可以参考QT4ABrowser的实现,IOS端可以参考Safari的实现。