自学Python+Selenium自动化测试

发布于:2022-12-15 ⋅ 阅读:(827) ⋅ 点赞:(0)

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

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

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

---谈论学习也不行?


        退伍回来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位置一一对应


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

---无名之辈


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


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


网站公告

今日签到

点亮在社区的每一天
去签到