pytest简介、编写规则、fixture

一、pytest简介

pytest 是 python 的第三方单元测试框架,比自带的 unittest 更简洁和高效,同时兼容 unittest 框架。

它还有如下优点:

1、简单灵活,容易上手,文档丰富;

2、支持参数化,可以细粒度地控制要测试的测试用例;

3、能够支持简单的单元测试和复杂的功能测试,还可以用来做 selenium/appnium等自动化测试、接口自动化测试(pytest+requests);

4、pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest- selenium(集成selenium)、pytest-html(完美html测试报告生成)、 pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等

5、测试用例的skip和xfail处理;

6、可以很好的和CI工具结合,例如jenkins。

pytest是python的一个第三方类库,可以直接使用pip install pytest 在线 安装,或者下载离线包安装。

 

二、pytest测试用例编写规则

1、测试文件以test_开头(以_test结尾也可以)

2、测试类以Test开头,并且不能带有 init 方法

3、测试函数以test_开头

4、断言必须使用 assert

举例:

import pytest

class TestDemo01:
    def testadd(self):
        assert 10+10 == 20

if __name__ == '__main__':
    pytest.main()
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collected 1 item

test_demo_01.py .                                                        [100%]

============================== 1 passed in 0.06s ===============================
test_demo_01.py 为文件名

三、pytest中的fixture

   fixture是pytest特有的功能,它用pytest.fixture标识,定义在函数前面。 fixture有明确的名字,在其他函数,模块,类或整个工程调用它时会被激活。 fixture是基于模块来执行的,每个fixture的名字就可以触发一

fixture的函数, 它自身也可以调用其他的fixture。

可以把fixture看做是资源,在你的测试用例执行之前需要去配置这些资源, 执行完后需要去释放资源。类似unittest中的setup和teardown功能。

 

四、fixture方法详解

fixture(callable_or_scope=None,*args,scope="function",params=None,aut ouse=False,ids=None,name=None)

 

scope: 作用范围,设置范围后,会根据设置的范围去触发执行。

范围可选值:

  • function:每个方法(函数)都会执行一次。(默认)
  • class:每个类都会执行一次。类中有多个方法调用,只在第一个方法调用时执行
  • module:一个 .py 文件执行一次。一个.py 文件可能包含多个类和方法。
  • package/session:多个文件调用一次,可以跨 .py 文件。

function举例:

import pytest

@pytest.fixture(scope='function')
def setUp():
    print('测试初始化')
    yield
    print('测试清理')

class TestDemo01:
    def testadd(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 20-10 == 10

if __name__ == '__main__':
    pytest.main(['-s'])
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collected 2 items

test_demo_02.py 测试初始化
test_demo_02 TestDemo01 testadd
.测试清理
测试初始化
test_demo_02 TestDemo01 testadd
.测试清理


============================== 2 passed in 0.05s ===============================

class举例:

import pytest

@pytest.fixture(scope='class')
def setUp():
    print('测试初始化')
    yield
    print('测试清理')

class TestDemo01:
    def testadd(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 20-10 == 10

class TestDemo02:
    def testadd(self,setUp):
        print('test_demo_02 TestDemo02 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_02 TestDemo02 testadd')
        assert 20-10 == 10

if __name__ == '__main__':
    pytest.main(['-s'])
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collected 4 items

test_demo_03.py 测试初始化
test_demo_02 TestDemo01 testadd
.test_demo_02 TestDemo01 testadd
.测试清理
测试初始化
test_demo_02 TestDemo02 testadd
.test_demo_02 TestDemo02 testadd
.测试清理


============================== 4 passed in 0.06s ===============================

Process finished with exit code 0

module举例:

import pytest

@pytest.fixture(scope='module')
def setUp():
    print('测试初始化')
    yield
    print('测试清理')

class TestDemo01:
    def testadd(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_02 TestDemo01 testadd')
        assert 20-10 == 10

class TestDemo02:
    def testadd(self,setUp):
        print('test_demo_02 TestDemo02 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_02 TestDemo02 testadd')
        assert 20-10 == 10

if __name__ == '__main__':
    pytest.main(['-s'])
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collected 4 items

test_demo_03.py 测试初始化
test_demo_02 TestDemo01 testadd
.test_demo_02 TestDemo01 testadd
.test_demo_02 TestDemo02 testadd
.test_demo_02 TestDemo02 testadd
.测试清理


============================== 4 passed in 0.06s ===============================

package/session举例:

文件一:test_demo_03.py
import pytest

@pytest.fixture(scope='session')
def setUp():
    print('测试初始化')
    yield
    print('测试清理')

class TestDemo01:
    def testadd(self,setUp):
        print('test_demo_03 TestDemo01 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_03 TestDemo01 testadd')
        assert 20-10 == 10

class TestDemo02:
    def testadd(self,setUp):
        print('test_demo_03 TestDemo02 testadd')
        assert 10+10 == 20

    def testsub(self,setUp):
        print('test_demo_03 TestDemo02 testadd')
        assert 20-10 == 10

if __name__ == '__main__':
    pytest.main(['-s'])
文件二:test_demo_04.py
import pytest

class TestDemo01:
    def testadd(self):
        print('test_demo_04 TestDemo01 testadd')
        assert 10+10 == 20

    def testsub(self):
        print('test_demo_04 TestDemo01 testadd')
        assert 20-10 == 10

class TestDemo02:
    def testadd(self):
        print('test_demo_04 TestDemo02 testadd')
        assert 10+10 == 20

    def testsub(self):
        print('test_demo_04 TestDemo02 testadd')
        assert 20-10 == 10

if __name__ == '__main__':
    pytest.main(['-s'])

运行test_demo_03.py或test_demo_04.py

============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collected 8 items

test_demo_03.py 测试初始化
test_demo_03 TestDemo01 testadd
.test_demo_03 TestDemo01 testadd
.test_demo_03 TestDemo02 testadd
.test_demo_03 TestDemo02 testadd
.
test_demo_04.py test_demo_04 TestDemo01 testadd
.test_demo_04 TestDemo01 testadd
.test_demo_04 TestDemo02 testadd
.test_demo_04 TestDemo02 testadd
.测试清理


============================== 8 passed in 0.06s ===============================

name:fixture的名称,默认为装饰函数的名称

autouse:在一个session内所有的test都会自动调用当前的fixture,默认为false

ids:测试字符串id的列表,每个测试字符串id对应于params,默认为参数值

params:传入参数,接收一个列表,列表中每个数据都作为用例的输入

举例(autouser=True,则不需要显示调用,例如函数test01()):

import pytest

p = [100,200]
@pytest.fixture(params=p,autouse=True,ids=['01','02'],name='paramss')
def setUp(request):
return request.param

class TestDemo01:
def testadd(self,paramss):
print(paramss)
assert 10+10 < paramss

def testsub(self,paramss):
print(paramss)
assert 20-10 < paramss

def test01(self):
print('test_autouse')


if __name__ == '__main__':
pytest.main(['-v','-s'])
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
rootdir: /appium_test/pytest
plugins: Faker-4.1.1, celery-4.2.0
collecting ... collected 4 items

test_demo_05.py::TestDemo01::testadd[01] 100
PASSED
test_demo_05.py::TestDemo01::testadd[02] 200
PASSED
test_demo_05.py::TestDemo01::testsub[01] 100
PASSED
test_demo_05.py::TestDemo01::testsub[02] 200
PASSED

============================== 4 passed in 0.06s ===============================

Process finished with exit code 0

 

 

 

 

 

posted @ 2020-08-13 15:31  陈娟  阅读(390)  评论(0)    收藏  举报