• 自动化测试-高级篇


     

    目标

     为什么使用UnitTest框架?    
        1. 能组织用例和执行用例
        2. 提供丰富的断言方法
        3. 提供丰富的日志与测试结果

    单元测试框架

    掌握UnitTest框架的基础使用方法
    什么是框架
    说明:
        1. 框架英文单词FrameWork;
        2. 为解决一类事情的功能集合;
    什么是UnitTest框架
    概念:UnitTest框架是专门用来进行执行代码测试的框架;
    为什么使用UnitTest框架
    1. 能够组织多个用例去执行
    2. 提供丰富的断言方法
    3. 提供丰富的日志与测试结果
    提示
    在学习UnitTest框架之前,我们先了解下UnitTest框架内几个核心要素
    UnitTest核心要素
    1. TestCase
    2. TestSuite
    3. TextTestRunner
    4. Fixture

    TestCase(测试用例)

    说明:(翻译:测试用例)一个TestCase就是一条测试用例;
    使用:
        1. 导包:import unittest             --> 导入unitest框架
        2. 继承:unittest.TestCase             --> 新建测试类继承unittest.TestCase
    
    提示:
        1). 测试用例:在自动化测试中,一条用例就是一个完整的测试流程;                
        2). 测试方法名称命名必须以test开头;
           (原因:unittest.TestCase类批量运行的方法是搜索执行test开头的方法)
    Python
    L1 (default)
    已复制
    # 导入unittest
    import  unittest
    class Test01(unittest.TestCase): # 新建测试类继承unittest.TestCase
        # 测试方法名称必须以test开头
        def test001(self):
            print('test001被执行')
        def test002(self):
            print('test002被执行')
    
    if __name__ == '__main__': # 可以看看python当中的__name__,当前文件运行,__name__==main
        unittest.main() # 执行以test开头的方法
    '''
        结果:
        Test01-->test001被执行
        Test01-->test002被执行
    '''

    TestSuite

    说明:(翻译:测试套件)多条测试用例集合在一起,就是一个TestSuite;
    使用:
        1. 实例化:     suite=unittest.TestSuite()                    
                     (suite:为TestSuite实例化的名称)
        2. 添加用例:suite.addTest(ClassName("MethodName"))    
                     (ClassName:为类名;MethodName:为方法名)
    
        3. 添加扩展:suite.addTest(unittest.makeSuite(ClassName))
                     (搜索指定ClassName内test开头的方法并添加到测试套件中)
    
    提示:
        1). 一条测试用例(.py)内,多个方法也可以使用测试套件
        2). TestSuite需要配合TextTestRunner才能被执行

     

    # 导入unittest
    import unittest
    # 导入测试用例.py
    from TestCase.Test01 import Test01
    from TestCase.Test02 import Test02
    from TestCase.Test03 import Test03
    if __name__ == '__main__':
        # 实例化suite
        suite=unittest.TestSuite()
        # 调用 添加用例方法 className(methonName)
        suite.addTest(Test01('test001'))
        suite.addTest(Test02('test002'))
        suite.addTest(Test03('test003'))
        # 执行testsuite
        unittest.TextTestRunner().run(suite)
    '''
    结果:
        Test01-->test001被执行
        Test02-->test002被执行
        Test03-->test003被执行
    '''

     

    # 导入unittest
    import unittest
    # 导入测试用例.py
    from TestCase.Test01 import Test01
    from TestCase.Test02 import Test02
    from TestCase.Test03 import Test03
    if __name__ == '__main__':
        # 实例化suite
        suite=unittest.TestSuite()
        # 调用 添加用例方法 ClassName
        # 搜索指定ClassName内test开头的方法并添加到测试套件中
        suite.addTest(unittest.makeSuite(Test02))
        # 执行testsuite
        unittest.TextTestRunner().run(suite)
    '''
    结果:
        Test02-->test001被执行
        Test02-->test002被执行
        Test02-->test003被执行
    '''

     

    # 导入unittest
    import unittest
    # 导入测试用例.py
    from TestCase.Test01 import Test01
    from TestCase.Test02 import Test02
    from TestCase.Test03 import Test03
    if __name__ == '__main__':
        # 搜索指定目录指定的py文件,并返回所有搜索文件内test开头的方法,以测试套件的形式返回
        # 定义测试套件
        suite=unittest.defaultTestLoader.discover('.',pattern='Test*.py')
        unittest.TextTestRunner().run(suite)

    TextTestRunner

    说明:(翻译:以文本形式执行测试)是用来执行测试用例套件
    使用:
        1. 实例化: runner=unittest.TextTestRunner()
                    (runner:TextTestRunner实例化名称)
        2. 执行:    runner.run(suite)
                    (suite:为测试套件名称)

     

    Fixture

    说明:是一个概述,对一个测试用例环境的搭建和销毁就是一个Fixture;
    使用:
        1. 初始化(搭建):def setUp(self)        --> 首先执行
           (setUp:此方法继承于unittest.TestCase)        
        2. 结束(销毁):    def tearDown(self)        --> 最后执行
           (tearDown:此方法继承于unittest.TestCase)
    提示:
        1. 必须继承unittest.TestCase类,setUp、tearDown才是一个Fixture;
        2. setUp:一般做初始化工作,比如:实例化浏览器、浏览器最大化、隐式等待设置
        3. tearDown:一般做结束工作,比如:退出登录、关闭浏览器
        4. 如果一个测试类有多个test开头方法,则每个方法执行之前都会运行setUp、结束时运行tearDown

    案例

    需求:使用UnitTest框架对iweb_shop项目测试
        1. 登陆进行测试
    操作步骤分析:
    1. 导包 import unittest
    2. 新建测试类并继承unittest.TestCase
    3. 新建一个Fixture(setUp、tearDown)
    4. 新建登录方法
    5. if __name__ == '__main__':
    6. unittest.main()执行
    代码实现:
    import unittest
    from time import sleep
    from selenium import webdriver
    class TestLoginOut(unittest.TestCase):
        def setUp(self):
            # self.driver 是成员属性,被类对象内部共享
            # self指代当前对象
            # driver 是局部变量,生命周期在当前方法内
            # 这里由于driver对象在后面还用到也就是要共享,所以将其设为对象内部属性,调用时self.driver
            self.driver = webdriver.Firefox()
            url = 'http://localhost/iwebshop/'
            self.driver.get(url)
            # 设置隐式等待10s
            self.driver.implicitly_wait(10)
            # 最大化浏览器对象
            self.driver.maximize_window()
            print('setup')
        def test_login(self):
            driver = self.driver
            driver.find_element_by_link_text('登录').click()
            driver.find_element_by_css_selector('input[alt*="邮箱"]').send_keys('admin')
            driver.find_element_by_css_selector('input[alt*="密码"]').send_keys('123456')
            driver.find_element_by_css_selector('.submit_login').click()
            sleep(3)
            driver.find_element_by_css_selector('.reg').click()
        def tearDown(self):
            sleep(2)
            self.driver.quit() # 确保是同一个浏览器对象
            print('tearDown')
        if __name__=='main':
            # 调用main方法执行unittest内所有test开头方法
            unittest.main()

    回顾

    为什么使用UnitTest框架?    
        1. 能组织用例和执行用例
        2. 提供丰富的断言方法
        3. 提供丰富的日志与测试结果
    1. UnitTest用例组织和执行用例方法我们基本就学完了
    2. 接下来我们学习UnitTest框架的断言方法

    UnitTest断言

    什么是断言?

    概念:让程序代替人为判断测试程序执行结果是否符合预期结果的过程

    为什么要学习断言?

    自动化脚本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,
    所以我们需要让程序代替人为检测程序执行的结果是否符合预期结果,这就需要使用断言;

    UnitTest断言分类

    1. 基本布尔型断言
    2. 比较断言
    3. 复杂断言
    
    提示:
        1. 这里这介绍基本布尔类型断言 说明:结果只有True和False
        2. 比较断言、复杂断言有兴趣的同学请参考4.4附件资料

    案例

    需求:
        1. iweb项目登陆,输入正确用户名和密码,断言登录成功的用户名是否为admin,如果断言失败截图保存
    扩展:
        1. 图片名称为动态-时间
        2. 图片名称添加断言错误信息
    实现步骤分析
    1. 成功登陆
    2. 获取登陆后的信息
    3. 添加断言

    断言主要代码实现

     # 获取登陆信息,因为没有打开新窗口,所以句柄没变化,还是在当前窗口查找元素
    import sys
    import time
    import unittest
    from time import sleep
    from selenium import webdriver
    class TestLoginOut(unittest.TestCase):
        def setUp(self):
            # self.driver 是成员属性,被类对象内部共享
            # self指代当前对象
            # driver 是局部变量,生命周期在当前方法内
            self.driver = webdriver.Firefox()
            url = 'http://localhost/iwebshop/'
            self.driver.get(url)
            # 设置隐式等待10s
            self.driver.implicitly_wait(10)
            # 最大化浏览器对象
            self.driver.maximize_window()
            print('setup')
        def test_login(self):
            driver = self.driver
            driver.find_element_by_link_text('登录').click()
            driver.find_element_by_css_selector('input[alt*="邮箱"]').send_keys('admin')
            driver.find_element_by_css_selector('input[alt*="密码"]').send_keys('123456')
            driver.find_element_by_css_selector('.submit_login').click()
            # 获取登录后的提示信息
            text = driver.find_element_by_css_selector('.loginfo').text
            try:
                self.assrtIn('admin',text)
            except AssertionError:
                # 设置时间字符串(获取运行时系统时间)
                nowtime = time.strftime('%Y_%m_%d %H_%M_%S')
                # 截取屏幕
                driver.get_screenshot_as_file('../Image/%s---%s.jpg' % nowtime,sys.exc_info()[1])
                # 抛出捕获的异常,并终止后面的代码
                raise AssertionError
            # 退出
            sleep(3)
            driver.find_element_by_link_text('安全退出').click()
        def tearDown(self):
            sleep(2)
            self.driver.quit() # 确保是同一个浏览器对象
            print('tearDown')
        if __name__=='main':
            # 调用main方法执行unittest内所有test开头方法
            unittest.main()

    测试结果-HTML测试报告

    什么是HTML测试报告

    说明:HTML测试报告就是执行完测试用例后以HTML(网页)方式将执行结果生成报告

    为什么要生成测试报告

    1. 测试报告是本次测试目的最终体现形态
    2. 测试报告内包含了有关本次测试用例的详情

    HTML生成报告方式

    Export Test Results (自带)

    测试报告

    测试步骤

        提示:适合单条用例执行时使用

    HTMLTestRunner【重点】

    测试报告
    测试报告 生成步骤分析
    1. 复制HTMLTestRunner.py文件到项目文件夹
    2. 导入HTMLTestRunner、UnitTest包    
    3. discover加载要执行的用例
          (discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py"))
    4. 设置报告生成路径和文件名
       (file_name=file_dir+nowtime+"Report.html")
     5. 打开报告 with open(file_name,'wb') as f:  # 没有会自动生成文件
     6. 实例化HTMLTestRunner对象:runner=HTMLTestRunner(stream=f,[title],[description])
     参数说明:
                   (stream:文件流,打开写入报告的名称及写入编码格式)
                   (
                           [],为可选;
                           title为报告标题,如XXX自动化测试报告
                           description:为说明;比如操作系统、浏览器等版本
                   )
    7. 执行:runner.run(discover)
    
    

    实现代码

     

    # 导入unittest
    import time
    import unittest
    # 导入HTMLTestRunner.py
    import TestCase.HTMLTestRunner
    # 导入测试用例.py
    from TestCase.HTMLTestRunner import HTMLTestRunner
    from TestCase.Test01 import Test01
    from TestCase.Test02 import Test02
    from TestCase.Test03 import Test03
    test_dir='.'
    
    if __name__ == '__main__':
        # 加载当前目录下test开头的.py文件
        discover = unittest.defaultTestLoader.discover(test_dir, pattern="Test*.py")
        # 定义报告目录
        file_dir = '../Report/'
        # 定义报告名称格式
        nowtime=time.strftime("%Y-%m-%d %H_%M_%S")
        # 报告完整路径和名称
        file_name = file_dir+nowtime+'Report.html'
        with open(file_name,'wb') as f: # 二进制形式写入
            # 实例化HTMLTestRunner 对象,传入报告文件流f
            runner = HTMLTestRunner(stream=f,title='web自动化测试报告',description='孙腾写的')
            runner.run(discover)
     
     
     
     
  • 相关阅读:
    查看系统运行时间和系统当前时间
    根据端口查进程信息
    SELinux深入理解
    nginx配置文件
    centos7 nginx配置httpsCenos(6.6/7.1)下从源码安装Python+Django+uwsgi+nginx环境部署(二)
    Linux的加密认证功能以及openssl详解
    linux中shell变量$#,$@,$0,$1,$2的含义解释
    理解GRUB2工作原理及配置选项与方法
    在用busybox制作系统过程中遇到的问题
    内核编译选配(VMware篇)
  • 原文地址:https://www.cnblogs.com/st998/p/13797934.html
Copyright © 2020-2023  润新知