执行

 

1.在控制台执行 pytest

2.在控制台指定执行范围
a.指定某个模块 pytest test_module.py
b.指定某个目录及其子目录的所有测试文件 pytest testcase
c.指定某个某块的某个方法 pytest test_module::test_function
d.指定执行某模块的某个类中的某个用例 用“::”分割 pytesy test_model.py::test_class::test_method
更多指定范执行范围样例,请参考官网

3.通过python代码执行pytest
1.直接执行pytest.main() 【自动查找当前目录下,以test_开头的文件或者以_test结尾的py文件】
2.设置pytest的执行参数 pytest.main(['--html=./report.html','test_login.py'])【执行test_login.py文件,并生成html格式的报告】
方式2中,执行参数和插件参数,通过[]进行分割,[]内的多个参数通过‘逗号,’进行分割

Pytest 查找测试策略

默认情况下,pytest 会递归查找当前目录下所有以 test 开始或结尾的 Python 脚本,并执行文件内的所有以 test 开始或结束的函数和方法。

mark 标记执行

# test_with_mark.py

@pytest.mark.finished
def test_func1():
    assert 1 == 1

@pytest.mark.unfinished
def test_func2():
    assert 1 != 1

cmd:
 pytest -m finished tests/test-function/test_with_mark.py

skip 需要跳过执行的case: 

@pytest.mark.skip(reason='out-of-date api')
def test_connect():
    pass

@pytest.mark.skip() #1、跳过方法或用例,未备注原因

@pytest.mark.skip(reason='跳过一个方法或一个测试用例') #2、跳过方法或用例,备注了原因

@pytest.mark.skipif(1==1,reason='跳过一个方法或一个测试用例')   #3、当条件满足,跳过方法或用例,备注了原因
 

参数化

在 pytest 中,我们有更好的解决方法,就是参数化测试,即每组参数都独立执行一次测试。使用的工具就是 pytest.mark.parametrize(argnames, argvalues)

单参数

@pytest.mark.parametrize('passwd',
                      ['123456',
                       'abcdefdfs',
                       'as52345fasdf4'])
def test_passwd_length(passwd):
    assert len(passwd) >= 8

多参数

@pytest.mark.parametrize('user, passwd',
                         [('jack', 'abcdefgh'),
                          ('tom', 'a123456a')])
def test_passwd_md5(user, passwd):
    db = {
        'jack': 'e8dc4081b13434b45189a720b77b6818',
        'tom': '1702a132e769a623c1adb78353fc9503'
    }

    import hashlib

    assert hashlib.md5(passwd.encode()).hexdigest() == db[user]

注意:

1.parametrize中字符串指定参数名必须与testcase中指定参数名一致(user,passwd)

2.parametrize中实际参数以 列表形式,多个参数则列表每项为元组

测试类的参数化

固件(fixture)

@pytest.fixture()
def postcode():
    return '010'


def test_postcode(postcode):
    assert postcode == '010'

 yield:预处理和后处理

Pytest 使用 yield 关键词将固件分为两部分,yield 之前的代码属于预处理,会在测试前执行;yield 之后的代码属于后处理,将在测试完成后执行。

@pytest.fixture()
def db():
    print('Connection successful')

    yield

    print('Connection closed')


def search_user(user_id):
    d = {
        '001': 'xiaoming'
    }
    return d[user_id]


def test_search(db):
    assert search_user('001') == 'xiaoming'


@pytest.fixture()
def my_fix():
    print(123)

    yield 1234   #调用固件时返回值

    print(432)

def test_my(my_fix):
    print(my_fix)

固件作用域

在定义固件时,通过 scope 参数声明作用域,可选项有:

function: 函数级,每个测试函数都会执行一次固件;
class: 类级别,每个测试类执行一次,所有方法都可以使用;
module: 模块级,每个模块执行一次,模块内函数和方法都可使用;
package,表示 fixture 函数在测试包(文件夹)中第一个测试用例执行前和最后一个测试用例执行后执行一次。
session: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。

固件自动执行

目前为止,所有固件的使用都是手动指定,或者作为参数,或者使用 usefixtures

如果我们想让固件自动执行,可以在定义时指定 autouse 参数。

@pytest.fixture(scope='session', autouse=True)

固件参数化

与函数参数化使用 @pytest.mark.parametrize 不同,固件在定义时使用 params 参数进行参数化。

固件参数化依赖于内置固件 request 及其属性 param

conftest

  • pytest会默认读取conftest.py
  • conftest.py 文件名称是固定的,不能改动
  • conftest.py只对同一个package下的所有测试用例生效
  • 不同目录可以有自己的conftest.py,一个项目中可以有多个conftest.py
  • 测试用例文件中不需要手动import conftest.py,pytest会自动查找
  • conftest.py文件所在目录必须存在__init__.py文件