Python测试模块学习笔记

发表于:2017-10-16 10:20

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:CSDN

#
Python
#
python
分享:
  关于unittest模块
  unittest是python发行版里面自带的一个模块,使用起来非常简单,为了能够更好的理解和使用unittest模块,必须了解一下一些基本的概念。
  unittest模块是用来进行单元测试的一个模块。
  关于该模块,有几个类必须理解。
  TestCase类:该类是封装了一个测试用例,即每个测试用例对应于一个TestCase类。
  TestSuite类:该类是一个测试集,即把相关的TestCase类集合到一起形成一个TestSuite
  TestLoader类:该类负责搜索和装载TestCase到TestSuite中。
  TextTestRunner类:该类负责运行测试用例。
  TextTestResult类:该类负责存储测试用例的执行结果。
  最后所有的以上类都集成在了unittest.main()模块中了。
  理解了这些基本概念之后,来看一个很简单的例子(官方文档中的例子)
  importunittest
  classTestStringMethods(unittest.TestCase):
  deftest_upper(self):
  self.assertEqual('foo'.upper(),'FOO')
  deftest_isupper(self):
  self.assertTrue('FOO'.isupper())
  self.assertFalse('Foo'.isupper())
  deftest_split(self):
  s='helloworld'
  self.assertEqual(s.split(),['hello','world'])
  #checkthats.splitfailswhentheseparatorisnotastring
  withself.assertRaises(TypeError):
  s.split(2)
  if__name__=='__main__':
  unittest.main()
  上述这个例子很明确的告诉了我们unittest的使用方法。unittest中的测试函数必须作为某一个类的成员函数并通常以“test_”前缀开头,该类必须是TestCase的子类,之后执行unittest.main()函数,该模块就会自动封装每一个以“test_”前缀开头的例子到一个TestCase类中,然后把所有的TestCase都装载到TestSuite中并由TextTestRunner负责执行。运行一下可以看到如下结果:
  unittest模块还提供了一些命令行应用的简单命令,列举一些常用的如下:
  测试特定模块:
  python-munittestTestmodule_name
  测试特定模块中的某个类:
  python-munittestTestmodule_name.TestClass
  测试特定模块某个类中的某个方法:
  python-munittestTestmodule_name.TestClass.TestMethod
  列举可用的命令行选项:
  python-munittest-h
  测试该模块,并显示执行了的测试方法:
  python-munittest-vTestmodule_name
  测试当前目录下的所有测试用例:
  python-munittest
  最后一个要提的就是unittest的skip和expectedFailure属性。可以看几个小例子。
  跳过该测试函数,并且显示”demonstratingskipping”的提示
  @unittest.skip("demonstratingskipping")
  deftest_nothing(self):
  self.fail("shouldn'thappen")
  在满足特定的条件下跳过该测试用例:
  @unittest.skipIf(mylib.__version__<(1,3),
  "notsupportedinthislibraryversion")
  deftest_format(self):
  #Teststhatworkforonlyacertainversionofthelibrary.
  pass
  该测试用例标记为失败的,在计算测试不通过的测试用例的时候不用考虑:
  @unittest.expectedFailure
  deftest_fail(self):
  self.assertEqual(1,0,"broken")
  关于unittest更详细的介绍可以参考
  unittest参考文档
  关于pytest模块
  pytest是python常用的一个测试框架,可以帮助我们完成从单元测试到复杂的功能测试等一系列功能,同时pytest和其他的测试工具和测试方法的集成的很好,非常容易安装和使用插件。总之,pytest是一款不错的测试工具,下面就来学习怎么使用它。
  pytest不是python标准发行包里面的一个模块,所以使用前需要进行一下安装操作,安装的方法也非常简单,只需要执行如下命令:
  pip-install-Upytest
  或者
  easy_install-Upytest
  如果不太了解pip和easy_install可以参考其他资料。
  安装完成之后可以用如下的命令检测是否安装成功:
  py.test--version
  看到如下结果表明安装成功:
  在安装结束之后就来看下如何是使用。
  pytest的基本使用思想和unittest模块差不多,先来看一个简单的小例子:
  #test_sample.py
  deffunc(x):
  returnx+1
  deftest_answer():
  assertfunc(3)==5
  然后终端进入到test_sample.py所在目录下运行如下命令:
  py.testtest_sample.py
  结果如下所示:
  看一下上面的例子,写了一个函数,并写了一个简单的测试用例,用例中只有一条断言语句,相比于unittest模块,该程序有了如下的简化,即测试方法不需要封装在一个TestCase的子类中(当然如果测试用例庞大,封装到不同的类中还是很有必要),同时也不必要导入任何模块,即可完成一个简单的测试。
  pytest同unittest类似,也提供了许多命令行使用的接口
  测试某个模块:
  py.testtestfile_name
  测试某个模块,并在首次错误用例出现后停止测试:
  py.test-xtestfile_name
  测试某个模块,在出现n个错误后停止:
  py.test–maxfailtestfile_name
  等等还有很多命令具体可以参考官方文档
  pytest官方文档
  下面来说下pytest的一些比较有用的特性。
  首先是pytest中的断言机制。
  使用起来非常简单,就同上述例子一样直接一个assert语句就可以完成。
  如果要断言会出现某个异常可以使用如下的方式:
  importpytest
  deftest_zero_division():
  withpytest.raises(ZeroDivisionError):
  1/0
  这样在出现该异常的时候这个测试用例也不会标记为失败。
  也可以自定义异常的提示信息,看一个下面的例子
  #contentofconftest.py
  fromtest_foocompareimportFoo
  defpytest_assertrepr_compare(op,left,right):
  ifisinstance(left,Foo)andisinstance(right,Foo)andop=="==":
  return['ComparingFooinstances:',
  'vals:%s!=%s'%(left.val,right.val)]

  #contentoftest_foocompare.py
  classFoo:
  def__init__(self,val):
  self.val=val
  deftest_compare():
  f1=Foo(1)
  f2=Foo(2)
  assertf1==f2
  然后终端运行:
  py.test-qtest_foocompare.py
  结果如下所示:
  可以看出要自定义异常信息,只需要在conftest.py里面定义一个名为pytest_assertrepr_compare的函数即可。
  然后不得不看的一个特性就是fixture特性。
  这是官方文档中对fixture特性的一个介绍
