zoukankan      html  css  js  c++  java
  • 第六章 自动测试实施(下)

    ---Web自动化测试之Webdriver(python)--从零到熟练(系列)

    6.6 编写自动化测试用例

       我们规划好了代码架构,就可以编写具体的测试用例了。首先,我们写登录的测试用例,在写自动化测试用例的时候,我们要先写一下公用函数类。根据需要,我们写了三个通用的类放到CommonFunction文件夹下:WebDriverHelp用来存放所有页面操作用到公用方法;QT_Operations 用来存放具体操作功能块,如登录,退出等;DataOperations用来存放所有数据操作,用来读取xml中的测试数据。

    然后我们在TestCases文件夹下编写登录的测试用例TestCase_QT_Login.py执行具体的测试操作,验证测试用例执行是否成功。

    并把测试用例需要的测试数据,放到TestData文件夹下TestCase_QT_Login.xml文件中。如果网站有所变化,可以修改这个里面的测试数据,从而减少代码维护的成本。

    6.6.1 WebDriverHelp类的内容

    WebDriverHelp是我们所有测试用例能用到的方法,可以在编写测试过程中不断抽象出来,写到这个类里面,相当于对Webdriver再次做了一下封装。

    下面是部分代码,以供大家参考:

    @author:songxianfeng

    @copyright: V1.0

    '''

    import time

    import datetime

    from selenium import webdriver

    from selenium.webdriver.support.ui import Select

     

    from selenium.common.exceptions import NoSuchElementException

    from selenium.webdriver.common.action_chains import ActionChains

    from selenium.webdriver.common.keys import Keys

    global G_WEBDRIVER, G_BROWSERTYTPE,DRIVER

     

    class WebDriverHelp(object):

        '''

        本类主要完成页面的基本操作,如打开指定的URL,对页面上在元素进行操作等

        '''

     

        def  __init__(self,btype="close",atype="firefox",ctype="local"):

            '''

            根据用户定制,打开对应的浏览器

            @param bType: 开关参数,如果为close则关闭浏览器

            @param aType:打开浏览器的类型,如chrome,firefox,ie等要测试的浏览器类型

            @param cType:打开本地或是远程浏览器: local,本地;notlocal:远程        '''

            global DRIVER

            if(  btype == "open" ):           

                if(  atype == "chrome" ):

                    if(ctype == "local"):   

                        DRIVER = webdriver.Chrome()

                        DRIVER.maximize_window()

                    elif(ctype == "notlocal"):                

                        DRIVER = webdriver.Remote(command_executor='http://124.65.151.158:4444/wd/hub', desired_capabilities=webdriver.DesiredCapabilities.CHROME)

                        DRIVER.maximize_window()                   

                elif(  atype == "ie" ):

                    if(ctype == "local"): 

                        DRIVER = webdriver.Ie()

                        DRIVER.maximize_window()

                    elif(ctype == "notlocal"):                  

                        DRIVER = webdriver.Remote(command_executor='http://124.65.151.158:4444/wd/hub',desired_capabilities=webdriver.DesiredCapabilities.INTERNETEXPLORER)

                        DRIVER.maximize_window()                   

                elif(  atype == "firefox" ):

                    if(ctype == "local"):

                        DRIVER = webdriver.Firefox()

                        DRIVER.maximize_window()

                    elif(ctype == "notlocal"):                  

                        DRIVER = webdriver.Remote(command_executor='http://10.20.5.56:4444/wd/hub',desired_capabilities=webdriver.DesiredCapabilities.FIREFOX)

                        DRIVER.maximize_window() 

                                      

            self.DRIVER = DRIVER

     

        def  setup(self,logintype):

            '''

            定制测试URL

            @param loginplace: 指定测试的URL qiantai:前台测试地址,houtai:后台测试地址,zhengshi:正式环境测试地址

            ysh:原始会测试地址 zhengshiysh:正式原始会测试地址

            '''

            try:

                qiantai_url = "http://test.zhongchou.cn"

                ysh_url = "http://test.ysh.zhongchou.cn" 

                houtai_url = "http://test.admin.zhongchou.cn"

                zhengshi_url = "http://www.zhongchou.cn"

                zhengshi_ysh_url = "http://ysh.zhongchou.cn"

     

                if(logintype=="qiantai"):

                    self.DRIVER.get(qiantai_url)

                elif(logintype=="houtai"):

                    self.DRIVER.get(houtai_url)

                elif(logintype=="zhengshi"):

                    self.DRIVER.get(zhengshi_url)

                elif(logintype=="ysh"):

                    self.DRIVER.get(ysh_url)

                elif(logintype=="zhengshiysh"):

                    self.DRIVER.get(zhengshi_ysh_url)

                else:

                    print '路径错误!'

                self.DRIVER.implicitly_wait(1)

            except NoSuchElementException:

                print '您选择的测试地址出错!!'      

        def  teardown(self):

            '''

            关闭浏览器

            '''       

            self.DRIVER.quit()

                    

        def  geturl(self,url):

            '''

            打开指定的网址

            @param url: 要打开的网址

            '''

            self.DRIVER.get(url)    

    def  selectvalue(self,findby,select,selectvalue):

            '''

            通过定制定位方法和要选择项的文本,选择指定的项目

            @param findby:定位方法,如:byid,byname,byclassname

            @param select: 要执行选择操作的下拉框句柄

            @param selectvalue: 下拉框中要选择项的文本

            '''

            if(findby == 'byid'):

                select = Select(self.findelementbyid(select))

            elif(findby =='byname'):

                select = Select(self.findelementbyname(select))

            elif(findby =='byclassname'):

                select = Select(self.findelementbyclassname(select))

            select.select_by_visible_text(selectvalue)

          

        def  inputvalue(self,findby,elmethod,value):

            '''

            通过定制定位方法,在输入框中输入值

            @param findby: 定位方法,如:byid,byname,byclassname,byxpath

            @param elmethod: 要定位元素的属性值 ,如:id,name,class name,xpath

            @param value: 要给文本框输入的值

            '''

            if(findby == 'byid'):

                self.findelementbyid(elmethod).send_keys(value)

            elif(findby == 'byname'):

                self.findelementbyname(elmethod).send_keys(value)

            elif(findby =='byclassname'):

                self.findelementbyclassname(elmethod).send_keys(value)

            elif(findby == 'byxpath'):

                self.findelementbyxpath(elmethod).send_keys(value)

          …… 

    上面的代码都有很详细的注释,在此就不一一讲述了。

    6.6.2 QT_Operations类的内容

    QT_Operations类是业务相关的公用功能块的封装,以便增加函数的公用性,减少代码量。例如,登录,在很多测试用例的第一步都需要先登录再操作的。所以你可以抽像出测试用例中的功能模块,封装后放到这个类中。

    QT_Operations类的部分代码展示:

    #-*- coding: UTF-8 -*-

    '''

    Created on 2014-12-15

    @author:songxianfeng

    @copyright: V1.0

    '''

    import time

    import win32api

    import win32con

     

    from WebDriverHelp import WebDriverHelp

     

    class QT_Operations(object):

        '''

        众筹前台相关操作

        '''

        def login(self,userName,passwd):

            '''

            从首页直接登录

            @param userName: 用户名

            @param passwd:密码

            @param type1:指示登录方式,1为从主页登录,2,从登录页登录

            '''

            WebDriverHelp().clickitem("byclassname", "Js-showLogin")

            time.sleep(3)

            WebDriverHelp().clearvalue('byname','username')

            WebDriverHelp().inputvalue('byname','username',userName)

            WebDriverHelp().clearvalue('byname','user_pwd')

            WebDriverHelp().inputvalue('byname','user_pwd',passwd)

            time.sleep(1)

            WebDriverHelp().clickitem("byclassname", "a-btn")

            time.sleep(5)

           

        def logout(self):

            '''

            退出登录

            '''

            WebDriverHelp().geturl("http://www.zhongchou.cn/usernew-loginout")

    ……

    展示部分只包含了登录和退出功能,其他的功能可以根据测试用例的需要进行添加。

    6.6.3 DataOperations类的内容

       DataOperations类是对测试数据进行读取的操作,我们是用xml来存放测试数据的,所以测试用例执行的时候,需要先将测试数据读取出来,传递给相应的函数来对测试用例进行执行。然后根据执行的结果,判断测试用例是否执行成功。

    DataOperations的内容:

    #-*- coding: UTF-8 -*-

    '''

    Created on 2014-12-15

    @author:songxianfeng

    @copyright: V1.0

    '''

    import MySQLdb

    from xml.dom import minidom

    global DOC,CONN

     

    class DataOperations(object):   

        '''

        数据读取相关操作

        '''

     

        def __init__(self,filename):

            '''

            初始化xml文档

            '''

            global DOC,CONN

            DOC = minidom.parse("../testData/"+filename) 

              

        def readxml(self,ftagname,num,stagname):

            '''

            从指定的文件中中读取指定节点的值

            @param ftagname:起始节点的名称,如:project

            @param num:取与起始节点相同的第num个节点

            @param stagname: 起始节点下的二级节点

            @return: 返回二级节点的值

            '''          

            root = DOC.documentElement

            message=root.getElementsByTagName_r(ftagname)[num]

            return message.getElementsByTagName_r(stagname)[0].childNodes[0].nodeValue

       

        def readxml_attribute(self,ftagname,num,stagname,attributeName):

            '''

            all_case.xml文件中读取节点的属性值

            @param ftagname:起始节点的名称,如:project

            @param num:取与起始节点相同的第num个节点

            @param stagname: 起始节点下的二级节点

            @param attributeName: 二级节点的属性名

            @return:返回二级节点指定的属性值       

            '''

          

            root = DOC.documentElement

            message=root.getElementsByTagName_r(ftagname)[num]

            return message.getElementsByTagName_r(stagname)[0].getAttribute(attributeName)

     

    pythonxml的读取操作,如果你不太明白,可以去自行学习相关的内容,要教程不讲解相关的操作。

    6.6.3 具体的测试用例

      上面的公用方法类创建以后,我们就可以着手编写具体的测试用例了。在TestCases文件夹下创建测试用例TestCase_QT_Login.py,然后编写下面的测试步骤:

    (1)            打开众筹网。

    (2)            点击登录按钮,输入用户名和密码。

    (3)            验证是否登录成功,用户昵称是不是刚刚登录的账号。

    (4)            退出登录,关闭浏览器。

    测试用例代码如下:

    -*- coding: UTF-8 -*-

    '''

    Created on 2014-12-15

    @author:songxianfeng

    @version: v1.0

    '''

    import unittest

    import time

    #导入需要的公共函数类

    from CommonFunction.WebDriverHelp import WebDriverHelp

    from CommonFunction.DataOperations import DataOperations

    from CommonFunction.QT_Operations import QT_Operations

    class testcases_login(unittest.TestCase):

        '''

        登录检测

        '''

        def setUp(self):

            WebDriverHelp("open","firefox","local").setup("zhengshi")#打开浏览器,并打开众筹网

           

        def testlogin(self):       

            #登录检测       

            dataoper=DataOperations("TestCase_QT_Login.xml") #读取测试数据

            #登录      

            QT_Operations().login(dataoper.readxml('login', 0, 'username'),

    dataoper.readxml('login', 0, 'password'))

            self.assertEqual(WebDriverHelp().gettext('byxpath',dataoper.readxml('login', 0, 'checkpoint1')),dataoper.readxml('login', 0, 'value1')) #判断登录是否成功

            #退出

            QT_Operations().logout()

            time.sleep(5)

            self.assertEqual(WebDriverHelp().gettext('byclassname',dataoper.readxml('login', 0, 'checkpoint2')),dataoper.readxml('login', 0, 'value2')) #判断退出是否成功

                            

        def tearDown(self):

            WebDriverHelp().teardown()#关闭浏览器

           

    if __name__ == "__main__":   

    unittest.main()

     

    经过我们上面的封装,现在具体的测试用例只是传参数,调用具体的函数,验证执行结果。是不是非常简单?有点儿像我们小时候玩积木,用一块块现成的积木堆积出魔幻的城堡。

    6.6.4 测试用例的具体数据

       由于我们把测试用例和测试数据完全分离开了,所以我们用和测试用例同名的文件名命名对应的测试数据文件。登录测试用例的数据文件是TestCase_QT_Login.xml,具体内容如下:

     

  • 相关阅读:
    贴板子系列_1-km算法,匈牙利算法
    bzoj 2333
    bzoj 3531 旅行
    斯坦纳树
    可持久化线段树
    下界最小费用最大流
    我们还是太NAive
    ubuntu出现有线已连接却无法上网
    python小爬虫【1】
    [解答]对‘’未定义的引用 collect2: 错误: ld 返回 1
  • 原文地址:https://www.cnblogs.com/eagleking0318/p/6520876.html
Copyright © 2011-2022 走看看