IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 自学Python+Selenium自动化测试 -> 正文阅读

[开发测试]自学Python+Selenium自动化测试

作者:%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E4%B8%89%E3%80%81unittest%E6%A1%86%E6%9E%B6%E6%8B%86%E5%88%86%E4%BB%8B%E7%BB%8D

? ? ? ? 毛泽东说:“我一生最大的爱好是读书”,“饭可以一日不吃,觉可以一日不睡,书不可以一日不读”。

---毛泽东的读书学习生涯(上)

????????学习是文明传承之途、人生成长之梯、政党巩固之基、国家兴盛之要。

---谈论学习也不行?


? ? ? ??退伍回来10个多月,奈何没有相关的软件测试工作经验和经历,而且毕业四五年没碰过了软件专业了,加之现在疫情的变化无常,报培训班时间不够自由,所以回来边恶补专业知识,边找相关工作。只能是四处碰壁,让我学习的欲望更加强烈。

? ? ? ? 今天也恰巧看到CSDN话题挑战赛第2期中的《学习笔记》这个参赛话题很符合我,正好把我近期学习的(四)自动化测试-unittest框架简单总结一下,方便自己以后找出来看看。


CSDN话题挑战赛第2期

参赛话题:学习笔记


目? ? 录

? ? ? ? 一、前期脚本问题

? ? ? ? 二、融入unittest框架

? ? ? ? 1、unittest框架好处

????????2、unittest框架工作原理

? ? ? ? 三、unittest框架拆分介绍

????????1、导入unittest包

????????2、创建测试用例类

????????3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)

????????4、创建测试用例

????????5、测试用例执行

????????6、断言

?????????7、python代码和运行结果

? ? ? ? 四、脚本优化

????????1、测试用例主执行文件

????????2、测试结果优化

????????3、测试报告输出---SMTP(未完结)

????????五、项目结构(未完结)

????????1、public

????????2、test_cases

????????3、test_datas

????????4、test_reports

????????5、test.py

????????6、attachments

????????7、confs


? ? ? ? 一、前期脚本问题

? ? ? ? 1、测试用例过多,只能单一执行,或者导包执行。

? ? ? ? 2、断言方式简单且不实用,日志只能体现在控制台输出,无法体现在报告中。

? ? ? ? 3、无法体现测试报告中的效果:测试用例数量、执行数量、通过数量、失败数量以及失败原因。


? ? ? ? 二、融入unittest框架

????????不仅仅是代码级别的功能测试、逻辑覆盖

? ? ? ? 1、unittest框架好处

? ? ? ? (1)提供用例组织与执行

? ? ? ? (2)提供丰富的断言方法

? ? ? ? (3)提供丰富的日志和报告(HTML格式更直观展示)

????????2、unittest框架工作原理

????????(1)Fixture(固定件)

????????TestCase:测试用例、脚本

????????TestSuite:测试集合、套件、文件夹、统一管理多条测试用例

????????TestRunner:测试运行器

????????TestLoader:测试用例加载器

????????TestRusult:测试结果、字典类型

? ? ? ? (2)单元测试代码段

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/3 16:39
# software: PyCharm

"""
    单元测试:
        测试对象:类中的方法(函数)
"""


class MyMath:
    """定义运算函数:实现加减乘除算法"""

    @staticmethod
    def add(a, b):
        """加法"""
        # 测试问题:若a是字符串,b是整型,应该是字符串拼接运算
        if isinstance(a, str) and isinstance(b, int):
            b = str(b)
            return a + b
        else:
            return a + b

    @staticmethod
    def subtract(a, b):
        """减法"""
        return a - b

    @staticmethod
    def multiply(a, b):
        """乘法"""
        return a * b

    @staticmethod
    def divide(a, b):
        """除法"""
        if b == 0:
            return "除数不能是0,小学生都知道的啊"
        else:
            return a / b


if __name__ == '__main__':
    """单元测试-代码功能验证"""
    mm = MyMath()
    # 实现第一条加法测试用例
    actual_value = mm.add(1, 1)
    expect_value = 2
    if actual_value == expect_value:
        print("加法功能实现正确")

    # 实现第二条加法测试用例:can only concatenate str (not "int") to str
    try:
        actual_value = mm.add("a", 1)
        expect_value = "无法运算"
        if actual_value == expect_value:
            print("加法功能实现正确")
    except Exception as e:
        print(f"加法功能实现正确:{e}")

    # 实现第三条加法测试用例
    try:
        actual_value = mm.add("a", "b")
        expect_value = "ab"
        if actual_value == expect_value:
            print("加法功能实现正确")
    except Exception as e:
        print(f"加法功能实现正确:{e}")

? ? ? ? 三、unittest框架拆分介绍

????????1、导入unittest包

import unittest

????????2、创建测试用例类

????????继承单元测试框架的单元测试用例的类unittest.TestCase

class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

????????3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)

????????setUp()、test_xxx()、tearDown()执行顺序与位置无关,且每执行一条测试用例,setUp()和tearDown()都会执行一次(无论该测试用例是否通过)。

????????@classmethod注解的方法是类方法,不用创建对象也可以用的方法,在对象进入内存之前就已经存在的方法,随着类一起进内存。

????????(1)setUp()? #?初始化、环境搭建

????????(2)test_xxx()? #?测试用例方法、步骤

????????(3)tearDown()? #?还原测试用例环境

? ? ? ? (4)@classmethod-setUpClass()? #?对当前测试用例类的所有测试用例进行初始化,只在类执行开始执行一次

? ? ? ? (5)@classmethod-tearDownClass()? #?对当前测试用例类的所有测试用例资源进行释放,只在类执行结束执行一次

import unittest

# from importlib import import_module
from my_math import MyMath


