天天看点

【转】自动化测试框架pytest中文文档:pytest入门基础

成熟全功能的python测试工具

支持posix / windows, python的2.5-3.3 , pypy和jython - 2.5.1

1000测试用例自测零bug。

pytest升级时有很好的向后兼容性

丰富的在线和pdf文档

大量的第三方插件和内置帮助

在许多小型和大型项目和组织使用

许多测试实例

灵活

易学,有多种用法

assert语句断言

追踪和失败断言报告

打印调试和测试执行期间可以捕获标准输出

适合简单的单元测试到复杂的功能测试

模块化和参数化的平台

参数化的测试函数

支持属性

skip和xfail处理失败的用例

xdist插件分发测试给多个cpu

不断地重新运行失败的测试

灵活的python测试发现

集成

多范式:可以执行nose, unittest 和doctest风格的测试用例,甚至django和trial。

支持良好的集成实践

支持扩展的xunit风格setup

支持非python测试

支持生成测试覆盖率报告

支持pep8兼容的编码风格

扩展插件和定制系统:

所有的收集,报告,运行方面都委派给hook函数

定制可以是每个目录,每个项目或每个pypi上发布的插件

很容易添加命令行选项或定制现有的行为

安装

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 pip install -u pytest # or 2 easy_install -u pytest</pre>

检查版本:

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # py.test --version 2 this is pytest version 2.5.2, imported from /usr/lib/python2.7/site-packages/pytest.pyc</pre>

第一个实例:

代码:

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # content of test_sample.py

2 def func(x): 3 return x + 1

4 def test_answer(): 5 assert func(3) == 5</pre>

执行结果:

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test

2 =========================================================================================================== test session starts ===========================================================================================================

3 platform linux2 -- python 2.7.3 -- py-1.4.20 -- pytest-2.5.2

4 collected 1 items 5

6 test_sample.py f

7

8 ================================================================================================================ failures =================================================================================================================

9 _______________________________________________________________________________________________________________ test_answer _______________________________________________________________________________________________________________ 10

11 def test_answer(): 12 > assert func(3) == 5

13 e assert 4 == 5

14 e + where 4 = func(3) 15

16 test_sample.py:8: assertionerror 17 ======================================================================================================== 1 failed in 0.34 seconds =========================================================================================================</pre>

pytest通过标准测试发现规则发现test_answer函数,通常是查找 test_前缀。我们得到了一个故障报告,因为我们调用func(3)没有返回5。pytest的高级內省断言会智能报告assert的中间值,不需要记住那些junit传统方法。

异常断言

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 import pytest 2 def f(): 3 raise systemexit(1) 4 def test_mytest(): 5 with pytest.raises(systemexit): 6 f()</pre>

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 $ py.test -q test_sysexit.py 2 . 3 1 passed in 0.01 seconds</pre>

-q表示静默模式:

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 -q, --quiet decrease verbosity.</pre>

在类中分组用例

代码

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # content of test_class.py

2 class testclass: 3 def test_one(self): 4 x = "this"

5 assert 'h' in x 6

7 def test_two(self): 8 x = "hello"

9 assert hasattr(x, 'check')</pre>

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test test_class.py

4 collected 2 items 5

6 test_class.py .f

9 ___________________________________________________________________________________________________________ testclass.test_two ____________________________________________________________________________________________________________ 10

11 self = <test_class.testclass instance at 0x265aef0>

12

13 def test_two(self): 14 x = "hello"

15 > assert hasattr(x, 'check') 16 e assert hasattr('hello', 'check') 17

18 test_class.py:12: assertionerror 19 =================================================================================================== 1 failed, 1 passed in 0.01 seconds ====================================================================================================</pre>

功能测试示例:生成唯一的临时目录

功能测试经常需要创建一些文件,并将其传递给应用程序对象。pytest提供 builtin fixtures/function 参数允许请求任意资源,例如唯一的临时目录:

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 def test_needsfiles(tmpdir): 2 print tmpdir 3 assert 0</pre>

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 ]# py.test -q test_tmpdir.py

2 ff

3 ================================================================================================================ failures =================================================================================================================

4 _____________________________________________________________________________________________________________ test_needsfiles _____________________________________________________________________________________________________________

5

6 tmpdir = local('/tmp/pytest-0/test_needsfiles0')

8 def test_needsfiles(tmpdir):

9 print tmpdir 10 > assert 0

11 e assert 0

13 test_tmpdir.py:7: assertionerror 14 ------------------------------------------------------------------------------------------------------------- captured stdout -------------------------------------------------------------------------------------------------------------

15 /tmp/pytest-0/test_needsfiles0 16 1 failed in 0.07 seconds</pre>

断言的前面的print内容也会打印出来,测试时可以多加print语句,保证异常时输出一些有用的信息。

下面方式可以查看内置的

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test --fixtures

2

3 =========================================================================================================== test session starts ===========================================================================================================

4 platform linux2 -- python 2.7.3 -- py-1.4.20 -- pytest-2.5.2

5 collected 5 items 6 capsys

7 enables capturing of writes to sys.stdout/sys.stderr and makes

8 captured output available via <code>capsys.readouterr()</code> method calls

9 which return a <code>(out, err)</code> tuple. 10

11 capfd 12 enables capturing of writes to file descriptors 1 and 2 and makes 13 captured output available via <code>capsys.readouterr()</code> method calls 14 which return a <code>(out, err)</code> tuple. 15

16 monkeypatch 17 the returned <code>monkeypatch</code> funcarg provides these 18 helper methods to modify objects, dictionaries or os.environ:: 19

