您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  要资料 文章 文库 Lib 视频 Code iProcess 课程 认证 咨询 工具 火云堂 讲座吧   成长之路  
会员   
 
   
 
  
每天15篇文章
不仅获得谋生技能
更可以追随信仰
 
     
   
 订阅
  捐助
Python测试模块学习笔记
 
来源:csdn 发布于:2017-10-16
836 次浏览     评价:      
 

关于unittest模块

unittest是python发行版里面自带的一个模块,使用起来非常简单,为了能够更好的理解和使用unittest模块,必须了解一下一些基本的概念。

unittest模块是用来进行单元测试的一个模块。

关于该模块,有几个类必须理解。

TestCase类:该类是封装了一个测试用例,即每个测试用例对应于一个TestCase类。

TestSuite类:该类是一个测试集,即把相关的TestCase类集合到一起形成一个TestSuite

TestLoader类:该类负责搜索和装载TestCase到TestSuite中。

TextTestRunner类:该类负责运行测试用例。

TextTestResult类:该类负责存储测试用例的执行结果。

最后所有的以上类都集成在了unittest.main()模块中了。

理解了这些基本概念之后,来看一个很简单的例子(官方文档中的例子)

import unittest

class TestStringMethods(unittest.TestCase):

def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')

def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())

def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
s.split(2)

if __name__ == '__main__':
unittest.main()

上述这个例子很明确的告诉了我们unittest的使用方法。unittest中的测试函数必须作为某一个类的成员函数并通常以“test_”前缀开头,该类必须是TestCase的子类,之后执行unittest.main()函数,该模块就会自动封装每一个以“test_”前缀开头 的例子到一个TestCase类中,然后把所有的TestCase都装载到TestSuite中并由TextTestRunner负责执行。运行一下可以看到如下结果:

unittest模块还提供了一些命令行应用的简单命令,列举一些常用的如下:

测试特定模块:

python -m unittest Testmodule_name

测试特定模块中的某个类:

python -m unittest Testmodule_name.TestClass

测试特定模块某个类中的某个方法:

python -m unittest Testmodule_name.TestClass.TestMethod

列举可用的命令行选项:

python -m unittest -h

测试该模块,并显示执行了的测试方法:

python -m unittest -v Testmodule_name

测试当前目录下的所有测试用例:

python -m unittest

最后一个要提的就是unittest的skip和expectedFailure属性。可以看几个小例子。

跳过该测试函数,并且显示”demonstrating skipping”的提示

@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")

在满足特定的条件下跳过该测试用例:

@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Tests that work for only a certain version of the library.
pass

该测试用例标记为失败的,在计算测试不通过的测试用例的时候不用考虑:

@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")

关于unittest更详细的介绍可以参考

unittest参考文档

关于pytest模块

pytest是python常用的一个测试框架, 可以帮助我们完成从单元测试到复杂的功能测试等一系列功能,同时pytest和其他的测试工具和测试方法的集成的很好,非常容易安装和使用插件。总之,pytest是一款不错的测试工具,下面就来学习怎么使用它。

pytest不是python标准发行包里面的一个模块,所以使用前需要进行一下安装操作,安装的方法也非常简单,只需要执行如下命令:

pip -install -U pytest

或者

easy_install -U pytest

如果不太了解pip和easy_install 可以参考其他资料。

安装完成之后可以用如下的命令检测是否安装成功:

py.test --version

看到如下结果表明安装成功:

在安装结束之后就来看下如何是使用。

pytest的基本使用思想和unittest模块差不多,先来看一个简单的小例子:

#test_sample.py
def func(x):
return x + 1

def test_answer():
assert func(3) == 5

然后终端进入到test_sample.py 所在目录下运行如下命令:

py.test test_sample.py

结果如下所示:

看一下上面的例子,写了一个函数,并写了一个简单的测试用例,用例中只有一条断言语句,相比于unittest模块,该程序有了如下的简化,即测试方法不需要封装在一个TestCase的子类中(当然如果测试用例庞大,封装到不同的类中还是很有必要),同时也不必要导入任何模块,即可完成一个简单的测试。

pytest同unittest类似,也提供了许多命令行使用的接口

测试某个模块:

py.test testfile_name