class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

    # 注解:给方法指定特殊含义
    @classmethod
    def setUpClass(cls) -> None:
        print("setUpClass方法")

    @classmethod
    def tearDownClass(cls) -> None:
        print("tearDownClass方法")

    def setUp(self) -> None:
        """方法名固定、self参数不能少"""
        self.mm = MyMath()
        print("setUp方法")

    def test_add(self):
        """test_是测试用例:加法运算-正向"""
        add_value = self.mm.add(1, 1)
        # 断言方法,判断预期结果和实际结果是否相等
        # AssertionError: 2 != 3 : 预期和实际结果不相等
        self.assertEqual(add_value, 2, "预期和实际结果不相等")
        print("test_add方法")

    def tearDown(self) -> None:
        """方法名固定、self参数不能少"""
        print("tearDown方法")

????????4、创建测试用例

? ? ? ? (1)test_开头

import unittest

from my_math import MyMath


class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

    def test_add(self):
        """test_是测试用例:加法运算-正向"""
        print("test_add方法")

    def test_add_1(self):
        """test_是测试用例:加法运算-反向"""
        add_value = self.mm.add("a", 1)
        self.assertNotEqual(add_value, "a1", "预期和实际结果不相等")
        print("test_add_0方法")

    def test_add_2(self):
        """test_是测试用例:加法运算-正向"""
        add_value = self.mm.add("a", "b")
        self.assertEqual(add_value, "ab", "预期和实际结果不相等")
        print("test_add_1方法")

????????5、测试用例执行

? ? ? ? (1)main()执行方法

????????unittest.main()? #?所有测试用例执行一遍,但无法控制执行顺序(默认按照字母顺序执行)

if __name__ == '__main__':
    """此文件运行时执行"""
    # 执行测试用例类中所有的测试用例
    unittest.main()

? ? ? ? (2)TestSuite()自带加载执行方法

????????test_suite = unittest.TestSuite()? #?创建测试套件对象

????????test_suite.addTest(类名("用例名"))? #?将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序

????????test_suite.addTests([类名("用例名"),...])? #?将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序

????????test_suite.addTests(map(类名, ["用例名",...]))? #?使用map()方法将类应用于用例返回列表

????????test_suite.run(unittest.TestResult())? #?运行测试套件,并存储测试结果?

if __name__ == '__main__':
    """此文件运行时执行"""

    # addTest(类名("用例名")):将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
    test_suite = unittest.TestSuite()
    # 在测试套件中添加一条测试用例
    test_suite.addTest(MyMathUnittest("test_add"))
    test_result = unittest.TestResult()
    test_suite.run(test_result)
    print(test_result.__dict__)
if __name__ == '__main__':
    """此文件运行时执行"""

    # addTests([类名("用例名"),...]):将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
    test_suites = unittest.TestSuite()
    # 在测试套件中添加多条测试用例
    test_list = map(MyMathUnittest, ["test_add_2", "test_add_1", "test_add"])
    test_suites.addTests(test_list)
    test_results = unittest.TestResult()
    test_suites.run(test_results)
    print(test_results.__dict__)

? ? ? ? (3)TestLoader()特定加载方法

????????test_loader = unittest.TestLoader()? #?创建测试用例加载器对象

????????loader_suite = test_loader.loadTestsFromName("模块名")? #?将某模块中的所有测试用例加载到测试套件中

????????loader_suite = test_loader.loadTestsFromName("模块名.类名")? #?将某模块中的某类中的的所有测试用例加载到测试套件中

????????loader_suite = test_loader.loadTestsFromName(name="类名", module=import_module("模块名"))? #?将某模块中的某类中的的所有测试用例加载到测试套件中

????????loader_suite = test_loader.loadTestsFromName("模块名.类名.测试用例名")? #?将某一条测试用例加载到测试套件中

????????loader_suite = test_loader.loadTestsFromName(name="类名.测试用例名", module=import_module("模块名"))? #?将某一条测试用例加载到测试套件中

????????#?__import__(name):通过python解释器导入模块,非通用

????????loader_suite = test_loader.loadTestsFromModule(__import__("模块名"))? #?将某模块中的所有测试用例加载到测试套件中

????????#?importlib.import_module(name):以编程方式导入模块

????????loader_suite = test_loader.loadTestsFromModule(import_module("模块名"))? #?将某模块中的所有测试用例加载到测试套件中

????????loader_suite = test_loader.discover("./模块目录", "模块名正则表达式.py")? #?将指定模块中的所有测试用例一次性加载

if __name__ == '__main__':
    """此文件运行时执行"""

    # 加载测试用例到测试套件中
    test_loader = unittest.TestLoader()


    # loadTestsFromName("模块名"):将某模块中的所有测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame")


    # loadTestsFromName("模块名.类名"):将某模块中的某类中的的所有测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest")
    # loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest", module=import_module("unittest_frame"))


    # loadTestsFromName("模块名.类名.测试用例名"):将某一条测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest.test_add")
    # loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest.test_add", module=import_module("unittest_frame"))


    # __import__(name):通过python解释器导入模块,非通用
    #loader_suite = test_loader.loadTestsFromModule(__import__("unittest_frame"))

    # import_module(name):以编程方式导入模块
    # loader_suite = test_loader.loadTestsFromModule(import_module("unittest_frame"))


    # discover("./模块目录", "模块名正则表达式.py"):将指定模块中的所有测试用例一次性加载
    # loader_suite = test_loader.discover("./", "unit*.py")
    # defaultTestLoader是默认的共享加载器
    discover = unittest.defaultTestLoader.discover("./", "unit*.py")

? ? ? ? (4)TestRunner()特定执行方法

? ? ? ? # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中

with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:

????????# descriptions=True:测试用例是否显示注释;True表示显示,False表示不显示

????????# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示

????????test_runner = unittest.TextTestRunner(f_txt,descriptions=True,verbosity=1)

????????test_runner.run(loader_suite)

????????f_txt.close()?

if __name__ == '__main__':
    """此文件运行时执行"""

    with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
        # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
        text_runner = unittest.TextTestRunner(f_txt, verbosity=2)
        text_runner.run(discover)
        f_txt.close()

????????6、断言

? ? ? ? (1)一个自动化测试用例:测试步骤和断言缺一不可

? ? ? ? (2)unittest自带断言方法

