Loading

UI自动化学习笔记- UnitTest单元测试框架详解

一、UnitTest基本使用

1. UnitTest框架

1.1 什么是框架

说明:

  1. 框架英文单词frame
  2. 为解决一类事情的功能集合
1.2什么是UnitTest框架

概念:UnitTest是python自带的一个单元测试框架,用它来做单元测试

1.3为什么使用UnitTest框架?
  1. 能够阻止多个用例去执行
  2. 提供丰富的断言方法
  3. 能够生成测试报告
1.4 UnitTest框架及原理

做过自动化测试的同学应该都知道python中的unittest框架,它是python自带的一套测试框架,学习起来也相对较容易,unittest框架最核心的四个概念:

  1. test case:就是我们的测试用例,unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的实例就是一个测试用例;unittest中测试用例方法都是以test开头的,且执行顺序会按照方法名的ASCII值排序。
  2. test suite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。
  3. test runner:用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展现出来,如:HTMLTestRunner。
  4. TestLoader:批量执行测试用例-搜索指定文件夹内指定字母开头的模块
  5. test fixure:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。

2.TestCase

说明:TestCase就是测试用例

2.1案例

定义一个实现加法操作的函数,并对改函数进行测试

# test01.py
import unittest
def add(x,y):
    return x+y
class Test01(unittest.TestCase):
    def test_add(self):
        result = add(1,1)
        print("结果为:",result)
    def test_add2(self):
        result = add(1,2)
        print("结果为:",result)
if __name__ == '__main__':
    unittest.main()
2.2 定义测试用例
  1. 导包:import unittest
  2. 定义测试类:新建测试类必须继承unittest.TestCase
  3. 定义测试方法:测试方法名称命名必须为test开头
2.3 执行测试用例

方式一:

​ 使用pycharm在代码上点击鼠标右键,选择使用UnitTest运行

方法二:

​ 调用 unittest.main() 来运行

3.TestSuite

说明:多条测试用例集合在一起就是一个TestSuite

使用:

  1. 实例化:suite = unittest.TestSuite()

    ​ (suite:为TestSuite实例化的名称)

  2. 添加用例:suite.addTest(ClassName("MethodName"))

    ​ (ClassName:为类名;MethodName:为方法名)

  3. 添加扩展:suite.addTest(unittest.makeSuite(ClassName))

    ​ (搜索指定ClassName内test开头的方法并添加到测试套件中)

提示:TestSuite需要配合TestRunner才能被执行

#示例
import unittest
from test01 import Test01
suite = unittest.TestSuite()#实例化

suite.addTest(Test01("test_add"))# 添加一个用例
suite.addTest(unittest.makeSuite(Test01))#批量添加

# 执行
runner = unittest.TextTestRunner()
runner.run(suite)

4.TextTestRunner

说明:TextTestRunner 是用来执行测试用例和测试套件的

使用:

  1. 实例化:runner = unittest.TextTestRunner()
  2. 执行:runner.run(suite) # suite: 为测试套件名称

需求

将test01.py.....test10.py共10条用例批量执行

问题

  1. 使用suite.addtest(unittest.makeSuite(className)) 导入10条测试类
  2. .addtest()需要添加10次

5. TestLoader

说明:

​ 用来加载TestCase到TestSuite中,即加载满足条件的测试用例,并把测试用例封装成测试套件

使用unittest.TestLoader,通过该类下面的discover()方法自动搜索指定目录下指定开头的.py文件;并将查找到的测试用例组装到测试套件

用法:

​ suite = unittest.TestLoader().discover(test_dir, pattern = 'test*.py')

自动搜索指定目录下指定开头的.py文件,并将查找到的测试用例组装到测试套件

test_dir:为指定的测试用例的目录

pattern:为查找的.py文件的格式,默认为‘test*.py’

也可以使用unittest.defaultTestLoader 代替 unittest.TestLoader()

5.1 TestLoader与TestSuite区别

共同点:都是测试套件;不同点:实现方式不同

  1. TestSuite需要手动添加测试用例(可以添加测试类,也可以添加测试类中的某个测试方法)
  2. TestLoader搜索指定目录下指定开头.py文件,并添加测试类中的所有的测试方法,不能指定添加测试方法

6. Fixture

需求:在一个测试类中定义多个测试方法,查看每个测试方法执行完所花费的时间

说明: Fixture是一个概述,对一个测试用例环境的初始化和销毁就是一个 Fixture

Fixture控制级别:

  1. 函数级别 def setUp() / def tearDown()

    ​ 特性:几个测试函数,被执行几次。每个测试函数执行之前都会执行setUp,执行之后都会执行tearDown

  2. 类级别 def setUpClass() / def tearDownClass()

    ​ 特性:测试类运行之前运行一次setUpClass;类运行之后运行一次tearDownClass

    ​ 注意:类方法必须使用 @classmethod装饰

  3. 模块级别 def setUpModule() / def tearDownModule()

    ​ 特性:模块运行之前执行一次 setUpModule;模块运行之后执行一次 tearDownModule