Testfunctionscanreceivefixtureobjectsbynamingthemasaninputargument.Foreachargumentname,afixturefunctionwiththatnameprovidesthefixtureobject.
  来看一个例子:
  #contentof./test_smtpsimple.py
  importpytest
  @pytest.fixture
  defsmtp():
  importsmtplib
  returnsmtplib.SMTP("merlinux.eu")
  deftest_ehlo(smtp):
  response,msg=smtp.ehlo()
  assertresponse==250
  assert0#fordemopurposes
  然后终端里运行:
  py.testtest_smtpsimple.py
  可以看到如下结果:
  上述例子的执行过程是这样子,pytest首先寻找test_前缀开头的函数,找到test_ehlo()函数,然后发现该函数需要一个名为smtp的参数,就会去寻找有@pytest.fixture标记的名称为smtp的函数,并构造一个fixtureobject传递给该测试函数,之后执行测试函数。
  函数参数化是一种依赖注入的思想。
  了解了fixture是如何使用的之后,我们来看一下fixture的一些详细的介绍。
  由于构造一个fixtureobject是非常耗费时间的,所以通常一个fixtureobject对象会被许多函数所共享。pytest提供了声明在不同级别共享的方法
  每个函数一个fixtureobject::
  @pytest.fixture(scope="function")
  每个模块一个fixtureobject
  @pytest.fixture(scope="module")
  所有模块都共享一个fixtureobject
  @pytest.fixture(scope="session")
  在fixtureobject对象使用完以后会有一个destroy过程,如果想要在destroy过程中进行一些特殊的操作,可以给fixture函数增加一个request对象,然后定义一个包含你想要执行的操作的函数,调用request的addfinalizer(funct_name)方法来把该函数注册到这个fixtureobject中。
  可以看一个示例:
  @pytest.fixture(scope="module")
  defsmtp(request):
  smtp=smtplib.SMTP("merlinux.eu")
  deffin():
  print("teardownsmtp")
  smtp.close()
  request.addfinalizer(fin)
  returnsmtp#providethefixturevalue
  然后就像之前所说的那样执行测试命令就可以了。
  fixture还可以进行参数化,可以给fixture函数一个“param=[]”的关键字参数,之后对于param中的每个值都会构造一个fixtureobject传递给测试函数使用。
  可以看下如下的代码:
  #contentofconftest.py
  importpytest
  importsmtplib
  @pytest.fixture(scope="module",
  params=["merlinux.eu","mail.python.org"])
  defsmtp(request):
  smtp=smtplib.SMTP(request.param)
  deffin():
  print("finalizing%s"%smtp)
  smtp.close()
  request.addfinalizer(fin)
  returnsmtp
  对于每个需要使用到smtp这个fixture的测试函数,都会接收两个fixtureobject对象,一个使用的是“merlinux.edu”参数,另一个使用的是”mail.python.org”参数。
  使用如下命令可以看到自动生成的每个fixtureobject的id:
  py.test--collect-only
  也可以增加一个ids的参数来自定义每个fixtureobject的id如下代码所示:
  importpytest
  @pytest.fixture(params=[0,1],ids=["spam","ham"])
  defa(request):
  returnrequest.param
  注意0这个参数所构造的fixtureobject对象所对一的id为“spam”,1对应为“ham”
  在一个fixture函数中可以调用其他的fixture函数,只要该被使用的fixture的域范围比使用该fixture的域范围大即可。
  在fixture的使用过程中,pytest会自动决定每个测试函数的调用顺序,使得内存中存在最少的fixtureobject,以减少对系统资源的占用。
  在使用fixtureobject的时候也可以主动告诉pytest(可以减少查找的开销)要调用某个fixture,方式如下:
  @pytest.mark.usefixtures(fixture_name1,fixture_name2,...)
  如果要告诉pytest要在这个模块都使用某个fixture,可以给这个模块定义一个如下的属性:
  pytestmark=pytest.mark.usefixtures(fixture_name1,fixture_name2,...)
  如果要在告诉pytest在整个测试工程中都要使用某个fixture可以新建一个如下的文件:
  #contentofpytest.ini
  [pytest]
  usefixtures=cleandir
  fixture可以被覆盖,有许多级别的覆盖。
  在介绍完fixture特性之后再来看两个特性,skip和xfail属性。
  在满足特定的条件下跳过该测试函数,只需要在这个测试函数前使用如下命令
  @pytest.mark.skipif(sys.version_info>(3,3),reason="requ....")
  展示详细的测试信息可以使用-rs选项:
  py.test-rstest_module
  这些mark也可以共享,要在模块间共享一个mark可以定义一个如下变量:
  minversion=pytest.mark.skipif(mymodule.__versioninfo__<(1,1),reason="atleastmymodule-1.1required")
  然后在测试的函数前加上@minversion即可
  对于一个大的测试项目,通常把marker放在一个单独的mark文件中
  要在满足条件的情况下跳过一整个测试类,可以在该测试类前添加如下语句:
  @pytest.mark.skipif(sys.platform=="win32",reason="requireswindows")
  也可以为这个类定义一个pytestmark属性如下:
  pytestmark=pytest.mark.skipif(sys.platform=='win32',reason="requireswindows")
  如果在一个模块中定义这个全局的属性,pytestmark可以在满足条件的情况下跳过该测试模块
  下面是xfail属性的介绍
  xfail属性是用来表明一个测试用例预计是会失败的,在测试的时候会跳过该用例,在计算不通过的用例的时候不用考虑。
  使用xfail属性,只需要在测试用例之前加上一句:
  @pytest.mark.xfail
  用py.test–runxfail运行可以强制执行表明为xfail的文件,就好像没有标明一样
  可以声明在某个特定条件下会失败的测试
  @pytest.mark.xfail(sys.version_info>=(3,3),
  reason="python3.3apichanges")
  用-rx选项可以详细列出xfail的信息
  Skip/xfail也可以参数化:
  形式如下:
  @pytest.mark.parametrize(("n","expected"),[
  (1,2),
  pytest.mark.xfail((1,0)),
  pytest.mark.xfail(reason="somebug")((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应用非常广泛,是一款很好的测试工具。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号