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

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

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

---谈论学习也不行?


退伍回来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:"""定义运算函数:实现加减乘除算法"""@staticmethoddef add(a, b):"""加法"""# 测试问题:若a是字符串,b是整型,应该是字符串拼接运算if isinstance(a, str) and isinstance(b, int):b = str(b)return a + belse:return a + b@staticmethoddef subtract(a, b):"""减法"""return a - b@staticmethoddef multiply(a, b):"""乘法"""return a * b@staticmethoddef divide(a, b):"""除法"""if b == 0:return "除数不能是0,小学生都知道的啊"else:return a / bif __name__ == '__main__':"""单元测试-代码功能验证"""mm = MyMath()# 实现第一条加法测试用例actual_value = mm.add(1, 1)expect_value = 2if actual_value == expect_value:print("加法功能实现正确")# 实现第二条加法测试用例:can only concatenate str (not "int") to strtry: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 MyMathclass MyMathUnittest(unittest.TestCase):"""继承单元测试框架的单元测试用例类"""# 注解:给方法指定特殊含义@classmethoddef setUpClass(cls) -> None:print("setUpClass方法")@classmethoddef 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 unittestfrom my_math import MyMathclass 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 unittestclass 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, 2self.assertIs(a, b)self.assertIs(a, c)def test_ais_not(self):"""断言方法assertIsNot---判判断身份(内存地址值)不相等"""a, b, c = 1, 1, 2self.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判断布尔值为TrueassertFalse(x)  # booI(x) is False判断布尔值为FalseassertIs(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)存储优化---文件名规范# 文件命名:路径+时间格式+ .htmlfilename = 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 MyMathclass MyMathUnittest(unittest.TestCase):"""继承单元测试框架的单元测试用例类"""# 注解:给方法指定特殊含义@classmethoddef setUpClass(cls) -> None:print("setUpClass方法")@classmethoddef 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, 2self.assertIs(a, b)self.assertIs(a, c)def test_ais_not(self):"""断言方法assertIsNot---判判断身份(内存地址值)不相等"""a, b, c = 1, 1, 2self.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 unittestdiscover = 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.

    # 文件命名:路径+时间格式+ .htmltime_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 unittestimport 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_pngcaptcha = 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").textexcept_value = reg_data["except"]self.assertEqual(except_value, actual_value, "注册username反向测试用例失败")driver.quit()def tearDown(self) -> None:"""重置测试环境"""passif __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 unittestimport 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_pngcaptcha = 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").textexcept_value = reg_data["except"]self.assertEqual(except_value, actual_value, "注册email反向测试用例失败")driver.quit()def tearDown(self) -> None:"""重置测试环境"""passif __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位置一一对应


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

---无名之辈


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


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