????????都可以在参数中设置错误提示信息, msg=""

assertEqual(a, b):a==b判断相等

assertNotEqual(a, b):a!=b判断不相等

assertTrue(x):bool(x) is True判断布尔值为True

assertFalse(x):booI(x) is False判断布尔值为False

assertIs(a, b):a is b判断身份(内存地址值)相等

assertIsNot(a, b):a is not b判断身份(内存地址值)不相等

assertIsNone(x):x is None判断为空指针

assertIsNotNone(x):x is not None判断不为空指针

assertIn(a, b):a in b判断a在b中

assertNotIn(a, b):a not in b判断a不在b中

assertIsInstance(a, b):isinstance(a,b)判断a是b的实例对象

assertNotIsInstance(a, b):not isinstance(a,b)判断a不是b的实例对象?

import unittest


class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

    def test_ae(self):
        """断言方法assertEqual---判断相等"""
        self.assertEqual(1, 1)
        self.assertEqual(1, 2)

    def test_ane(self):
        """断言方法assertNotEqual---判断不相等"""
        self.assertNotEqual(1, 1)
        self.assertNotEqual(1, 2)

    def test_at(self):
        """断言方法assertTrue---判断布尔值为True"""
        self.assertTrue(1 == 1)
        self.assertTrue(1 == 2)

    def test_af(self):
        """断言方法assertFalse---判断布尔值为False"""
        self.assertFalse(1 == 1)
        self.assertFalse(1 == 2)

    def test_ais(self):
        """断言方法assertIs---判断身份(内存地址值)相等"""
        a, b, c = 1, 1, 2
        self.assertIs(a, b)
        self.assertIs(a, c)

    def test_ais_not(self):
        """断言方法assertIsNot---判判断身份(内存地址值)不相等"""
        a, b, c = 1, 1, 2
        self.assertIsNot(a, b)
        self.assertIsNot(a, c)

    def test_ais_none(self):
        """断言方法assertIsNone---判断为空指针"""
        self.assertIsNone(None)
        self.assertIsNone(1)

    def test_ais_not_none(self):
        """断言方法assertIsNotNone---判断不为空指针"""
        self.assertIsNotNone(None)
        self.assertIsNotNone(1)

    def test_ai(self):
        """断言方法assertIn---判判断a在b中"""
        self.assertIn(1, [1, 2, 3])
        self.assertIn(1, [2, 3, 4])

    def test_ani(self):
        """断言方法assertNotIn---判断a不在b中"""
        self.assertNotIn(1, [1, 2, 3])
        self.assertNotIn(1, [2, 3, 4])

    def test_aii(self):
        """断言方法assertIsInstance--- 判断a是b的实例对象"""
        self.assertIsInstance(1, int)
        self.assertIsInstance(1, str)

    def test_anii(self):
        """断言方法assertNotIsInstance---判断a不是b的实例对象"""
        self.assertNotIsInstance(1, int)
        self.assertNotIsInstance(1, str)

?????????7、python代码和运行结果

????????(1)python代码

????????注意:

????????????????测试用例虽然失败,但是里面的两条断言中有一条是通过的!!!

????????????????只是为了方便测试此断言的运行结果!!!

? ? ? ? ? ? ? ? 里面运行了前两个测试套件的结果都会展示在运行窗口中!!!

? ? ? ? ? ? ? ? 测试用例加载器testloader()就相当于把测试用例加载到了测试套件中,所以返回的对象是测试套件,每次使用一种即可!!!

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/6 10:47
# software: PyCharm

