unitTest理论
unitTest:
通过直接导入UnitTest包即可实现
主要用于管理测试用例和实现数据驱动
一、unittest单元测试框架和自动化测试框架的关系
单元测试:指的是针对我们程序的最小单元(方法)进行测试。
unittest它是自动化框架的重要组成部分之一。
Pom,是自动化框架的重要组成部分之一
ddt数据驱动,是自动化框架的重要组成部分之一
全局配置文件封装,是自动化框架的重要组成部分之一
selenium二次封装,是自动化框架的重要组成部分之一
日志监控,是自动化框架的重要组成部分之一
断言,邮件发送。。。。。。
二、单元测试框架对比
基于python语言:unittest和pytest
基于java语言:junit和estng
1、用例编写规则
unittest:提供了testcases测试用例、testsuits测试事件、testfixtures测试固件或夹具、testloader测试加载器、 testrunner测试运行器。必须遵守以下规则:
(1)测试文件必须先导入import unittest
(2)测试类必须继承unittest.TestCase
(3)测试方法必须以test开头
Pytest:它是python的第三方测试框架。基于unittest的扩展框架,必须遵守以下规则:
(1)测试文件名必须以test_开头或者_test结尾。
(2)测试类命令必须以Test开头
(3)测试方法必须test开头
2、用例的前置和后置
Unittest:
setUp/teatDown 在每个用例之前或之后运行一次。
打开浏览器,加载网页/关闭网页,关闭浏览器
setUpClass/tearDownClass 在每个类运行之前或之后运行一次
创建数据库连接,创建日志对象/关闭数据库连接,销毁日志对象
setUpModule/tearDownModule 在每个模块之前和之后执行一次
Pytest:(在类的里面属于方法,类的外面属于函数)
方法级:setup_mothod/teardown_mothod 在方法之前和之后
setup/teardown
函数级:setup_function/teardown_function 在函数之前和之后
类级:
setup_class/teardown_class 在类之前和之后
模块:
setup_module/teardown_module
还有,还可以在函数之前加@pytest.fixture()
3、断言
unittest:assertTrue、assertEqual、assertln
pytest:assert
4、报告
unittest:htmltestrunner
pytest:插件:pytest-HTML、allure
5、失败重跑
unittest:没有
pytest:pytest_runnfailures插件
6、数据驱动
Unittest:ddt
Pytest:@pytest.mark.parametrize装饰器
7、用例分类执行
unittest默认执行所有,也可以通过testsuite来执行部分用例,或者-k参数。
Pytest:@pytest.mark
三、unittest框架主要做了什么?
1、测试发现:从多个py文件中收集并且加载测试用例
3、测试判断:通过断言去判断结果是否正确
4、测试报告:统计测试进度,通过率,生成报告
四、unittest重要组件
1.TestCase
2.TestSuite
3.TestFixture
4.TestLoader
5.TestRunner
五、TestCase组件
新建项目;
模块(文件)命名:xxx_xxx 小写
类命名:XxxXxx 首字母大写
一、TestCase用法
1、使用命令行运行
集成Jenkins的时候使用,因为Jenkins只能执行命令行,所有的命令行的方式都叫做非GUI的方式。
扩展:postman,非GUI,newman
jmeter,jmeter的命令
unittests with arguments python -m unittest ecshop_login.EcshopLogin.test01_baili in C:\Users\mihxy\PycharmProjects\WebUI\20210929unittest
2、测试执行:将测试用例按照一定的顺序和条件去执行并且生成结果
可以在terminal中写命令执行
python -m unittest -v ecshop_login.EcshopLogin -K命令的含义:
python -m以二进制形式/脚本的形式运行一个模块
unittest -v (verbose)更详细的输出结果
ecshop_login.EcshopLogin模块名.类名.方法名
-k匹配模式:
01.通配符:-k *-baili
02.字符串:-l baili
2、使用unittest.main()方式以模块的方式去运行
在调试的时候使用这种方式运行
配置pycharm 的环境或者使用python模块名.py
可以在terminal中写命令执行
Python ecshop_login.py
二、读懂执行的结果
. 成功
F 失败
E 错误
S 跳过
三、用例执行顺序
按ASCII码的规则:【0-9 A-Z a-z】A=65 a=97
四、框架底层原理
module='__main__',测试用例所在的路径,_main_表示当前模块
defaultTest=None,待测用例的名称,默认是所有
argv=None,接收外部的参数
testRunner=None,测试运行器:testRunner
testLoader=loader.defaultTestLoader,指定使用默认的测试用例加载器
exit=True,是否在测试完成之后结束python程序
verbosity=1,类似于命令行-v,0,1,2:0 控制台没有. 1 控制台有. 2控制台显示详细信息
六、TestSuite组件
图有误:TextTestRunner()
1、只运行部分用例可以使用testsuite,通过测试套件的方式来执行测试
2、使用testsuite添加用例集的方式去运行用例
七、TestLoader组件、TestRunner组件
通过默认的加载器去发现一个目录下面所有以.py结尾的所有的用例
Alt+enter 导入包
需要导包
八、TestFixture组件
TestFixture包含:
setUp()初始化操作
testcase()相当于我们的函数
tearDown()释放资源的操作
一、TestFixture测试夹具或测试固件
import os
import unittest
from unittest import defaultTestLoader
def setUpModule():
print("模块级夹具开始")
def tearDownModule():
print("模块级夹具结束")
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls)->None:
print("setUpClass:在每个类之前执行一次,如:创建数据库,生成日志对象")
@classmethod
def tearDownClass(cls)->None:
print("setUpClass:在每个类之后执行一次,如:关闭数据库,销毁日志对象")
def setUp(self)->None:
print("setUp:在测试用例之前的准备工作,如:打开浏览器,加载网页")
def tearDown(self)->None:
print("tearDown:在测试用例之后的扫尾工作,如:关闭浏览器")
def test01_baili(self):
print("测试百炼")
def test02_lisi(self):
print("测试李四")
class Test2(unittest.TestCase):
def test_login(self):
print("测试登录")
if__name__=='__main__':
#print(os.getcwd())
suite=unittest.TestSuite()
testcases=unittest.defaultTestLoader.discover(start_dir=os.getcwd(),pattern='*.py')
suite.addTest(testcases)
#unittest.main(defaultTest='suite')
unittest.TextTestRunner().run(suite)
优化:夹具的二次封装
将公用的类和方法封装在一个.py文件中,后直接导入即可
模块夹具没有生效
二、自动化的架构是什么样的?
九、忽略测试用例
一、忽略测试用例
无条件忽略
有条件忽略
import unittest
class SkipTest(unittest.TestCase):
age=22
@unittest.skip("百炼已测试过,不需要再测试了")
def test01_baili(self):
print("测试百炼")
#为真忽略
@unittest.skipIf(18<=age<=25,"年龄在18-25之间忽略")
def test02_lisi(self):
print("测试李四")
#为假忽略
@unittest.skipUnless(age<18,"年龄大于等于18忽略")
def test02_zhangsan(self):
print("测试张三")
class Test2(unittest.TestCase):
def test_login(self):
print("测试登录")
忽略可直接作用于类
import unittest
@unittest.skip("此模块暂不测试")
class SkipTest(unittest.TestCase):
age=22
#@unittest.skip("百炼已测试过,不需要再测试了")
def test01_baili(self):
print("测试百炼")
#为真忽略
#@unittest.skipIf(18<=age<=25,"年龄在18-25之间忽略")
def test02_lisi(self):
print("测试李四")
#为假忽略
#@unittest.skipUnless(age<18,"年龄大于等于18忽略")
def test02_zhangsan(self):
print("测试张三")
class Test2(unittest.TestCase):
def test_login(self):
print("测试登录")
十、unitest单元框架中的断言
一、unitest单元框架中的断言
assertEqual(a,b) 断言a==b
assertNotEqual(a,b) 断言a!=b
assertTrue (a) 断言a为真
assertFalse(a) 断言a为假
assertIn(a,b) 断言a在b里面
assertNotin(a,b) 断言a不在b里面
实例:
#打开浏览器
driver=webdriver.Chrome()
#加载网页
driver.get('http://47.107.116.139/shopnc/admin/index.php?act=login&op=login')
#加入所有的cookie
driver.add_cookie({'name':'','value':''})
#加载登陆后的页面
driver.get('http://47.107.116.139/shopnc/admin/index.php')
time.sleep(5)----有时会报错,可以使用隐式等待
#断言
self.assertIn('admin/index.php',driver.current_url)
#功能右键复制copyxpath
#点击会员
driver.find_element_by_xpath('').click()
#点击会员管理编辑文本
driver.find_element_by_link_text("会员管理")
使用xpath,在iframe中可能会报错,需要添加ifame的名称
driver.switch_to.frame("")
注意事项:浏览器显示添加速度太快,如何去断言?
针对这种三秒睡眠的情况
手动去添加,f12
暂停成功后,可以看到添加成功(几个字)
复制他的xpath
self.assertEqual('新增会员成功',driver.find_element_by_xpath('***').text)
二、unittest断言应用
1、通过文件读取到测试数据read_file()方法,可以读取.txt,保存到list,通过@data(*read_file())函数解析数值,通过@unpack对数据进行二次拆包,拆完之后传递到方法中运行
2、使用file_data读取yaml文件,@file_data('test.yaml'),这样是不管yaml文件中有多少条数据,我们都可以通过file_data直接解析,不需要@unpack拆包
Python3导入pyyaml
十一、批量执行用例生成HTML格式的报告
下载HTMLTestRunner.py 放在python\lib下面
HTMLTestRunner 是 Python 标准库的 unittest 模块的一个扩展,它可以生成 HTML的 测试报告