20 monkeypatch.setattr(obj, name, value, raising=true) 21 monkeypatch.delattr(obj, name, raising=true) 22 monkeypatch.setitem(mapping, name, value) 23 monkeypatch.delitem(obj, name, raising=true) 24 monkeypatch.setenv(name, value, prepend=false) 25 monkeypatch.delenv(name, value, raising=true) 26 monkeypatch.syspath_prepend(path) 27 monkeypatch.chdir(path) 28

29 all modifications will be undone after the requesting 30 test function has finished. the <code>raising</code> 31 parameter determines if a keyerror or attributeerror 32 will be raised if the set/deletion operation has no target. 33

34 pytestconfig 35 the pytest config object with access to command line opts. 36 recwarn 37 return a warningsrecorder instance that provides these methods: 38

39 * <code>pop(category=none)</code>: return last warning matching the category. 40 * <code>clear()</code>: clear list of warnings 41

42 see http://docs.python.org/library/warnings.html for information

43 on warning categories. 44

45 tmpdir 46 return a temporary directory path object

47 which is unique to each test function invocation, 48 created as a sub directory of the base temporary 49 directory. the returned object is a <code>py.path.local</code>_ 50 path object. 51

52

53 ============================================================================================================ in 0.02 seconds =============================================================================================================&lt;/pre&gt;

python -m pytest调用:

python -m pytest [...] 效果和py.test [...] 一样

获取版本,选项名,环境变量

py.test --version 看版本

py.test --fixtures 查看内置参数

py.test -h | --help 命令行和配置文件帮助

失败后停止

首次失败后停止执行:py.test -x

py.test --maxfail=2 两次失败之后停止执行

执行选择用例

py.test test_mod.py,执行模块中的用例

py.test somepath,执行路径中用例

py.test -k stringexpr,执行字符串表达式中的用例,比如"myclass? and not method",选择testmyclass.test_something,排除了testmyclass.test_method_simple。

py.test --pyargs pkg,导入pkg,使用其文件系统位置来查找和执行用例。执行pypkg目录下的所有用例。

调试输出:

py.test --showlocals 在traceback中显示本地变量

py.test -l 在traceback中显示本地变量(快捷方式)

py.test --tb=long 默认的traceback信息格式化形式

py.test --tb=native 标准库格式化形式

py.test --tb=short 更短的格式

py.test --tb=line 每个错误一行

失败时调用pdb (python debugger):

python带有一个内置的python调试器称为pdb。pytest可以在命令行选项指定调用:

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test --pdb &lt;/pre&gt;

这将每次失败时调用python调试器。

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test -x --pdb # 失败时调用pdb,然后退出测试。

py.test --pdb - maxfail=3# 前3次失败调用pdb。 &lt;/pre&gt;

设置断点:

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"&gt;1 import pytest 2 def test_function(): 3 ... 4 pytest.set_trace() # invoke pdb debugger and tracing&lt;/pre&gt;

以前的版本中只有通过py.test-s禁用命令行捕捉才可以进入pdb调试。

profiling测试执行时间:得到最执行慢的10个测试:

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test --durations=10 &lt;/pre&gt;

创建junitxml格式的文件

创建hudson或其他持续集成服务器的结果文件:

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test --junitxml=path &lt;/pre&gt;

创建resultlog格式的文件

要创建纯文本的机器可读的结果文件,用于pypy-testweb展示等。

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test --resultlog=path &lt;/pre&gt;

发送测试报告给在线pastebin服务

bpaste可以为你的文本生成url连接,下面为创建每个测试失败创建一个url:

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test --pastebin=failed

py.test --pastebin=all

py.test --pastebin=failed -x &lt;/pre&gt;

目前只支持:py.test --pastebin=failed

禁用插件

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"&gt;py.test -p no:doctest &lt;/pre&gt;

在python代码中调用pytest

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"&gt;1 $ python myinvoke.py 2 ***

3 test run reporting finishing&lt;/pre&gt;

使用虚拟环境

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"&gt; 1 #virtualenv .

2 new python executable in ./bin/python

3 installing setuptools, pip...done.

4 root@autotest:[/data/code/python/pytest]#source bin/activate

5 (pytest)root@autotest:[/data/code/python/pytest]#pip install pytest 6 downloading/unpacking pytest

7 downloading pytest-2.5.2.tar.gz (608kb): 608kb downloaded

8 running setup.py (path:/data/code/python/pytest/build/pytest/setup.py) egg_info for package pytest 9

10 downloading/unpacking py&gt;=1.4.20 (from pytest) 11 downloading py-1.4.22.tar.gz (189kb): 189kb downloaded 12 running setup.py (path:/data/code/python/pytest/build/py/setup.py) egg_info for package py 13

14 installing collected packages: pytest, py 15 running setup.py install for pytest 16

17 installing py.test-2.7 script to /data/code/python/pytest/bin 18 installing py.test script to /data/code/python/pytest/bin 19 running setup.py install for py 20

21 successfully installed pytest py 22 cleaning up...&lt;/pre&gt;

测试布局和导入规则

测试布局的方法有2种。一为放置在应用代码之外,适用于有很多功能测试等情况。

&lt;pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"&gt;setup.py # your distutils/setuptools python package metadata

mypkg/ init.py

appmodule.py

tests/ test_app.py

...&lt;/pre&gt;

二为嵌入测试目录到应用,当(单元)测试和应用之间的有直接关系,并想一起发布时有用:

...

test/ test_app.py

http://automationtesting.sinaapp.com/blog/m_pytest_doc1

继续阅读