"""
unittest框架:
    1、导入unittest包
    2、创建测试用例类(继承单元测试框架的单元测试用例的类)
    3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)
    (1)setUp()、test_xxx()、tearDown()执行顺序与位置无关,且每执行一条测试用例,setUp()和tearDown()都会执行一次(无论该测试用例是否通过)
    (2)setUp()  # 初始化、环境搭建
    (3)test_xxx()  # 测试用例方法、步骤
    (4)tearDown()  # 还原测试用例环境
    (5) @classmethod注解的方法是类方法,不用创建对象也可以用的方法,在对象进入内存之前就已经存在的方法,随着类一起进内存
    (6)@classmethod-setUpClass()  # 对当前测试用例类的所有测试用例进行初始化,只在类执行开始执行一次
    (7)@classmethod-tearDownClass()  # 对当前测试用例类的所有测试用例资源进行释放,只在类执行结束执行一次
    4、创建测试用例:test_开头
    5、测试用例执行:
    (1)main()执行方法
        unittest.main()  # 所有测试用例执行一遍,但无法控制执行顺序(默认按照字母顺序执行)
    (2)TestSuite()自带加载执行方法
        test_suite = unittest.TestSuite()  # 创建测试套件对象
        test_suite.addTest(类名("用例名"))  # 将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
        test_suite.addTests([类名("用例名"),...])  # 将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
        test_suite.addTests(map(类名, ["用例名",...]))  # 使用map()方法将类应用于用例返回列表
        test_suite.run(unittest.TestResult())  # 运行测试套件,并存储测试结果
    (3)TestLoader()特定加载方法
        test_loader = unittest.TestLoader()  # 创建测试用例加载器对象
        loader_suite = test_loader.loadTestsFromName("模块名")  # 将某模块中的所有测试用例加载到测试套件中
        loader_suite = test_loader.loadTestsFromName("模块名.类名")  # 将某模块中的某类中的的所有测试用例加载到测试套件中
        loader_suite = test_loader.loadTestsFromName(name="类名", module=import_module("模块名"))  # 将某模块中的某类中的的所有测试用例加载到测试套件中
        loader_suite = test_loader.loadTestsFromName("模块名.类名.测试用例名")  # 将某一条测试用例加载到测试套件中
        loader_suite = test_loader.loadTestsFromName(name="类名.测试用例名", module=import_module("模块名"))  # 将某一条测试用例加载到测试套件中
        # __import__(name):通过python解释器导入模块,非通用
        loader_suite = test_loader.loadTestsFromModule(__import__("模块名"))  # 将某模块中的所有测试用例加载到测试套件中
        # importlib.import_module(name):以编程方式导入模块
        loader_suite = test_loader.loadTestsFromModule(import_module("模块名"))  # 将某模块中的所有测试用例加载到测试套件中
        loader_suite = test_loader.discover("./模块目录", "模块名正则表达式.py")  # 将指定模块中的所有测试用例一次性加载
    (4)TestRunner()特定执行方法
        # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
        with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
            # descriptions=True:测试用例是否显示注释;True表示显示,False表示不显示
            # verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
            test_runner = unittest.TextTestRunner(f_txt,descriptions=True,verbosity=1)
            test_runner.run(loader_suite)
            f_txt.close()
    6、断言
    (1)一个自动化测试用例:测试步骤和断言缺一不可
    (2)unittest自带断言方法
    都可以在参数中设置错误提示信息, msg=""
    assertEqual(a, b)  # a==b判断相等
    assertNotEqual(a, b)  # a!=b判断不相等
    assertTrue(x)  # bool(x) is True判断布尔值为True
    assertFalse(x)  # booI(x) is False判断布尔值为False
    assertIs(a, b)  # a is b判断身份(内存地址值)相等
    assertIsNot(a, b)  # a is not b判断身份(内存地址值)不相等
    assertIsNone(x)  # x is None判断为空指针
    assertIsNotNone(x)  # x is not None判断不为空指针
    assertIn(a, b)  # a in b判断a在b中
    assertNotIn(a, b)  # a not in b判断a不在b中
    assertIsInstance(a, b)  # isinstance(a,b)判断a是b的实例对象
    assertNotIsInstance(a, b)  # not isinstance(a,b)判断a不是b的实例对象
    7、测试用例主执行文件
    使用默认的可共享的加载器更方便加载更多的测试用例
    discover = unittest.defaultTestLoader.discover("./模块目录", "模块名正则表达式.py")
    8、测试结果优化
    (1)格式优化---HTML
    # HTTPTestRunner().run(测试套件):执行测试用例,并将结果以HTML页面形式写入文件中
    with open("unittest_result.html", "wb", encoding="utf-8") as f_html:
        # wb:以字节形式写入文件
        # verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
        # title="":网页标题
        # descriptions="":测试描述
        html_runner = HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="页面标题",description="测试描述")
        html_runner.run(discover)
        f_html.close()
    (2)显示优化---文档注释
    在每个测试用例中添加文档'''一行注释'''
    (3)存储优化---文件名规范
    # 文件命名:路径+时间格式+ .html
    filename = f"../测试报告/{time.strftime('%Y-%m-%d-%H-%M-%S')}.html"
    注意时间格式获取方法:
        time.time()  # 获取当前时间戳
        time.ctime()  # 获取当前时间的字符串格式
        time.localtime()  # 获取当前时间的结构化格式
        time.strftime()  # 获取当前时间,并可格式化为字符串
            %Y Year with century as a decimal number.
            %m Month as a decimal number [01,12].
            %d Day of the month as a decimal number [01,31].
            %H Hour (24-hour clock) as a decimal number [00,23].
            %M Minute as a decimal number [00,59].
            %S Second as a decimal number [00,61].
            %z Time zone offset from UTC.
            %a Locale's abbreviated weekday name.
            %A Locale's full weekday name.
            %b Locale's abbreviated month name.
            %B Locale's full month name.
            %c Locale's appropriate date and time representation.
            %I Hour (12-hour clock) as a decimal number [01,12].
            %p Locale's equivalent of either AM or PM.
"""
import HTTPTestRunner
import time
import unittest

# from importlib import import_module
from my_math import MyMath


class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

    # 注解:给方法指定特殊含义
    @classmethod
    def setUpClass(cls) -> None:
        print("setUpClass方法")

    @classmethod
    def tearDownClass(cls) -> None:
        print("tearDownClass方法")

    def setUp(self) -> None:
        """方法名固定、self参数不能少"""
        self.mm = MyMath()
        print("setUp方法")

    def test_add(self):
        """test_是测试用例:加法运算-正向"""
        add_value = self.mm.add(1, 1)
        # 断言方法,判断预期结果和实际结果是否相等
        # AssertionError: 2 != 3 : 预期和实际结果不相等
        self.assertEqual(add_value, 2, "预期和实际结果不相等")
        print("test_add方法")

    def test_add_1(self):
        """test_是测试用例:加法运算-反向"""
        add_value = self.mm.add("a", 1)
        self.assertNotEqual(add_value, "a1", "预期和实际结果不相等")
        print("test_add_0方法")

    def test_add_2(self):
        """test_是测试用例:加法运算-正向"""
        add_value = self.mm.add("a", "b")
        self.assertEqual(add_value, "ab", "预期和实际结果不相等")
        print("test_add_1方法")

    def test_ae(self):
        """断言方法assertEqual---判断相等"""
        self.assertEqual(1, 1)
        self.assertEqual(1, 2)

    def test_ane(self):
        """断言方法assertNotEqual---判断不相等"""
        self.assertNotEqual(1, 1)
        self.assertNotEqual(1, 2)

    def test_at(self):
        """断言方法assertTrue---判断布尔值为True"""
        self.assertTrue(1 == 1)
        self.assertTrue(1 == 2)

    def test_af(self):
        """断言方法assertFalse---判断布尔值为False"""
        self.assertFalse(1 == 1)
        self.assertFalse(1 == 2)

    def test_ais(self):
        """断言方法assertIs---判断身份(内存地址值)相等"""
        a, b, c = 1, 1, 2
        self.assertIs(a, b)
        self.assertIs(a, c)

    def test_ais_not(self):
        """断言方法assertIsNot---判判断身份(内存地址值)不相等"""
        a, b, c = 1, 1, 2
        self.assertIsNot(a, b)
        self.assertIsNot(a, c)

    def test_ais_none(self):
        """断言方法assertIsNone---判断为空指针"""
        self.assertIsNone(None)
        self.assertIsNone(1)

    def test_ais_not_none(self):
        """断言方法assertIsNotNone---判断不为空指针"""
        self.assertIsNotNone(None)
        self.assertIsNotNone(1)

    def test_ai(self):
        """断言方法assertIn---判判断a在b中"""
        self.assertIn(1, [1, 2, 3])
        self.assertIn(1, [2, 3, 4])

    def test_ani(self):
        """断言方法assertNotIn---判断a不在b中"""
        self.assertNotIn(1, [1, 2, 3])
        self.assertNotIn(1, [2, 3, 4])

    def test_aii(self):
        """断言方法assertIsInstance--- 判断a是b的实例对象"""
        self.assertIsInstance(1, int)
        self.assertIsInstance(1, str)

    def test_anii(self):
        """断言方法assertNotIsInstance---判断a不是b的实例对象"""
        self.assertNotIsInstance(1, int)
        self.assertNotIsInstance(1, str)

    def test_multiply(self):
        """test_是测试用例:"""
        multiply_value = self.mm.multiply(1, 1)
        # 断言方法,判断预期结果和实际结果是否相等
        self.assertEqual(multiply_value, 1, "预期和实际结果不相等")
        print("test_multiply方法")

    def tearDown(self) -> None:
        """方法名固定、self参数不能少"""
        print("tearDown方法")



