Pytest使用知识点归纳——干货(自用)

一、常用参数详解

--help,查看帮助

--collect-only 展示将要执行的测试用例,而不执行。

-k 通过指定测试用例名称表达是来执行测试用例。

-m 用于执行被标记的测试用例。

-m ‘not 标签’

pytest -m p0
仅运行用@pytest.mark.p0 装饰器修饰的所有测试用例

如果要运行多个标识,可使用表达式

pytest -m “p1 or p2” #运行有p1标识或p2标识用例
pytest -m “p1 and p2” #运行有p1和p2标识的用例
pytest -m “not p1” #运行除了p1之外的标识的用例
pytest -m “p1 and not p2” #运行有p1和没有p2标识的用例

-x 出现失败测试用例就停止执行。

--maxfail=num 允许执行失败的次数。

-s 允许在测试时输出信息。

--lf 重新执行上一个测试失败的用例

--ff 重新执行全部用例,优先执行上一次失败的用例。

-v 输出更详细的信息

-q 简化输出信息

-l 失败的测试用例被堆栈追踪

--tb=style 用于决定不到到失败时暑促信息的显示方式(short,line,no)

--duration=N 统计测试阶段的执行时间

二、使用方法:

1、测试文件的命名格式:test_<something>.py 或者 <something>_test.py。

2、测试函数、测试类的方法命名:test_<something>。

3、测试类命名Test<Something>。

4、标记测试函数,使用@pytest.mark,例如: @pytest.mark.smoke,执行时是哦那个pytest -m marker_name,运行。可以接 and、or、not关键字。例如:pytest -m 'smoke and get' test.py

5、跳过测试。skip、skipif。如过在测试时希望看到跳过测试的原因可以使用 pytest -rs。

6、标记预期会失败的用力使用:@pytest.mark.xfail(task.__version__<'0.2.0', reason='not supported until version 0.2.0')

7、传递参数:@pytest.mark.parametrize(key_list_string,value_list)。例如:@pytest.mark.parametrize('task1,task2',[[1,2]]),支持id标识。例如:

task_to_try = ( Task('sleep', done=True),
                Task('wake', 'brian'),
                Task('breathe','BRIAN',True))

task_ids = [ 'Task({},{},{})'.format(t.summary, t.owner, t.done) for t in task_to_try]

@pytest.mark.parametrize('task', task_to_try, ids=task_ids)
def test_add(task):
    task_id = tasks.add(task)
    assert equivalent(...)

 还可以在参数旁定义一个id来做标识,语法是 pytest.param(<value>, id="something"),例如

@pytest.mark.parametrize('task',[pytest.param(Task('create', 'Michelle'), id='just summary')])

三、Fixture

@pytest.fixture()用于声明函数是一个fixture。fix可以完成任务,也可以返回数据给测试函数。

例如:

@pytest.fixture()
def some_data():
...

def test_some_data(some_data):

 fixture函数的搜索顺序是,先搜索当前模块,然后搜索conftest.py。conftest.py可以被pytest视作一个fixture仓库。

如果fixture函数包含yield,那么系统会在yield处停止后面的代码,执行测试函数,因此,可以将yield之前的代码是为配置setup过程,yield后面的代码是为teardown过程。无论测试发生里什么yield之后的代码都会被执行。

下面这种用法也可以:

@pytest.fixture()
def a_tuple():
    return (1, 'foo', None, {'bar':23})

def test_a_tuple(a_tuple):
    asssert a_tuple[3]['bar'] == 32

我们可以在测试中使用多个fixture函数。

@pytest.fixture()
def db_with_task1():
    ...

@pytest.fixture()
def db_with_task2(db_with_task1):
    ...

@pytest.fixture()
def db_with_task3(db_with_task1, db_with_task2):
    ...

def test_add_count(db_with_task3):

 fixture的作用范围:通过scope来指定,参数有:function(函数级别),class(测试类级别),module(模块级别),session(会话级别)。

@pytest.fixtuer(scope='function')

使用usefixtures可以指定fixture。

为常用fixture添加autouse选项。通过指定autouse=True选项使作用域内的测试函数都运行改fixture。

fixture传参,通过params参数,在函数中通过request.param调用。例如

@pytest.fixture(params=['tiny', 'mongo'])
def task_db_session(tmpdir, request):
    task.start_task_db(str(temp_dir), request.param)
    yield
    task.stop_task_db()

常用的内置Fixture

tmpdir和tmpdir_factory

a_file = tmpdir.join('something.txt') 
a_sub_dir = tmpdir.mkdir('anything')
another_file = a_dir.join('something_else.txt')

a_dir = tmpdir_factory.mktemp('mydir')
base_dir = tmpdir_factory.getbasetemp()
a_file = a_dir.join('something.txt')
a_sub_dir = a_dir.mkdir('anything')
another_file = a_sub_dir.join(something_else.txt)

pytestconfig:为测试添加配置选项可以通过pytest_addoption或者在顶层目录的conftest.py中完成。

通过pytest_addoption()添加选项:

# /pytestconfig/conftest.py