测试某个模块,并在首次错误用例出现后停止测试:

py.test -x testfile_name

测试某个模块,在出现n个错误后停止:

py.test –maxfail testfile_name

等等还有很多命令具体可以参考官方文档

pytest官方文档

下面来说下pytest的一些比较有用的特性。

首先是pytest中的断言机制。

使用起来非常简单,就同上述例子一样直接一个assert语句就可以完成。

如果要断言会出现某个异常可以使用如下的方式:

import pytest

def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0

这样在出现该异常的时候这个测试用例也不会标记为失败。

也可以自定义异常的提示信息,看一个下面的例子

# content of conftest.py
from test_foocompare import Foo
def pytest_assertrepr_compare(op, left, right):
if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
return ['Comparing Foo instances:',
' vals: %s != %s' % (left.val, right.val)]

# content of test_foocompare.py
class Foo:
def __init__(self, val):
self.val = val

def test_compare():
f1 = Foo(1)
f2 = Foo(2)
assert f1 == f2

然后终端运行:

py.test -q test_foocompare.py

结果如下所示:

可以看出要自定义异常信息,只需要在conftest.py 里面定义一个名为pytest_assertrepr_compare的函数即可。

然后不得不看的一个特性就是fixture特性。

这是官方文档中对fixture特性的一个介绍

Test functions can receive fixture objects by naming them as an input argument. For each argument name, a fixture function with that name provides the fixture object.

来看一个例子:

# content of ./test_smtpsimple.py
import pytest

@pytest.fixture
def smtp():
import smtplib
return smtplib.SMTP("merlinux.eu")

def test_ehlo(smtp):
response, msg = smtp.ehlo()
assert response == 250
assert 0 # for demo purposes

然后终端里运行:

py.test test_smtpsimple.py

可以看到如下结果:

上述例子的执行过程是这样子,pytest 首先寻找test_ 前缀开头的函数,找到test_ehlo()函数,然后发现该函数需要一个名为smtp的参数,就会去寻找有@pytest.fixture标记的名称为smtp的函数,并构造一个fixture object传递给该测试函数,之后执行测试函数。

函数参数化是一种依赖注入的思想。

了解了fixture是如何使用的之后,我们来看一下fixture的一些详细的介绍。

由于构造一个fixture object是非常耗费时间的,所以通常一个fixture object对象会被许多函数所共享。pytest提供了声明在不同级别共享的方法

每个函数一个fixture object::

@pytest.fixture(scope = "function")

每个模块一个fixture object

@pytest.fixture(scope = "module")

所有模块都共享一个fixture object

@pytest.fixture(scope = "session")

在fixture object对象使用完以后会有一个destroy 过程,如果想要在destroy过程中进行一些特殊的操作,可以给fixture 函数增加一个request对象,然后定义一个包含你想要执行的操作的函数,调用request的addfinalizer(funct_name)方法来把该函数注册到这个fixture object中。

可以看一个示例:

@pytest.fixture(scope="module")
def smtp(request):
smtp = smtplib.SMTP("merlinux.eu")
def fin():
print ("teardown smtp")
smtp.close()
request.addfinalizer(fin)
return smtp # provide the fixture value

然后就像之前所说的那样执行测试命令就可以了。

fixture 还可以进行参数化,可以给fixture函数一个“param = []” 的关键字参数,之后对于param中的每个值都会构造一个fixture object传递给测试函数使用。

可以看下如下的代码:

# content of conftest.py
import pytest
import smtplib

@pytest.fixture(scope="module",
params=["merlinux.eu", "mail.python.org"])
def smtp(request):
smtp = smtplib.SMTP(request.param)
def fin():
print ("finalizing %s" % smtp)
smtp.close()
request.addfinalizer(fin)
return smtp

对于每个需要使用到smtp这个fixture的测试函数,都会接收两个fixture object对象,一个使用的是“merlinux.edu” 参数,另一个使用的是”mail.python.org”参数。

使用如下命令可以看到自动生成的每个fixture object的id:

py.test --collect-only

也可以增加一个ids 的参数来自定义每个fixture object的id如下代码所示:

import pytest

@pytest.fixture(params=[0, 1], ids=["spam", "ham"])
def a(request):
return request.param