if __name__ == '__main__':
    """此文件运行时执行"""
    # 执行测试用例类中所有的测试用例
    # unittest.main()

    # addTest(类名("用例名")):将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
    test_suite = unittest.TestSuite()
    # 在测试套件中添加一条测试用例
    test_suite.addTest(MyMathUnittest("test_add"))
    test_result = unittest.TestResult()
    test_suite.run(test_result)
    print(test_result.__dict__)

    # addTests([类名("用例名"),...]):将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
    test_suites = unittest.TestSuite()
    # 在测试套件中添加多条测试用例
    test_list = map(MyMathUnittest, ["test_add_2", "test_add_1", "test_add"])
    test_suites.addTests(test_list)
    test_results = unittest.TestResult()
    test_suites.run(test_results)
    print(test_results.__dict__)

    # 加载测试用例到测试套件中
    # test_loader = unittest.TestLoader()
    # loadTestsFromName("模块名"):将某模块中的所有测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame")
    # loadTestsFromName("模块名.类名"):将某模块中的某类中的的所有测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest")
    # loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest", module=import_module("unittest_frame"))
    # loadTestsFromName("模块名.类名.测试用例名"):将某一条测试用例加载到测试套件中
    # loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest.test_add")
    # loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest.test_add", module=import_module("unittest_frame"))
    # __import__(name):通过python解释器导入模块,非通用
    # loader_suite = test_loader.loadTestsFromModule(__import__("unittest_frame"))
    # import_module(name):以编程方式导入模块
    # loader_suite = test_loader.loadTestsFromModule(import_module("unittest_frame"))
    # discover("./模块目录", "模块名正则表达式.py"):将指定模块中的所有测试用例一次性加载
    # loader_suite = test_loader.discover("./", "unit*.py")
    # defaultTestLoader是默认的共享加载器
    discover = unittest.defaultTestLoader.discover("./", "unit*.py")

    with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
        # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
        text_runner = unittest.TextTestRunner(f_txt, verbosity=2)
        text_runner.run(discover)
        f_txt.close()

????????(2)运行结果

? ? ? ? ?注意:此运行结果已存入(unittest_result.txt)文件中