def pytest_addoption(parser):
    parser.addoption("--myopt", action="store_true", help="some boolean option")
    parser.addoption("--foo", action="sotre", default="bar", help="foo: bar or baz")

注意:pytestconfig 是一个内建fixture,可以被其他测试函数或者fixture使用。

def test_pytestconfig(pytestconfig):
    print('args :', pytestconfig.args)
    print('inifile :', pytestconfig.inifile)
    print('invocation_dir :', pytestconfig.invocation_dir)
    print('rootdir :', pytestconfig.rootdir)
    print('-k EXPRESSION :', pytestconfig.getoption('keyword'))
    print('-v, --verbose :', pytestconfig.getoption('verbose'))
    print('-q, --quiet :', pytestconfig.getoption('quiet'))
    print('-l, --showlocals :', pytestconfig.getoption('tbstyle'))

capsys:内置的capsys有两个功能:1、允许使用代码读取stdout和stderr;2、可以临时禁止抓取日志输出。例如:

# /ch4/cap/test_capsys.py

def greeting(name):
    print('Hi, {}'.format(name))

def test_greeting(capsys):
    greeting('Earthling')
    out,err = capsys.readouterr()
    assert out == 'Hi, earthling\n'
    assert err == ''

pytest通常会抓取测试用例及被测试代码的输出。仅当全部测试会话运行结束后,抓取到的输出才会随着失败用例显示出来。

-s 参数可以关闭这个功能,在测试仍在运行期间就把输出直接发送到stdout。

你可以使用capsys.disabled() 让输入绕过默认的输出捕获机制。

monkeypatch可以在运行期间对类或者模块进行动态修改。monkeypatch提供以下函数:

setattr(target, name, value=<notset>, raising=True):设置一个属性。

delattr(target, name=<notset>, raising=True):删除一个属性。

setitem(dic, name, value):设置字典中的一条记录。

delitem(dic, name, raising=True):删除字典中的一条记录。

setenv(name, value, preend=None):设置一个环境变量。

delenv(name, raising=True):删除一个环境变量

syspath_prepend(path):将路径path加入sys.path并放在最前面。sys.path是Python导入的系统路径类表。

chdir(path):改变当前工作目录。

raising参数用于指示pytest是否在记录不存在时抛出异常。setenv()函数里的prepend可以是一个字符,如果这样设置的话,那么环境变量的值就是value+prepend+<old value>

# ch4/monkey/cheese.py
_default_prefs={
    "slicing": ['manchego', 'sharp cheddar']
    "spreadable": ['Saint Andre', 'camebert']
    "salads": ['crumbled feta']
}



# ch4/monkey/test_cheese.py
def test_def_change_default(tmpdir,monkeypatch):
    fake_home_dir = tmpdir.mkdir('home')
    monkeypatch.setattr(cheese.os.path, 'expanduser', (lambda x:x.replace('~', str(fake_home_dir))))
    monkeypatch.setitem(cheese._default_prefs, 'slicing', ['provolone'])

doctest模块是Python标准库的一部分。你可以使用--doctest-modules标识搜寻doctest测试用例。

doctest_namespace能够使doctest中的测试用例在运行时识别某些用于pytest命名空间的字符标识。

"""
this moudles defines multiply(a, b) and divide(a, b).
>>> import unnecessary_math as um
Here's how you use multiply:
>>>um.multiply(4, 3)
12
>>>um.multiply('a', 3)
'aaa'
Here's how you use divide:
>>>um.divide(10, 5)
2.0



"""

def multiply(a, b):
"""
Returns a multiplied by b.
>>>um.multiply(4, 3)
12
"""

正常情况下pytest会把每个字符串里的代码看成是不同的测试用例。

recwarn用来检测代码产生的警告信息。

#/ch4/test_warning.py

import warnings
import pytest

def lame_function():
    warnings.warn("Please stop using this", DeprecationWarning)


def test_lame_function():
    lame_function()
    assert len(recwarn) == 1
    w = recwarn.pop()
    assert w.category == DeprecationWarning
    assert str(w.message) == 'Please stop using this'

四、配置文件

pytest.ini:pytest.ini的主配置文件,可以改变pytest的默认配置。

conftest.py:是本地插件库,其中hook函数和fixture将作用于该文件所在的目录以及所有的子目录。

__init__.py:每个测试子目录都包含该文件时,那么在多个测试目录中可以出现同名测试文件。

tox.ini:如果你使用tox工具会用到的配置文件。