注意0 这个参数所构造的fixture object对象所对一的id为 “spam”, 1对应为“ham”

在一个fixture函数中可以调用其他的fixture函数,只要该被使用的fixture的域范围比使用该fixture的域范围大即可。

在fixture的使用过程中,pytest会自动决定每个测试函数的调用顺序,使得内存中存在最少的fixture object,以减少对系统资源的占用。

在使用fixture object的时候也可以主动告诉pytest(可以减少查找的开销)要调用某个fixture ,方式如下:

@pytest.mark.usefixtures(fixture_name1, fixture_name2, ...)

如果要告诉pytest要在这个模块都使用某个fixture,可以给这个模块定义一个如下的属性:

pytestmark = pytest.mark.usefixtures(fixture_name1, fixture_name2, ...)

如果要在告诉pytest在整个测试工程中都要使用某个fixture 可以新建一个如下的文件:

# content of pytest.ini

[pytest]
usefixtures = cleandir

fixture可以被覆盖,有许多级别的覆盖。

在介绍完fixture特性之后再来看两个特性,skip和xfail属性。

在满足特定的条件下跳过该测试函数,只需要在这个测试函数前使用如下命令

@pytest.mark.skipif(sys.version_info > (3,3), reason = "requ....")

展示详细的测试信息可以使用 -rs选项:

py.test -rs test_module

这些mark也可以共享,要在模块间共享一个mark可以定义一个如下变量:

minversion = pytest.mark.skipif(mymodule.__versioninfo__ < (1,1), reason="at least mymodule-1.1 required")

然后在测试的函数前加上@minversion 即可

对于一个大的测试项目,通常把marker放在一个单独的mark文件中

要在满足条件的情况下跳过一整个测试类,可以在该测试类前添加如下语句:

@pytest.mark.skipif(sys.platform == "win32", reason = "requires windows")

也可以为这个类定义一个pytestmark 属性如下:

pytestmark = pytest.mark.skipif(sys.platform== 'win32', reason = "requires windows")

如果在一个模块中定义这个全局的属性,pytestmark 可以在满足条件的情况下跳过该测试模块

下面是xfail属性的介绍

xfail属性是用来表明一个测试用例预计是会失败的,在测试的时候会跳过该用例,在计算不通过的用例的时候不用考虑。

使用xfail属性,只需要在测试用例之前加上一句:

@pytest.mark.xfail

用py.test –runxfail 运行可以强制执行表明为xfail的文件,就好像没有标明一样

可以声明在某个特定条件下会失败的测试

@pytest.mark.xfail(sys.version_info >= (3,3),
reason="python3.3 api changes")

用 -rx 选项可以详细列出xfail的信息

Skip/xfail 也可以参数化:

形式如下:

@pytest.mark.parametrize(("n", "expected"), [
(1, 2),
pytest.mark.xfail((1, 0)),
pytest.mark.xfail(reason="some bug")((1, 3)),
(2, 3),
(3, 4),
(4, 5),
pytest.mark.skipif("sys.version_info >= (3,0)")((10, 11)),
])

如果要在导入失败的时候跳过可以给该模块定义一个如下属性:

docutils = pytest.importorskip("docutils")

或者要求导入的包要满足特定的版本:

docutils = pytest.importorskip("docutils", minversion = "0.3")

最后要提一下的就是pytest的插件使用,在pytest中插件使用非常简单,只要安装了相应的插件,pytest都会在运行的时候自动导入所有的插件,具体可以参考官方文档。

总结

unittest是python自带的一个模块,很多其他的测试框架都和其类似,unittest的使用只需要定义一些以test_ 前缀开头的方法,并封装到一个TestCase的子类中,unittest模块就会自动装载和执行这些测试,unittest模块一个可以很方便的在命令行下使用(有很多命令,非常方便)。同时unittest模块里提供了skip和expectedFailure属性,可以让我们跳过某些测试,或者标记某些用例为预期就是失败的。

pytest是第三方开发的一个python的测试框架,使用的方法和思路都基本和unittest类似,pytest有一个强大的fixture特性,以及skip和xfail标记,同时pytest的插件资源非常丰富,安装和使用也非常的方便。pytest应用非常广泛,是一款很好的测试工具。

 

   
 订阅
  捐助
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号