test_add (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-正向 ... ok test_add_1 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-反向 ... ERROR test_add_2 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-正向 ... ok test_ae (unittest_frame.MyMathUnittest) 断言方法assertEqual---判断相等 ... FAIL test_af (unittest_frame.MyMathUnittest) 断言方法assertFalse---判断布尔值为False ... FAIL test_ai (unittest_frame.MyMathUnittest) 断言方法assertIn---判判断a在b中 ... FAIL test_aii (unittest_frame.MyMathUnittest) 断言方法assertIsInstance--- 判断a是b的实例对象 ... FAIL test_ais (unittest_frame.MyMathUnittest) 断言方法assertIs---判断身份(内存地址值)相等 ... FAIL test_ais_none (unittest_frame.MyMathUnittest) 断言方法assertIsNone---判断为空指针 ... FAIL test_ais_not (unittest_frame.MyMathUnittest) 断言方法assertIsNot---判判断身份(内存地址值)不相等 ... FAIL test_ais_not_none (unittest_frame.MyMathUnittest) 断言方法assertIsNotNone---判断不为空指针 ... FAIL test_ane (unittest_frame.MyMathUnittest) 断言方法assertNotEqual---判断不相等 ... FAIL test_ani (unittest_frame.MyMathUnittest) 断言方法assertNotIn---判断a不在b中 ... FAIL test_anii (unittest_frame.MyMathUnittest) 断言方法assertNotIsInstance---判断a不是b的实例对象 ... FAIL test_at (unittest_frame.MyMathUnittest) 断言方法assertTrue---判断布尔值为True ... FAIL test_multiply (unittest_frame.MyMathUnittest) test_是测试用例: ... ok ====================================================================== ERROR: test_add_1 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-反向 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 99, in test_add_1 add_value = self.mm.add("a", 1) File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\my_math.py", line 19, in add return a + b TypeError: can only concatenate str (not "int") to str ====================================================================== FAIL: test_ae (unittest_frame.MyMathUnittest) 断言方法assertEqual---判断相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 112, in test_ae self.assertEqual(1, 2) AssertionError: 1 != 2 ====================================================================== FAIL: test_af (unittest_frame.MyMathUnittest) 断言方法assertFalse---判断布尔值为False ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 126, in test_af self.assertFalse(1 == 1) AssertionError: True is not false ====================================================================== FAIL: test_ai (unittest_frame.MyMathUnittest) 断言方法assertIn---判判断a在b中 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 154, in test_ai self.assertIn(1, [2, 3, 4]) AssertionError: 1 not found in [2, 3, 4] ====================================================================== FAIL: test_aii (unittest_frame.MyMathUnittest) 断言方法assertIsInstance--- 判断a是b的实例对象 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 164, in test_aii self.assertIsInstance(1, str) AssertionError: 1 is not an instance of <class 'str'> ====================================================================== FAIL: test_ais (unittest_frame.MyMathUnittest) 断言方法assertIs---判断身份(内存地址值)相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 133, in test_ais self.assertIs(a, c) AssertionError: 1 is not 2 ====================================================================== FAIL: test_ais_none (unittest_frame.MyMathUnittest) 断言方法assertIsNone---判断为空指针 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 144, in test_ais_none self.assertIsNone(1) AssertionError: 1 is not None ====================================================================== FAIL: test_ais_not (unittest_frame.MyMathUnittest) 断言方法assertIsNot---判判断身份(内存地址值)不相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 138, in test_ais_not self.assertIsNot(a, b) AssertionError: unexpectedly identical: 1 ====================================================================== FAIL: test_ais_not_none (unittest_frame.MyMathUnittest) 断言方法assertIsNotNone---判断不为空指针 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 148, in test_ais_not_none self.assertIsNotNone(None) AssertionError: unexpectedly None ====================================================================== FAIL: test_ane (unittest_frame.MyMathUnittest) 断言方法assertNotEqual---判断不相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 116, in test_ane self.assertNotEqual(1, 1) AssertionError: 1 == 1 ====================================================================== FAIL: test_ani (unittest_frame.MyMathUnittest) 断言方法assertNotIn---判断a不在b中 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 158, in test_ani self.assertNotIn(1, [1, 2, 3]) AssertionError: 1 unexpectedly found in [1, 2, 3] ====================================================================== FAIL: test_anii (unittest_frame.MyMathUnittest) 断言方法assertNotIsInstance---判断a不是b的实例对象 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 168, in test_anii self.assertNotIsInstance(1, int) AssertionError: 1 is an instance of <class 'int'> ====================================================================== FAIL: test_at (unittest_frame.MyMathUnittest) 断言方法assertTrue---判断布尔值为True ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 122, in test_at self.assertTrue(1 == 2) AssertionError: False is not true ---------------------------------------------------------------------- Ran 16 tests in 0.003s FAILED (failures=12, errors=1)


? ? ? ? 四、脚本优化

????????1、测试用例主执行文件

? ? ? ? (1)使用默认的可共享的加载器更方便加载更多的测试用例

????????discover = unittest.defaultTestLoader.discover("./模块目录", "模块名正则表达式.py")

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 10:18
# software: PyCharm

"""测试用例主执行文件"""
import unittest

discover = unittest.defaultTestLoader.discover("./", "unittest_frame_*.py")
with open("unittest_result1.txt", "a", encoding="utf-8") as f:
    test_runner = unittest.TextTestRunner(f, verbosity=2)
    test_runner.run(discover)

????????2、测试结果优化

? ? ? ? (1)格式优化---HTML

????????# HTTPTestRunner().run(测试套件):执行测试用例,并将结果以HTML页面形式写入文件中

with open("unittest_result.html", "wb", encoding="utf-8") as f_html:

????????# wb:以字节形式写入文件

????????# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示

????????# title="":网页标题

????????# descriptions="":测试描述

????????html_runner =?HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="页面标题",description="测试描述")

????????html_runner.run(discover)

? ? ? ??f_html.close()

import HTTPTestRunner

...


if __name__ == '__main__':
    """此文件运行时执行"""

    # 加载测试用例到测试套件中
    discover = unittest.defaultTestLoader.discover("./", "unit*.py")

    
    # wb写入字节格式,才能保存到html中
    with open("unittest_result.html", "wb") as f_html:
        # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
        html_runner = HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="unittest测试框架HTML格式测试结果",
                                                    description="运行XX测试用例的结果展示")
        html_runner.run(discover)
        f_html.close()

?????????(2)显示优化---文档注释

在每个测试用例中添加文档"""一行注释"""

class MyMathUnittest(unittest.TestCase):
    """继承单元测试框架的单元测试用例类"""

    def test_add(self):
        """test_是测试用例:加法运算-正向"""

????????(3)存储优化---命名规范

????????# 文件命名:路径+时间格式+ .html

filename = f"../测试报告/{time.strftime('%Y-%m-%d-%H-%M-%S')}.html"

????????注意时间格式获取方法:

time.time() ?# 获取当前时间戳

time.ctime() ?# 获取当前时间的字符串格式

time.localtime() ?# 获取当前时间的结构化格式

time.strftime() ?# 获取当前时间,并可格式化为字符串

%Y Year with century as a decimal number.

%m Month as a decimal number [01,12].

%d Day of the month as a decimal number [01,31].

%H Hour (24-hour clock) as a decimal number [00,23].

%M Minute as a decimal number [00,59].

%S Second as a decimal number [00,61].

%z Time zone offset from UTC.

%a Locale's abbreviated weekday name.

%A Locale's full weekday name.

%b Locale's abbreviated month name.

%B Locale's full month name.

%c Locale's appropriate date and time representation.

%I Hour (12-hour clock) as a decimal number [01,12].

%p Locale's equivalent of either AM or PM.?

    # 文件命名:路径+时间格式+ .html
    time_format = time.strftime('%Y-%m-%d-%H-%M-%S')
    filename = f"测试报告/{time_format}.html"
    with open(filename, "wb") as f_html:

????????3、测试报告输出---SMTP(未完结)

????????集成右键自动发送:脚本运行结束后,将测试结果自动发送给相关负责人。

????????email模块:构造邮件

????????smtplib模块发送邮件

????????登录密码是授权码


????????五、项目结构

????????优点:方便分类、方便分工协作

????????1、public

????????公共模块,如登录和退出系统模块,被test_case中模块调用的模块(发邮件、写日志)

????????2、test_cases

????????测试用例文件py,每个文件可以有多个test_开头的测试方法(用例)

????????3、test_datas

????????测试数据,如csv、excel文件

????????4、test_reports

????????测试结果报告

????????5、test.py

????????主测试类

