zoukankan      html  css  js  c++  java
  • 8_17号总结

                     python自动化web测试
    
    文档包含的内容:
         1.web自动化说明与框架     2. web自动化测试例子     3.环境的搭建(附录)
         近期,由于对需要对迪备产品进行web测试,上网找了些关于python进行自动化测试的资料,发现进行Web测试,可以通过Webdriver去模拟用户的操作,当前比较出色就是splinter+selenuim,基本上支持IE,fixfox和chrome浏览器的基本操作。
        有了第三方模拟浏览器工具的帮助,然后就要想想产品的测试框架了,因为我们的产品基本上进行的是功能测试,而python自己自带的unittest是进行单元测试的,不过,似乎单元测试也是有层次的,小单元到大单元,再到一个个的模块,最后整体的软件测试。其实我们的产品的测试,也可以这样,一个个测试单元组成一个模块,例如登录迪备就是一个小模块,里面是测试单元,则是一个个的测试用例。然后再由这些小模块再组成大模块,最后成为我们产品的测试的框架。python提供了testsuit(测试包) 就是把小模块组合成大模块的类。整体来看还是典型的树形结构,同时每一层都可以有测试的进行。
        有点头绪了,就开始尝试用python进行测试了,刚开始的参数是默认的,逐渐变成从txt文件,到xml文件去读取测试用例。
        继续需要做的就是把这些测试用例做成模块,构架出框架来。
    以下些例子:主要参考
    http://splinter.cobrateam.info/docs/ splinter的官网,自动测试的Web框架,包含小例子和API的说明
    http://docs.python.org/library/unittest.html python单元测试框架的文档和小例子
    http://docs.python.org/library/xml.etree.elementtree.html python对XML的解析
    另外还需要了解一下html,css,和javacript
    其实这只是例子,真正的还需要很多的细化。
    例子1:批量增加,删除用户,增加ftp服务器,删除ftp服务器的参数都从XML文件中读取,并可以从server端的mysql数据库获取数据来assertEqual.
    例子2:创建oracle数据库备份实例和mysql数据库备份实例,在备份之前先往数据库里面添加数据,在恢复后,再查询是否同样的数据在数据库中(未完成)
    xml文件在以后就变成测试用例输入的数据,如边界值,只需要修改xml文件,再运行python脚本来测试
    username.xml
    <?xml version = "1.0" encoding= "UTF-8"?> 
    <addUsers> 
        <user name='hzhida' password = 'dingjia' email ='hzhida95@gmail.com' telephone='13424341233' /> 
        <user name='dingjia' password= 'dingjia' email ='dbackup@gmail.com'  telephone= '3143142131' /> 
        <user name = 'Tommy' password = 'djifadf' email ='34131431@qq.com'   telephone ='1341314312'/> 
        <user name = 'Janny' password = 'dafjljfd' email ='erfdjlafj@qq.com' telephone = '143143134'/> 
    </addUsers>
    ftp.xml
    <?xml version = "1.0" encoding= "UTF-8"?> 
    <TotalFTP> 
        <ftp name='ftpunbuntu' ip='192.168.88.245' port ='21' username = 'hzhida' password = 'dingjia' path ='FTPFile/backup/'/> 
        <ftp name='windowftp' ip='192.168.88.162' port = '21' username = 'hzhida' password = 'dingjia' path='FTPFile\backup'/> 
    </TotalFTP>
    
    #-*-coding:utf-8-*- 
    from __future__ import with_statement 
    import os 
    import unittest 
    import time 
    from splinter import Browser 
    from random import randint 
    from xml.etree import ElementTree as ET 
    import MySQLdb 
    
    class DbackupTestCase(unittest.TestCase): 
    
        @classmethod 
        def setUpClass(cls): 
            cls.browser = Browser('firefox') 
            cls.connection = MySQLdb.connect(user='scutech',db ='dpsora_1',passwd='dingjia',host='192.168.88.245') 
            cls.cursor = cls.connection.cursor() 
    
        @classmethod 
        def setDownClass(cls): 
            cls.browser.quit() 
    
        def login(self, username, password): 
            if self.browser.find_by_id('lhgfrm_lhgdgId'): 
                with self.browser.get_iframe('lhgfrm_lhgdgId') as frame: 
                    frame.find_by_id('trialRadio').click() 
                    frame.find_by_id('continue').click() 
    
            self.browser.fill('username',username) 
            self.browser.fill('password',password) 
            self.browser.find_by_name('Submit').click() 
            time.sleep(0.5) 
            assert self.browser.is_element_present_by_tag('body') 
    
        #@unittest.skip('skip register') 
        def test_register(self): 
            self.browser.visit('http://192.168.88.245/dbackup') 
            self.login(username='admin', password= 'admin') 
            time.sleep(1) 
            #because iframe has no id,so can't get it 
            #iframe = self.browser.find_by_tag('iframe') 
            #iframe.find_link_by_href('../Supermanage/LocalCfgManage.php').click() 
    
            #self.browser.find_by_id('Navigate1').click() 
            #self.browser.find_link_by_href('Register.php').click() 
            navigate = self.browser.find_by_css('.NavigateMBG') 
            for i in navigate: 
                print i 
            navigate[2].click() 
            navigate[2].find_by_tag('a')[2].click() 
            time.sleep(0.5)     
            file = ET.parse('username.xml') 
            users = file.findall('./user') 
            for user in users: 
                self.browser.find_by_id('username').fill(user.get('name')) 
                self.browser.fill('password',user.get('password')) 
                self.browser.find_by_id('confirmpassword').fill(user.get('password')) 
                self.browser.find_by_id('email').fill(user.get('email')) 
                self.browser.find_by_id('telephone').fill(user.get('telephone')) 
                self.browser.find_by_name('Submit').click() 
                time.sleep(1) 
                alert = self.browser.get_alert() 
                alert.accept() 
    
                #select from database to check whether the user had registered 
                self.cursor.execute("""select username from v_loginaccountinfo where enabled = '1' and username= %s""" , (user.get('name'),)) 
                self.assertEqual(self.cursor.fetchone(),(user.get('name'),)) 
     
                #navigate[2].click() 
                #navigate[2].find_by_tag('a')[2].click() 
                self.browser.find_by_id('Navigate1').click() 
                self.browser.find_link_by_href('Register.php').click() 
            
    
        
        @unittest.skip('skip user land') 
        def test_User(self): 
            self.browser.visit('http://192.168.88.245/dbackup') 
            file = ET.parse('username.xml') 
            users = file.findall('./user') 
            for user in users: 
                self.login(username = user.get('name'), password = user.get('password')) 
                time.sleep(1) 
                iframe =  self.browser.find_by_tag('iframe') 
                iframe[0].find_by_tag('a')[3].click() 
                self.browser.visit('http://192.168.88.245/dbackup') 
    
        @unittest.skip('del user') 
        def test_delUser(self): 
            self.browser.visit('http://192.168.88.245/dbackup') 
            self.login(username ='admin', password ='admin') 
            time.sleep(0.5) 
            navigate = self.browser.find_by_css('.NavigateMBG') 
            navigate[2].click() 
            navigate[2].find_by_tag('a')[1].click() 
            table=self.browser.find_by_id('mytable') 
            tr=table.find_by_tag('tr') 
            file = ET.parse('deluser.xml') 
            user = file.find('./user') 
            i=1 
            while i< len(tr): 
                if tr[i].find_by_tag('td')[1].value == user.get('name'): 
                    tr[i].find_by_tag('input').click() 
                    self.browser.find_by_id('nDeleteAccountID').click() 
                    time.sleep(1) 
                    alert = self.browser.get_alert() 
                    alert.accept() 
                    alert = self.browser.get_alert() 
                    alert.accept() 
                    time.sleep(1) 
                    break 
                else: 
                    i+=1 
    
        @unittest.skip('skip addFTP') 
        def test_addFTP(self): 
            self.browser.visit('http://192.168.88.245/dbackup') 
            self.login(username = 'admin', password = 'admin') 
            time.sleep(0.5) 
            navigate = self.browser.find_by_css('.NavigateMBG') 
            navigate[0].click() 
            navigate[0].find_by_tag('a')[2].click() 
            file = ET.parse('ftp.xml') 
            ftps = file.findall('./ftp') 
            for ftp in ftps: 
                self.browser.find_by_id('strFTPNameID').fill(ftp.get('name')) 
                ip = [ ftp.get('ip').strip().split('.') for ipnum in ftp.get('ip') ] 
                self.browser.find_by_id('IP1').fill(ip[0][0]) 
                self.browser.find_by_id('IP2').fill(ip[0][1]) 
                self.browser.find_by_id('IP3').fill(ip[0][2]) 
                self.browser.find_by_id('IP4').fill(ip[0][3]) 
                self.browser.find_by_id('strPortID').fill(ftp.get('port')) 
                self.browser.find_by_id('strFTPLoginNameID').fill(ftp.get('username')) 
                self.browser.fill('strFTPLoginPW',ftp.get('password')) 
                self.browser.find_by_id('ConfirmPWID').fill(ftp.get('password')) 
                self.browser.find_by_id('nPathID').fill(ftp.get('path')) 
                self.browser.find_by_id('Submit').click() 
                alert = self.browser.get_alert() 
                alert.accept() 
                time.sleep(1) 
                self.cursor.execute("""select FtpName from ftpserver where Disabled ='0' and FtpName = %s""",(ftp.get('name'),)) 
                self.assertEqual(self.cursor.fetchone(),(ftp.get('name'),)) 
                self.browser.find_by_id('Navigate5').click() 
                self.browser.find_link_by_href('FtpCfg.php').click() 
    unittest.main()        
    
       例子2:
    #-*-coding:utf-8-*- 
    from __future__ import with_statement 
    import os 
    try: 
        import unittest2 as unittest 
    except ImportError: 
        import unittest 
    import time 
    from splinter import Browser 
    from random   import randint 
    import cx_Oracle 
    import mySQLdb 
    import cPickle 
    from sys import modules 
    
    class DbackupTestCase(unittest.TestCase): 
       # support 2.7,but not support 2.6.all the testcases just have one instance 
        @classmethod 
        def setUpClass(cls): 
            cls.browser=Browser('firefox') 
            cls.connection =cx_Oracle.connect('system','dingjia','192.168.88.245/oracle') 
            cls.cursor =cls.connection.cursor() 
        
        @classmethod 
        def setDownClass(cls): 
             cls.browser.quit() 
    
       #every testcase has one instance 
       # def setUp(self): 
       #     self.browser=Browser('firefox') 
    
       # def setDown(self): 
       #     self.browser.quit() 
    
        def do_login_if_need(self, username, password): 
    
            if self.browser.find_by_id('lhgfrm_lhgdgId'): 
                    with self.browser.get_iframe('lhgfrm_lhgdgId') as frame: 
                        frame.find_by_id('trialRadio').click() 
                        frame.find_by_id('continue').click() 
    
            self.browser.fill('username',username) 
            self.browser.fill('password',password) 
            self.browser.find_by_name('Submit').click() 
    
            assert  self.browser.is_element_present_by_css('.none') 
            
    
        def test_create_oracle_event(self): 
            #In order to check the backup process is correct, so before it backup,insert some data in database, and when it recover,so it is a chance to select the same data in database to terify the process of backup 
            create_table=""" 
                create table python_modules( 
                module_name VARCHAR2(50) NOT NULL, 
                file_path VARCHAR2(300) NOT NULL 
                )""" 
            self.cursor.execute(create_table) 
            M= [] 
            for m_name, m_info in modules.items(): 
                try: 
                    M.append((m_name,m_info.__file__)) 
                except AttributeError: 
                    pass 
            cursor.prepare("insert into python_modules(module_name,file_path) values(:1,:2)") 
            cursor.executemany(None,M) 
            #submit transation 
            self.connection.commit() 
    
            #open home and login 
            self.browser.visit('http://192.168.88.245/dbackup') 
            self.do_login_if_need(username='hzhida', password ='dingjia') 
            time.sleep(0.5) 
            assert self.browser.is_element_present_by_id('treeNodeId1') 
            self.browser.find_link_by_href('javascript:void(0)')[1].click() 
            time.sleep(1) 
            element=self.browser.find_by_css('.tree_item_child') 
            #self.browser.find_link_by_href('javascript:void(0)')[2].click() 
            element[0].find_by_css('.tree_item_click').first.click() 
            #element[0].find_by_tag('a').first.click() 
            self.browser.find_by_id('Navigate7').click() 
            time.sleep(1) 
            self.browser.find_link_by_href('#wizard-2').click() 
            self.browser.find_link_by_href('#wizard-3').click() 
            self.browser.find_by_id('ftpRadio').click() 
            self.browser.find_link_by_href('#wizard-4').click() 
            number = [randint(1000,9999) for i in range(1)] 
            jobname='job'+'_'+ str(number[0]) 
            self.browser.find_by_id('jobName').fill(jobname) 
            self.browser.find_by_id('middlelevelRadio').click() 
            self.browser.find_link_by_href('#wizard-5').click() 
            self.browser.find_by_css('.submit_btn').click() 
            time.sleep(1) 
            self.browser.select('Filtermenu','JobMonitorManage.php?FType=1') 
            time.sleep(0.1) 
            self.browser.select('Filtermenu','JobMonitorManage.php?FType=0') 
            time.sleep(0.1) 
            self.assertEqual(self.browser.find_link_by_href('javascript:void(0)').first.value,jobname) 
            print self.browser.find_by_id('CompletePercent0').value 
            print self.browser.find_by_id('strBeginTime0').value 
            print self.browser.find_by_id('strUsedTime0').value 
            time.sleep(10) 
        
        @unittest.skip('skip test mysql') 
        def test_create_mysql_event(self): 
    
            self.browser.visit('http://192.168.88.245/dbackup') 
            self.do_login_if_need(username='hzhida',password='dingjia') 
            time.sleep(0.5) 
            assert self.browser.is_element_present_by_id('treeNodeId1') 
            self.browser.find_link_by_href('javascript:void(0)')[1].click() 
            time.sleep(1) 
            element=self.browser.find_by_css('.tree_item_child') 
            element[1].find_by_tag('a').first.click() 
            self.browser.find_by_id('Navigate7').click() 
            self.browser.find_by_id('sqlSelectAllCheckbox').click() 
            time.sleep(2) 
            navigate=self.browser.find_by_css('.nav') 
            navigate[0].find_by_css('.next').click() 
            self.browser.find_by_id('ftpRadio').click() 
            navigate[1].find_by_css('.back').click() 
            time.sleep(1) 
            navigate[0].find_by_css('.next').click() 
            navigate[1].find_by_css('.next').click() 
            self.browser.find_by_id('lowlevelRadio').click() 
            number = [randint(1000,9999) for i in range(1)] 
            jobname= 'job'+'_'+str(number[0]) 
            self.browser.find_by_id('jobName').fill(jobname) 
            navigate[2].find_by_css('.next').click() 
            navigate[3].find_by_css('.submit_btn').click() 
            self.assertEqual(self.browser.find_by_tag('font').value, jobname) 
            print self.browser.title() 
            print self.browser.html 
    unittest.main()
    
    附录:
    Ubuntu 11.10 安装splinter
    为了防止下面的过程出错,建议:
        sudo apt-get install build-essential python-dev libxml2-dev libxslt1-dev
    1.下载splinter 0.4.7.tar.gz包  http://pypi.python.org/pypi/splinter/0.4.7/
    2.解压 tar -zxvf 安装包  进入cd splinter 0.4.7
    3.安装 sudo python setup.py install
        ImportError: No module named setuptools
        wget http://pypi.python.org/packages/source/s/setuptools/setuptools-0.6c11.tar.gz
          tar zxvf setuptools-0.6c11.tar.gz
        cd setuptools-0.6c11
        python setup.py build
        python setup.py install
     安装过程中提示
    make sure the development packages of libxml2 and libxslt are installed **
    
      Using build configuration of libxslt
      src/lxml/lxml.etree.c:4: fatal error: Python.h: 没有那个文件或目录
      compilation terminated.
      error: Setup script exited with error: command 'gcc' failed with exit status 1
      经过google查询得知没有安装libxml2-dev和libxlst1-dev
    为保险起见,请依次安装如下:
      sudo apt-get install gcc
      sudo apt-get install python-dev
      sudo apt-get install libxml2 libxml2-dev
      sudo apt-get install libxslt1.1 libxslt1-dev
      后面的是数字1,不是字母l,不要写错了。
    AttributeError: 'NoneType' object has no attribute 'clone' 到http://pypi.python.org/pypi/setuptools/ 下载ez_setup.py
    执行python ez_setup.py -U setuptools 升级setuptools 过程中可能会出现网络的错误,如connection peer ,可以重复执行一下
    支持浏览器fixfox,chrome,IE 还需下载安装http://pypi.python.org/pypi/selenium/
    下载selenium-2.25.0.tar.gz
    解压 tar -zxvfselenium-2.25.0.tar.gz
    cd    selenium-2.25.0
    sudo python setup.py install    这样就可以模拟浏览器的操作
    
    环境基本搭建好了,如果想用python去操作mysql数据库和oracle数据库, 还需安装:
    MySQLdb模块 和 cx_Oracle模块
    安装MySQLdb模块:
         首先安装MySQL数据库,在Ubuntu可以直接apt-get mysql,对于其他的系统,如Redhat 可以到oracle官网上下载mysql.rpm安装文件
        使用命令rpm -ivh mysql-server.rpm 和rpm -ivh mysql-client.rpm 进行安装
        假如发生包mysql-lib冲突,可以yum erase 或者yum remove 来把冲突的包给去掉。
        ubuntu 系统:sudo apt-get install python-mysqldb
        另外其他系统:下载 MySQL-python-1.2.3.tat.gz (下载地址Google下)
          解压后 sudo python setup.py build
          提示: ImportError: No module named setuptools (没有setuptools 模块)
          继续下载 setuptools-0.6c11.tar.gz
          解压后 sudo python setup.py build (编译)
          sudo python setup.py install (安装)
          这回有 setuptools模块了吧!
          回到用户MySQLdb源码目录
    
          继续sudo python setup.py build 又提示:mysql_config not found
          于是乎查mysql_config
          得知mysql_config是属于MySQL开发用的文件,而使用apt-get安装的MySQL是没有这个文件的,于是在包安装器里面寻找
          libmysqld-dev
          libmysqlclient-dev
          这两个包安装后问题即可解决
          这回/usr/bin/ 下有 mysql_config命令了 (查找命令 whereis mysql_config)
          修改MySQLdb下的setup_posix.py 文件 
          找到mysql_config.path 改成mysql_config.path = "/usr/bin/mysql_config"//就是mysql_config.path=XXXX的这行。
          在重复: sudo python setup.py build
          又出错: error: command 'gcc' failed with exit status 1
          sudo apt-get install build-essential
          sudo apt-get install python-dev
          安完以后在回到MySQLdb目录
          sudo python setup.py build (编译)
          sudo python setup.py install (安装)
    
    安装cx_Oracle模块:
    
        Oracle Instant Client is a free Oracle database client. The current version is 11.2.0.1.0, and several versions back to 10.1.0.5 are available.
    Install RPMs
    Download the Oracle Instantclient RPM files fromhttp://www.oracle.com/technetwork/database/features/instant-client/index-097480.html. Everyone needs either "Basic" or "Basic lite", and most users will want "SQL*Plus" and the "SDK".
    Convert these .rpm files into .deb packages and install using "alien" ("sudo apt-get install alien" if you don't have it):
    转为位deb包,然后直接安装
    alien -i  oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
    alien -i oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
    alien -i oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm
    由于是rpm包,在ubuntu上转换位deb包:sudo alien oracle-instantclient-basic-11.2.x86_64.rpm
    得到deb包,在ubuntu上安装命令为:sudo dpkg -i oracle-instantclient-basic_11.2_amd64.deb
    Test your Instantclient install by using "sqlplus" to connect to your database:
    sqlplus  username/password@//dbhost:1521/SID
    If sqlplus complains of a missing libaio.so.1 file, run
    sudo apt-get install libaio1
    If sqlplus complains of a missing libsqlplus.so file, follow the steps in the section "Integrate Oracle Libraries" below.
    If you execute sqlplus and get "sqlplus: command not found", see the section below about adding the ORACLE_HOME variable.
    Integrate Oracle Libraries|ORACLE_HOME
    If oracle applications, such as sqlplus, are complaining about missing libraries, you can add the Oracle libraries to the LD_LIBRARY_PATH each time it is used, or to add it to the system library list create a new file as follows:
    sudo vim /etc/profile
    增加以下环境变量:
            export ORACLE_HOME=/usr/lib/oracle/11.2/client64
      export PATH=$PATH:$ORACLE_HOME/bin
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
      export TNS_ADMIN=$ORACLE_HOME/network/admin
    source /etc/profile 文件 更新环境变量
    如果需要配置tnsnames.ora还需要这样操作:
    sudo mkdir -p $ORACLE_HOME/network/admin
    sudo cp tnsnames.ora $ORACLE_HOME/network/admin
    Download and build cx_Oracle
    Download cx_Oracle at http://cx-oracle.sourceforge.net and unzip wherever you want, then...
    选择源码安装:解压下载回来的tar.gz包,tar -zxvf cx_oracle.tar.gz
    cd [your cx_Oracle installation path]
    python setup.py build
    python setup.py install
      ImportError: libclntsh.so.11.1: cannot open shared object file: No such file or directory
      此时是由于python在操作oracle数据库的时候需要用到oracle的一些库,而上面的问题就是说python需要的这些库不在环境的路径里,在linux上就是不在LD_LIBRARY_PATH环境变量里,此时时就需要把这些库路径加到LD_LIBRARY_PATH中
    $exportLD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib/oracle/11.2/client64/lib 
    也可以选择rpm安装,解压出来里面有cx_Oracle.so ,执行命令:sudo cp cx_Oracle.so /usr/local/lib/python2.7/dist-packages/
    验证安装成功:
    luca@ubuntu:~$ python
    [GCC 4.4.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import cx_Oracle
    >>> print cx_Oracle.version
    5.1.2
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/hzhida/p/2644446.html
Copyright © 2011-2022 走看看