提示:

​ 无论使用函数级别还是类几倍,最后常用场景为:

​ 初始化:

  		1. 获取浏览器实例化对象
  		2. 最大化浏览器
  		3. 隐式等待

结束:

​ 关闭浏览器驱动对象

案例:

需求:使用UnitTest框架对tpshop项目测试
1). 点击登录,进入登录页面
2). 输入用户名和密码,不输入验证码,直接点击登录按钮
3). 获取错误提示信息

import time
import unittest
from time import sleep
from selenium import webdriver
from parameterized import parameterized
class TestTpshopLogin(unittest.TestCase):
    #初始化
    def setUp(self):
        # 获取浏览器驱动对象
        self.driver =webdriver.Chrome()
        #打开url
        url ='http://www.tpshop.com'
        self.driver.get(url)
        #最大化
        self.driver.maximize_window()
        #隐式等待
        self.driver.implicitly_wait(30)

    def tearDown(self):
        #关闭浏览器驱动
        sleep(5)
        self.driver.quit()

    def test_login_code_null(self):
        driver = self.driver
        # 点击登录页面
        driver.find_element_by_link_text("登录").click()
        # 输入用户名
        driver.find_element_by_id("username").send_keys("11234567843")
        # 输入密码
        driver.find_element_by_name("password").send_keys("23615115")
        # 点击登录按钮
        driver.find_element_by_name("sbtbutton").click()
        # 获取页面错误信息
        result = driver.find_element_by_css_selector(".layui-layer-padding").text
        print("result:",result)
        expect_result ="验证码不能为空!!"
        try:
            # 断言
            self.assertEqual(expect_result,result)
        except AssertionError:
            # 截图
            driver.get_screenshot_as_file("./{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
            # 抛出异常
            raise

7. Unittest断言

7.1 什么是断言

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

7.2 为什么学习断言

自动化监本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,所以我们需要让程序代替人

为检测程序执行的结果是否符合预期结果,就需要使用断言

7.3 Unittest断言方法

说明:

  1. Unittest中提供了非常丰富的断言方法
  2. 复杂的断言方法在自动化测试中几乎使用不到,所以只需要掌握几个常用的即可

常用的Unittest断言方法

序号 断言方法 断言描述
1 assertTrue(rxpr, msg=None) 验证expr是true,如果为false,则fail
2 assertFalse(expr, msg=None) 验证expr是false如果为true,则fail
3 assertEqual(expected, actual, msg=None) 验证expected == actual,不等则fail
4 assertNotEqual(first, second, msg=None) 验证first != second,相等则fail
5 assertIsNone(obj, msg=None) 验证obj是None,不是则fail
6 assertIsNotNone(obj, msg=None) 验证obj不是是None,是则fail
7 assertIn(member, container, msg=None) 验证是否member in container
8 assertNotIn(member, container, msg=None) 验证是否member not in container

如果断言失败即不通过就会抛出一个AssertionError断言错误,成功则标识为通过,以上几种方式都有一个共同点,就是都有一个msg参数,默认是None,即msg = None,如果指定msg参数的值,则将该信息作为失败的错误信息返回。

8、参数化

  1. 为什么要参数化:

    ​ 解决冗余代码问题

  2. 什么是参数化:

    ​ 根据需求动态获取参数并引用的过程

  3. 参数化应用场景

    ​ 解决相同业务逻辑,不同测试数据问题

通过参数的方式来传递数据,从而实现数据和脚本分离。并且可以实现用例的重复执行

unittest测试框架,本身不支持参数化,但是可以通过安装扩展插件parameterized来实现

安装

​ pip install parameterized

使用方式

  • 导包:from parameterized import parameterized

  • 修饰测试函数 @parameterized.expand([数据])

    ​ 数据格式:

    		1. 单个参数:类型为列表
    		2. 多个参数:类型为列表嵌套元组
    		3. 在测试函数中的参数设置变量引用参数值,注意:变量的数量必须和数据值的个数相同
    

9、跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行

使用方式

  1. 直接将测试函数标记成跳过

    ​ @unittest.skip('代码未完成')

  2. 根据条件判断测试函数是否跳过

    ​ @unittest.skipIf(condition, reason)

10、生成HTML测试报告

操作步骤

  1. 复制HTMLTestRunner.py文件到指定目录

  2. 导包 from HTNLTestRunner import HTMLTestRunner

  3. 获取报告存放文件流,并实例化HTMLTestRunner类,执行run方法

    ​ 注意:生成HTML报告,必须使用wb,以二进制形式写入

with open(report_dir, "wb") as f :
    HTMLTestRunner(stream=f, verbosity=2, tit le="XXX自动化测试报告", description="操作系统")
posted @ 2021-07-12 18:11  本该是你  阅读(394)  评论(0编辑  收藏  举报