????????6、attachments

????????附件模块

????????7、confs

????????配置文件?

?


? ? ? ? 六、unittest框架下的数据驱动测试

????????1、再看数据存储

????????大部分自动化测试采用测试脚本与测试数据分离

????????好处:降低维护成本,迁移成本以及提高效率

????????

????????存储形式

????????字典、列表(脚本内)

????????excel、csv、配置文件、数据库存储(脚本外)

测试数据分类管理示例
业务场景普通登录管理员登录数据库连接
数据类型基础数据测试数据临时数据
数据频次偶尔经常一直
数据量级几个几十~几千几万以上

????????2、数据驱动测试(DDT)

????????@ddt? ? ? ? ? ? ?# 标记测试类,支持DDR数据驱动

????????@data()? ? ? ? ?# 标记测试用例,传递参数

????????@unpack? ? ? # 当@data()中的参数时元组、列表时,用于分割序列中的元素

????????@file_data? ? # 标记测试用例,传递文件,支持yaml和json文件

????????实例1---脚本内字典列表(字典中存数据,列表中存字典)

????????流程:

(1)创建字典列表数据dict_data

(2)加载ddt模块(安装ddt、导包(from ddt import ddt, data)

(3)在测试类前加@ddt

(4)在测试用例方法前加@data(*dict_data))

(5)重新声明测试用例名称(添加传递数据的参数reg_data)

(6)使用reg_data["key"]可以按顺序取键对应的值

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 17:38
# software: PyCharm

"""
    数据驱动测试(DDT)
        @ddt  # 标记测试类,支持DDR数据驱动
        @data()  # 标记测试用例,传递参数
        @unpack  # 当@data()中的参数时元组、列表时,用于分割序列中的元素
        @file_data  # 标记测试用例,传递文件,支持yaml和json文件
    1、脚本内字典列表(字典中存数据,列表中存字典)
    (1)创建字典列表数据dict_data
    (2)加载ddt模块
        安装ddt
        导包(from ddt import ddt, data)
        在测试类前加@ddt
        在测试用例方法前加@data(*dict_data)
    (3)重新声明测试用例名称(添加传递数据的参数reg_data)
    (4)使用reg_data["key"]可以按顺序取键对应的值
"""
import time
import unittest

import ddddocr
from ddt import ddt, data
from selenium import webdriver
from selenium.webdriver.common.by import By


@ddt
class VRegUsernameFalse(unittest.TestCase):
    """用户注册---反向测试用例---无效用户名"""

    # 定义字典数据,用于存储注册数据(用户名、邮箱、密码、确认密码)
    dict_data = [
        {"username": "", "email": "eeee@16.com", "password": "123456", "repassword": "123456",
         "except": "请设置用户名"},
        {"username": "a123", "email": "ffff@16.com", "password": "123456", "repassword": "123456",
         "except": "用户名不符合格式要求"},
        {"username": "a1234567890123456", "email": "gggg@16.com", "password": "123456", "repassword": "123456",
         "except": "用户名不符合格式要求"},
        {"username": "1234a", "email": "hhhh@16.com", "password": "123456", "repassword": "123456",
         "except": "用户名不符合格式要求"},
        {"username": "a12*4", "email": "iiii@16.com", "password": "123456", "repassword": "123456",
         "except": "用户名不符合格式要求"}]

    def setUp(self) -> None:
        """搭建测试环境"""
        pass

    @data(*dict_data)
    def test_reg_01(self, reg_data):
        """反向测试用例-用户名"""
        # 创建浏览器驱动对象
        driver = webdriver.Edge()
        # 打开edge浏览器并跳转到verydows首页
        driver.get("http://kkk.xmyxwl.com/")
        # 点击首页“免费注册”按钮
        driver.find_element(by=By.LINK_TEXT, value="免费注册").click()
        time.sleep(1)
        # 用户名可以包含字母、数字或下划线,须以字母开头,长度为5~16个字符
        driver.find_element(value="username").send_keys(reg_data["username"])
        # 请填写您常用的电子邮箱地址,邮箱可用来重置密码,接收订促销信息,订单状态等
        driver.find_element(value="email").send_keys(reg_data["email"])
        # 密码可包含字母、数字或特殊符号,长度为6~32个字符
        driver.find_element(value="password").send_keys(reg_data["password"])
        # 确认您所设置的密码
        driver.find_element(value="repassword").send_keys(reg_data["repassword"])
        # 输入验证码:先将验证码截图成png图片存储在变量中,再通过ddddocr图文识别插件将验证码转换为字符串存储到变量中
        captcha_img = driver.find_element(value="captcha-img").screenshot_as_png
        captcha = ddddocr.DdddOcr().classification(captcha_img)
        driver.find_element(value="captcha").send_keys(captcha)
        time.sleep(0.5)
        # 默认已勾选已阅读完并同意 "用户注册协议"复选框
        # driver.find_element(value="agree").click()
        # 点击立即注册链接
        driver.find_element(by=By.LINK_TEXT, value="立即注册").click()
        time.sleep(5)
        # 注册失败,用户名后侧提示“请设置用户名”或“用户名不符合格式要求”
        actual_value = driver.find_element(by=By.XPATH, value="//*[@id='register-form']/div/dl[1]/dd/span/font").text
        except_value = reg_data["except"]
        self.assertEqual(except_value, actual_value, "注册username反向测试用例失败")
        driver.quit()

    def tearDown(self) -> None:
        """重置测试环境"""
        pass


if __name__ == '__main__':
    unittest.main(verbosity=2)

????????实例2---脚本外excel文件

????????流程:

(1)创建excel文件verydows_reg_email_false.xls

(2)导入ExcelUtil模块

(3)导入excel文件数据,并转换为字典列表dict_data

(4)加载ddt模块(安装ddt、导包(from ddt import ddt, data)

(5)在测试类前加@ddt

(6)在测试用例方法前加@data(*dict_data))

(7)重新声明测试用例名称(添加传递数据的参数reg_data)

(8)使用reg_data["key"]可以按顺序取键对应的值

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 17:38
# software: PyCharm