自学Python+Selenium自动化测试相关推荐

  1. Jenkins持续集成项目搭建与实践——基于Python Selenium自动化测试(自由风格)

    Jenkins简介 Jenkins是Java编写的非常流行的持续集成(CI)服务,起源于Hudson项目.所以Jenkins和Hudson功能相似. Jenkins支持各种版本的控制工具,如CVS.S ...

  2. python+selenium自动化测试-Windows环境搭建

    来自python+selenium自动化测试初学者的笔记,写的不对的地方大家多多指教哦 一.安装selenium 安装selenium需要先安装python环境,python环境在之前的python+ ...

  3. Python+Selenium自动化测试——126邮箱自动登录脚本(登录首页是二维码,切入账号密码输入框)

    Python+Selenium自动化测试--126邮箱自动登录脚本 版权声明:本文为博主原创文章,未经允许不得转载.https://blog.csdn.net/qiao_wan/article/det ...

  4. Python+Selenium自动化测试脚本(入门)

    前言 最近在学习Python+selenium自动化测试,计划把公司已有一套自动化测试框架(UIAutomation+C#)用Python+Selenium框架实现一遍.先拿了一个csdn的登录页面练 ...

  5. Python + Selenium 自动化测试《人生重开模拟器》

    原文 Python + Selenium 自动化测试<人生重开模拟器> 背景 最近有一款小游戏特别火,叫<人生重开模拟器>,这款游戏用黑色幽默的调侃形式,随机生成你的人生大事件 ...

  6. Python+selenium自动化测试环境搭建(详细)

    Python+selenium自动化测试环境搭建 环境版本: Python3.7+Selenium3.141+谷歌浏览器76.0/火狐浏览器 一.安装五大组件 1.安装python并配置环境变量   ...

  7. python写界面输入测试脚本,python+Selenium自动化测试——输入,点击操作

    这是我的第一个真正意思上的自动化脚本. 1.练习的测试用例为: 打开百度首页,搜索"胡歌",然后检索列表,有无"胡歌的新浪微博"这个链接 2.在写脚本之前,需要 ...

  8. python自动化框架2019_《一头扎进》系列之Python+Selenium自动化测试框架实战篇6 - 价值好几K的框架,呦!这个框架还真牛叉哦!!!...

    1. 简介 本文开始介绍如何通过unittest来管理和执行测试用例,这一篇主要是介绍unittest下addTest()方法来加载测试用例到测试套件中去.用addTest()方法来加载我们测试用例到 ...

  9. Python+selenium自动化测试——启动谷歌浏览器闪退问题 Traceback (most recent call last)

    后台报错:Traceback (most recent call last) 当我们使用Python+selenium调用谷歌浏览器出现闪退问题时,其实是谷歌的驱动和浏览器的版本不一致. from t ...

  10. Python+Selenium自动化测试详细教程

    前言 Python+Selenium 来实现的web端自动化, 以下演示会用到禅道.百度和自己编写的html. 一.准备工作 1.安装 安装Python 3 安装selenium库,命令:pip in ...

最新文章

  1. 山石网科发布智能下一代防火墙新版本 应对未知威胁
  2. 学会动态丨中国人工智能学会成功召开重大科学问题《智能生成机理》研讨会...
  3. 解决Red hat 5.4的中文问题
  4. css中em与px的介绍及换算方法
  5. AltiumDesigner17快捷键
  6. 手机pdf格式怎么弄_pdf怎么转html?pdf转html技能分享给你
  7. Java工具包工具类,java.util.concurrent 包下工具类的使用
  8. 限制只允许某个进程调用库
  9. 为什么以太网有最短帧长度的要求_线束工程师:车载以太网介绍
  10. GIGO1.1数据清洗利器,文献计量同义词合并
  11. 大年三十问候导师的后果...
  12. 统计学中相关数学符号、希腊字母的标准读法
  13. 安卓app开发工具_软件开发常用的几款app开发工具
  14. ​​​​​​​​​​​勾股数的规律
  15. 欧几里得gcd与拓展欧几里得exgcd
  16. 【微信公众号】7、SpringBoot整合WxJava新增临时、永久素材
  17. python库源码分析_python第三方库Faker源码解读
  18. 单细胞转录组实战01: CellRanger7定量
  19. wuc-tab标签点击不了_不干胶标签专属定制
  20. 信息安全密码技术--栅栏密码

热门文章

  1. Thinkpad部分软件相关服务进程的总结
  2. 关于Ajax原理与使用方式,收藏这一篇文章就够了!!
  3. 推荐系统(十六)多任务学习:腾讯PLE模型(Progressive Layered Extraction model)
  4. 批量自动打印PDF文件辅助工具BatchOutput PDF for Mac
  5. 微信小程序商品详情页面开发案例
  6. Mac系统安装consul
  7. 拼图游戏代码html5,翻译的HTML5拼图游戏(附源码)
  8. Office 2010 word无法创建工作文件 请检查临时环境变量
  9. 怎么成为抖音本地生活服务商家?需要哪些资质条件?
  10. python股票回测_Python量化投资框架:回测+模拟+实盘