#/ch6/pytest.ini
[pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
...more options...

    tox.ini

#/ch6/tox.ini
[pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
...more options...

    setup.cfg

#/ch6/setup.cfg
[tool:pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
...more options...

 pytest.ini文件的所有设置选项。

[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:

  markers (linelist):   markers for test functions
  empty_parameter_set_mark (string):
                        default marker for empty parametersets
  norecursedirs (args): directory patterns to avoid for recursion
  testpaths (args):     directories to search for tests when no files or
                        directories are given in the command line.
  usefixtures (args):   list of default fixtures to be used with this project
  python_files (args):  glob-style file patterns for Python test module
                        discovery
  python_classes (args):
                        prefixes or glob names for Python test class discovery
  python_functions (args):
                        prefixes or glob names for Python test function and
                        method discovery
  disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool):
                        disable string escape non-ascii characters, might cause
                        unwanted side effects(use at your own risk)
  console_output_style (string):
                        console output: "classic", or with additional progress
                        information ("progress" (percentage) | "count").
  xfail_strict (bool):  default for the strict parameter of xfail markers when
                        not given explicitly (default: False)
  junit_suite_name (string):
                        Test suite name for JUnit report
  junit_logging (string):
                        Write captured log messages to JUnit report: one of
                        no|system-out|system-err
  junit_log_passing_tests (bool):
                        Capture log information for passing tests to JUnit
                        report:
  junit_duration_report (string):
                        Duration time to report: one of total|call
  junit_family (string):
                        Emit XML for schema: one of legacy|xunit1|xunit2
  doctest_optionflags (args):
                        option flags for doctests
  doctest_encoding (string):
                        encoding used for doctest files
  cache_dir (string):   cache directory path.
  filterwarnings (linelist):
                        Each line specifies a pattern for
                        warnings.filterwarnings. Processed after -W and
                        --pythonwarnings.
  log_print (bool):     default value for --no-print-logs
  log_level (string):   default value for --log-level
  log_format (string):  default value for --log-format
  log_date_format (string):
                        default value for --log-date-format
  log_cli (bool):       enable log display during test run (also known as "live
                        logging").
  log_cli_level (string):
                        default value for --log-cli-level
  log_cli_format (string):
                        default value for --log-cli-format
  log_cli_date_format (string):
                        default value for --log-cli-date-format
  log_file (string):    default value for --log-file
  log_file_level (string):
                        default value for --log-file-level
  log_file_format (string):
                        default value for --log-file-format
  log_file_date_format (string):
                        default value for --log-file-date-format
  addopts (args):       extra command line options
  minversion (string):  minimally required pytest version

1、addopts用来配置常用设置。

[pytest]
addopts = -rsxX -l --tb -strict

--rsxX 表示pytest报告所有测试用例被跳过、预计失败、预计失败但实际通过的原因。

-l表示pytest报告所有失败测试的堆栈中的局部变量。 

--tb=short表示简化堆栈回溯信息,指保留文件和行数。

--strict选项表示禁止使用未在配置文件中注册的标记。

2、注册标记来防范拼写错误 --strict

[pytest]
markers = 
    smoke: Run the smoke test functions for tasks project
    get : Run the test functions that test tasks.get()

通过pytest --markers来查看注册过的标记。 

3、指定pytest的最低版本号。

minversion选项可以指定运行测试用例的pytest的最低版本。

[pytest]
minversion = 3.0

4、指定pytest忽略某些目录。使用norecurse简化pytest的搜索工作。

默认设置是.* build dist CVS _darcs {arch} 和 *.egg。因为有.*,所以将虚拟环境命名为.venv是一个好主意例如

[pytest]
norecursedirs = .* venv src *.egg dist build

5、指定测试目录testpaths。

testpaths是一系列相对于根目录的路径,用于指定测试用例的搜索范围。

[pytest]
testpaths = tests

 6、更改测试搜索规则。

pyhon_classes python_files python_functions

[pytest]
python_classes = *Test Test* *Suite
python_files = test_* *_test check_*
python_function = test_* check_*

 7、在所有的测试子目录下都有一个__init__.py文件,目的是可以在多个目录中使用同名的文件。

五、常用的工具

1、pdb

调试常用项

--tb=[auto/long/short/line/native/no]:指定堆栈回溯信息粒度。

-v/--verbose:显示所有测试用例的名字,测试通过情况。

-l/showlocals:显示错误堆栈中的局部变量。

-lf/--last-failed:只运行上次失败的测试。

-x/--exitfirst:当测试遇到错误时即停止。

--pdb:在错误出现时开启交互调试。

pdb查看错误时的常用命令:

p/print expr:输出expr值。

pp expr:美化输出expr值。

l/list:列出错误并显示错误之前和之后的5行代码。

l/list begin,end:列出错误,并通过行号指定需要显示的代码区域。

a/args:打印当前函数的参数列表。

u/up:移动到堆栈的上一层。

d/down:移动到堆栈的下一层。

q/quit:退出当前调试会话。

例如:

(Pdb) p new_task

(Pdb) p task_id

(Pdb) q

2、coverage.py判断测试覆盖了多少代码

pytest-cov插件,会自动引入coverage.py。

3、mock替换部分系统

4、tox测试多种配置

5、Jenkins集成测试

六、测试的目录结构

七、测试结果含义

XPASSED(.):测试通过

FAILED(F):测试失败

SKIPPED(s):测试未被执行。

xfail(x):预期测试失败,并且确实失败。

XPASS(X):预期失败,但实际通过运行。

ERROR(E):测试用例之外的代码触发了异常。

 


版权声明:本文为weixin_38278993原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。