"""
    数据驱动测试(DDT)
        @ddt  # 标记测试类,支持DDR数据驱动
        @data()  # 标记测试用例,传递参数
        @unpack  # 当@data()中的参数时元组、列表时,用于分割序列中的元素
        @file_data  # 标记测试用例,传递文件,支持yaml和json文件
    2、脚本外excel文件
    (1)创建excel文件verydows_reg_email_false.xls
    (2)导入ExcelUtil模块
    (3)导入excel文件数据,并转换为字典列表dict_data
    (2)加载ddt模块
        安装ddt
        导包(from ddt import ddt,data)
        在测试类前加@ddt
        在测试用例方法前加@data(*dict_data)
    (3)重新声明测试用例名称(添加传递数据的参数reg_data)
    (4)使用reg_data["key"]可以按顺序取键对应的值
"""
import os
import sys
import time
import unittest

import ddddocr
from ddt import ddt, data
from selenium import webdriver
from selenium.webdriver.common.by import By

# 先将目录追加到环境变量中
path = os.path.dirname(os.path.dirname(__file__)) + "\\public"
path1 = sys.path
path1.append(path)

from ExcelUtil import ExcelUtil


@ddt
class VRegEmailFalse(unittest.TestCase):
    """用户注册---反向测试用例---无效邮箱"""

    # 获取excel文件路径
    filepath = os.path.dirname(os.path.dirname(__file__)) + "\\test_datas\\verydows_reg_email_false.xls"
    # 读取excel文件数据
    excel_data = ExcelUtil(filepath)
    # 将excel数据转换为字典列表
    dict_data = excel_data.dict_data()

    def setUp(self) -> None:
        """搭建测试环境"""
        pass

    @data(*dict_data)
    def test_reg_01(self, reg_data):
        """反向测试用例-用户名"""
        # 创建浏览器驱动对象
        driver = webdriver.Edge()
        # 打开edge浏览器并跳转到verydows首页
        driver.get("http://kkk.xmyxwl.com/")
        # 点击首页“免费注册”按钮
        driver.find_element(by=By.LINK_TEXT, value="免费注册").click()
        time.sleep(1)
        # 用户名可以包含字母、数字或下划线,须以字母开头,长度为5~16个字符
        driver.find_element(value="username").send_keys(reg_data["username"])
        # 请填写您常用的电子邮箱地址,邮箱可用来重置密码,接收订促销信息,订单状态等
        driver.find_element(value="email").send_keys(reg_data["email"])
        # 密码可包含字母、数字或特殊符号,长度为6~32个字符
        driver.find_element(value="password").send_keys(reg_data["password"])
        # 确认您所设置的密码
        driver.find_element(value="repassword").send_keys(reg_data["repassword"])
        # 输入验证码:先将验证码截图成png图片存储在变量中,再通过ddddocr图文识别插件将验证码转换为字符串存储到变量中
        captcha_img = driver.find_element(value="captcha-img").screenshot_as_png
        captcha = ddddocr.DdddOcr().classification(captcha_img)
        driver.find_element(value="captcha").send_keys(captcha)
        time.sleep(0.5)
        # 默认已勾选已阅读完并同意 "用户注册协议"复选框
        # driver.find_element(value="agree").click()
        # 点击立即注册链接
        driver.find_element(by=By.LINK_TEXT, value="立即注册").click()
        time.sleep(5)
        # 注册失败,用户名后侧提示“请设置用户名”或“用户名不符合格式要求”
        actual_value = driver.find_element(by=By.XPATH, value="//*[@id='register-form']/div/dl[2]/dd/span/font").text
        except_value = reg_data["except"]
        self.assertEqual(except_value, actual_value, "注册email反向测试用例失败")
        driver.quit()

    def tearDown(self) -> None:
        """重置测试环境"""
        pass


if __name__ == '__main__':
    unittest.main(verbosity=2)

?

????????3、参数化传递数据

????????paramunittest??# 参数化库,同时支持 unittest、Nose 和 pytest 单元测试框架

????????流程:

(1)导包(import paramunittest)

(2)在测试类前加@paramunittest.parametrized(

????????????????("value1", "value2"),? # 第一种数据:在元组中按对应参数位置放值

????????????????(("value1",), {"key2": "value2"}),? # 第二种数据:在嵌套元组中按对应参数位置放值并为字典传值留空,同时用字典指定某一键(和参数名一致)值

????????????????((), {"key1": "value1", "key2": "value2"}),? ?# 第三种数据:在嵌套元组中为字典传值留空,同时用字典指定所有键(和参数名一致)值

????????????????{"key1": "value1", "key2": "value2"})? # 第四种数据:直接用字典中的键(和参数名一致)值对传值

(3)重新声明测试用例名称(添加传递数据的参数key1、key2...)

????????注意:参数化数据中的key-value必须和参数key位置一一对应,参数化数据中的key必须和参数中的key一致

????????parameterized??# 参数化库,同时支持 unittest、Nose 和 pytest 单元测试框架

????????流程:

(1)导包(from parameterized import parameterized)

(2)在测试用例方法前加@parameterized.expand([("value1", "value2",...),...])

(3)重新声明测试用例名称(添加传递数据的参数key1、key2、...)

????????注意:参数化数据中的每一个元组中的value必须和参数key位置一一对应


????????愿你我都能为中华民族的伟大复兴尽一份绵薄力量,让中华文化的根扎根在中国这片绿水青山之上,让新一代中华儿女传承与发扬!!!

---无名之辈


以上内容均是本人自学,当然是有网上公布的内容,如有冒犯,请留言,立即改正,谢谢!


? ? ? ? 看完要是觉得对自己有用,动一下您那根金色的会一指禅的右手食指,按一下您的鼠标左键,在对应的那个位置点个赞,亦或者在评论区留下您的绝顶好句,亦或者收藏在您的收藏夹里,再走也不迟嘛!您说要不要得!谢谢您的阅读和赞赏!

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:24:11  更:2022-09-24 21:24:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 12:12:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码