单元测试是指在软件开发当中,针对软件的最小单位(函数方法)进行正确性的检查测试。
java:junit和testng
python:unittest和pytest
(1)测试发现:从多个文件里边去找我们的测试用例
(2)测试执行:按照一定的顺序和规则去执行,并生成结果
(3)测试判断:通过断言判断预期结果和实际结果的差距
(4)测试报告:统计测试进度,耗时,通过率,生成测试报告。
1.提高测试效率,降低维护成本。
2.减少人工干预,提高测试的准确性,增加代码的重用性。
3.核心思想是让不懂代码的人也能过通过这个框架去实现自动化测试。
单元测试框架:只是自动化测试框架种的组成部分之一。
pom设计模式:只是自动化测试框架种的组成部分之一。
数据驱动、关键字驱动、全局配置文件封装、日志监控、selenium,requests二次封装、断言、报告、邮件。。。
1.pytest是一个非常成熟的python的单元框架,比unittest更灵活,容易上手。
2.pytest可以和selenium,requests,appium结合实现web自动化,接口自动化,app自动化。
3.pytest可以实现测试用例的跳过以及reruns失败用例重试。
4.pytest可以和allure生成非常美观的测试报告。
5.oytets可以和jenkins持续集成。
6.pytest有很多非常强大的插件,并且这些插件可以实现很多使用的操作。
(1)pytest
(2)pytest-html 生成html格式的自动化测试报告
(3)pytest-xdist 测试用例分布式执行,多cpu分发
(4)pytest-ordering 用于改变测试用例的执行顺序
(5)pytest-rerunfailures 用力失败后重跑
(6)allure-pytest 用于生成美观的测试报告
以上几个插件可以维护到requirements.txt种,通过pip install -r requirements.txt安装插件
1.模块名必须以test_开头或者_test结尾
2.测试类必须以Test开头,并且不能以init方法
3.测试方法必须要以test开头
(1)运行所有:pytest.main()
(2)指定模块:pytest.main(["test_login.py"]) "test_login.py"为文件的路径
(3)指定目录:pytest.main(["目录路径"])
(4)通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组成
pytest.main(["./testcase/test_web.py::TestLogin::test_001"])
(1)运行所有:pytest
(2)指定模块:pytest test_login.py"
(3)指定目录:pytest 目录路径
(4)pytets ./testcase/test_web.py::TestLogin::test_001
pytest.ini:是pytest单元测试框架的核心配置文件
位置:一般放在项目的根目录。
编码:必须是ANSI,可以使用notepad++修改编码格式
作用:改变pytest的默认行为
运行的规则:不管是主函数运行模式还是命令行运行模式,都会去读这个配置文件。
文件的内容:(实际运行时最好把中文注释给去掉)
[pytest]
addopts = -vs -m 'smoke or huigui' --html ./report/report.html #添加的命令符
testpaths = ./test_ #执测试用例的路径
python_files = test_*.py #执行的文件命名规则
python_classes = Test* #执行的class类命名规则,前边都有Test
python_functions = test #执行的类的方法命名规则
markers =
smoke:冒烟
huigui:回归 #分类管理,此处维护了可以在用例上打标签
参数详解:
-s:表示输出调试信息,包括print打印的信息
-v:表示显示更详细的信息
-vs:两个蚕食可以一起使用
-n:支持多线程或者分布式运行测试用例。如pytest.main(["-n=2"]),表示两个线程运行
--reruns NUM :失败用例重跑,NUM为重跑的次数,一个用力失败了,一共运行NUM+1次
-x:表示只要一个用例报错,那么测试就会停止。
--maxfail=2 出现两个用例失败就停止
-k:根据测试用例的部分字符串去运行测试用例 pytest.main(["-k="aaa""])
--html ./report/report.html:生成测试报告
--lf:只重新运行上次运行失败的用例
--ff:先执行上次失败的测试后,在执行上次正常的测试用例。
1.unittest:根据ascII的大小来决定执行的顺序
2.pytest:从上到下依次运行
pytest可以通过给用例添加修饰器来改变默认的顺序
@pytest.mark.run(order=1)
import pytest
class Test1:
def test_001(self):
print("用例1")
@pytest.mark.run(order=1) #执行顺序改为1
def test_002(self):
print("用例2")
def test_003(self):
print("用例3")
if __name__ == '__main__':
pytest.main()
执行结果:
smoke冒烟测试用例分布在各个模块里面,在进行冒烟测试的时候我们需要将这些用例从各个模块中挑选出来,用@pytest.mark.smoke 其中smoke为用户自定义的,写成什么都可以,能表明语义即可。
1.pytest.ini种 写好运行命令以及配置好分类的标签,在addopts中 用-m 来表示需要执行的标记用例,多个用例之间用or连接
2. 测试用例打标记
import pytest
class Test1:
def test_001(self):
print("用例1")
@pytest.mark.huigui
def test_002(self):
print("用例2")
@pytest.mark.smoke
def test_003(self):
print("用例3")
3.在Terminal中输入pytest执行命令
4.执行结果:只执行了打smoke和huigui标记的用例
@pytest.mark.skip(reason="跳过原因")
@pytest.mark.skipif(条件判断语句,reason="跳过原因")
代码片段:
import pytest
class Test1:
age =19
@pytest.mark.skipif(age>18,reason="已经成年")
def test_001(self):
print("用例1")
@pytest.mark.skip(reason="无条件跳过")
def test_002(self):
print("用例2")
def test_003(self):
print("用例3")
运行结果:
跟unittest不同setup跟teardown全都是小写
import pytest
class Test1:
def setup(self):
print("每个用例前执行一次")
def teardown(self):
print("每个用例后执行一次")
def setup_class(self):
print("每个类前执行一次")
def teardown_class(self):
print("每个类后执行一次")
def test_001(self):
print("用例1")
def test_002(self):
print("用例2")
def test_003(self):
print("用例3")
执行结果:
@pytest.fixture(scope='',params='',autouse='',ids='',name='')
其中:
scope表示的是被@pytest.fixture标记的方法的作用域,function(默认),class,module,package/session
params:参数化,支持列表[],元组(),字典列表[{},{}],字典元组({},{})
autouse=True:自动执行,默认是False
ids:当使用params参数化时,给每一个值设置一个变量名,意义不大
name:给被@pytest.fixture标记的方法取一个别名
import pytest
class Test1:
@pytest.fixture(scope="function")
def my_fixture(self): #用 @pytest.fixture()修饰my_fixture
print("这里是前置")
yield #以yield为分界线,前边属于前置内容,后边属于后置内容
print("这里是后置")
def test_001(self,my_fixture): #用例方法引用my_fixture实现test_001的前后置
print("用例1")
def test_002(self):
print("用例2")
运行结果:
作用域为class:
import pytest
class Test1:
@pytest.fixture(scope="class",autouse=True) #scope="class"设置为类的前后置,autouse=True自动执行
def my_fixture(self): #用 @pytest.fixture()修饰my_fixture
print("这里是前置")
yield #以yield为分界线,前边属于前置内容,后边属于后置内容
print("这里是后置")
def test_001(self):
print("用例1")
def test_002(self):
print("用例2")
运行结果:
参数化:
@pytest.mark.parameterize()方式的参数化,请参考文档Python测试框架pytest(17)参数化parametrize_wangmcn的博客-CSDN博客_python中的parametrize
通过conftest.py和pytest.fixture()结合使用实现全局的前置应用 ,比如项目的全局登录,模块的全局处理
conftest.py文件是一个单独存放的一个夹具配置文件,文件名不能修改 ,放在用例的同层级下
可以在不同的py文件里面使用同一个前后置 fixture
conftest.py需要和运行中的用例放到同一层,并且不需要做任何的import导入的操作
执行效果”
总结:
setup/teardown,setup_class/teardown_class他是作用于所有用例或者所有类
@pytest.fixture()它的作用是既可以部分也可以全部前后置
conftest.py和@pytest.fixture()结合使用,作用域全局的前后置
assert 1==2,msg
总结:
先通过 pytest --alluredir ./temp 生成json格式的临时报告。
run.py主程序运行以下代码:
import os import pytest if __name__ == '__main__': pytest.main() os.system("allure generate ./temp -o ./report --clean")
生成待时间戳的html文件
import time
import pytest
if __name__ == '__main__':
current_time = str(int(time.time()))
print(current_time)
pytest.main(["--html=./report/report{}.html".format(current_time),"--self-contained-html"])