华为手环 零星小睡机的小睡模式是怎么形成的

Python中的单元测试 - 为程序员服务
Python中的单元测试
上篇文章《》闲扯了下个人对单元测试的看法。
主题的文章,打算先选几个常见的编程语言作为示例来讲解,因为最近个人的主要编程语言是Python,那就必须先以Python为例讲解最省事了;-)
举个“栗子”
偷懒,就直接拿Python官方文档中的例子来做说明好了;-)
# http://docs.python.org/2/library/unittest.html?highlight=unittest#basic-example
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.seq = range(10)
def test_shuffle(self):
# make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, range(10))
# should raise an exception for an immutable sequence
self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
unittest.main()
先简单说下代码的意思,也就是:写1个测试用例(TestCase),用来测试Python自带的random模块,那1个测试用例里面包含了3个测试,分别用来测试random模块的3个函数(看Python源代码,其实在random模块中已经把一个Random类实例化了,所以从外部用法上看起来就是函数调用一样)。
再简单解释下代码中出现的几个概念,后续再详细讲解:
TestCase,就是测试用例,一个测试用例可以包含多个测试(为了避免混淆可以把“测试”叫“测试项”)。代码中以Python类的形式出现。
test_xxxx,就是测试项,根据实际的功能代码逻辑来编写对应的测试项。代码中以Python类方法的形式出现。
assertXXXX,就是检查点,相当于平时执行测试中的,判断测试结果是否符合测试预期结果的代码模拟。
setUp,就是执行测试项前的准备工作,比如:可以做一些初始化工作,这里就是初始化一个Python列表。另外,和setUp对应的还有个tearDown,后面会讲到。作为一对兄弟,相当于是平时执行测试中的2种行为的代码模拟,分别是:准备测试执行所需要的环境,以及销毁测试过程中产生的垃圾。
其实这里讲解的就是Python标准库,unittest模块,又叫PyUnit。类似其它编程语言,也都有对应的所谓XUnit,X可以替换为Java等其它编程语言等。
这里只是简单讲解下unittest模块中的几个概念,当然其他XUnit也会有类似概念。
test fixture
貌似平时习惯直接就叫fixture了,如果非得翻译个中文名称,叫“装置”不知道合不合适,也就是测试需要的装备。理解上可以直接对应到上面提到过的setUp和tearDown。所谓fixture就是:比如,程序运行的前提需要数据库,还得准备测试用的数据,常见的那些对数据库的操作程序就会如此;又比如,程序运行的前提得访问某个网页,常见的那些爬虫程序就会如此。类似这些,得需要准备好这些fixtures,而这个装置能有所谓清理和还原的功效(tearDown),这样不至于各个测试执行的时候有环境污染造成各种诡异情况。
这个最直白,也听的最多,叫测试用例。理解上可以直接对应到上面提到过的TestCase这个类。对于测试用例来说,就是针对功能代码,模拟一些输入,来验证输出是否符合预期。
test suite
测试套件,也好理解,就是包含了一堆test case的集合。使用上可以根据具体场景来归类各个test case吧,比如:根据业务逻辑分(模块A、模块B);根据测试逻辑分(全功能测试、冒烟测试)。当然,测试套件也可以包含一堆其它测试套件。
test runner
跑测试的家伙,你把各个测试丢给他,他去执行,然后把测试结果形成一份报告让你看。
画个示例图,应该可以更好理解这除了test runner外的几个概念的关系吧:
上面这个图,就是一个TestCase执行测试代码的时候,程序执行的过程吧,想要了解更直接些,直接运行下面这个程序,看下输出信息应该就明白了。
import unittest
class ExampleOrderTestCase(unittest.TestCase):
def setUp(self):
print 'I am setUp'
def tearDown(self):
print 'I am tearDown'
def test_do_something(self):
print 'I am test_do_something'
def test_do_something_else(self):
print 'I am test_do_something_else'
if __name__ == '__main__':
unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))
# Python 2.6
#unittest.main(verbosity=2)
# Python 2.7
控制台输入如下:
test_do_something (__main__.ExampleOrderTestCase) ...
I am setUp
I am test_do_something
I am tearDown
test_do_something_else (__main__.ExampleOrderTestCase) ...
I am setUp
I am test_do_something_else
I am tearDown
一般来说,日常用Python写单元测试代码,最多的还是跟TestCase打交道。而搭建针对具体项目的测试框架时候,会用到的较多是TestSuite、TestResult、TestLoader这些,一旦项目中的测试框架搭建成体系了,很少会打交道。所以,先单独讲下大众化点的TestCase。
执行某条测试前需要准备的工作,比如:某个文件或目录必须存在、数据库需要初始化好、网络服务要准备好、访问的URL需要登录授权完毕等等。
每次调用测试前,都会执行这个方法。如果你运行过上面的程序就应该了解。
顺便讲一下2个概念:测试错误(Error)和测试失败(Failure)。
测试错误,可以简单理解成测试代码执行时候报错了,比如:测试代码中print a,而a没有进行变量声明。
测试失败,可以简单理解成测试代码执行正常,但没有得到预期的测试结果,比如:测试代码中调用功能代码add(1, 2),但返回结果不是3。
另外,从Python 2.7开始支持了skip特性,也可以理解为测试忽略(Ignore),比如:某个测试只想在Windows下才运行,这样在Linux下就会被跳过,也就是忽略。
好了,现在可以讲了,如果代码在这个阶段出错,都会认为是测试错误(Error),比如:
import unittest
class SetUpErrorTestCase(unittest.TestCase):
def setUp(self):
self.assertEqual(1, 2)
def test_one(self):
self.assertEqual(1, 2)
def test_two(self):
self.assertEqual(2, 1)
if __name__ == '__main__':
unittest.main()
执行python test_set_up_error.py输出:
======================================================================
ERROR: test_one (__main__.SetUpErrorTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unittest/test_set_up_error.py", line 6, in setUp
self.assertEqual(1, 2)
AssertionError: 1 != 2
======================================================================
ERROR: test_two (__main__.SetUpErrorTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unittest/test_set_up_error.py", line 6, in setUp
self.assertEqual(1, 2)
AssertionError: 1 != 2
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (errors=2)
结果是2个errors,可以将代码中的setUp的assert修改正确了,再次执行试下,会发现结果是2个failures
tearDown()
执行某条测试完毕后需要销毁的工作,比如:删除测试生成的文件或目录、销毁测试用的数据库等等。
每次调用测试后,都会执行这个方法,即使调用的测试错误(Error)也会调用,比如:
import unittest
class TearDownAlwaysTestCase(unittest.TestCase):
def tearDown(self):
print 'I am tearDown'
def test_one(self):
self.assertEqual(1, 1)
print not_defined
def test_two(self):
self.assertEqual(2, 2)
if __name__ == '__main__':
unittest.main()
执行python test_tear_down_always.py -v输出:
test_one (__main__.TearDownAlwaysTestCase) ... ERROR
I am tearDown
test_two (__main__.TearDownAlwaysTestCase) ...
I am tearDown
======================================================================
ERROR: test_one (__main__.TearDownAlwaysTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unittest/test_tear_down_always.py", line 11, in test_one
print not_defined
NameError: global name 'not_defined' is not defined
----------------------------------------------------------------------
Ran 2 tests in 0.006s
FAILED (errors=1)
这样设计也是为了不让某个测试的错误,影响到下个要执行的测试,所以必须要执行到清理。
如果setUp就测试错误(Error)了,那tearDown()会不会执行呢?各位可以自己写代码验证下;-)
另外,跟setUp类似,如果代码在这个阶段出错,也都会认为是测试错误(Error)。
assertXXXX()
XXXX代码Equal、NotEqual等等一堆协助单元测试的判断方法,太多了直接看官方文档最直接了。问题是这么多不经常用难免记不住,所以平时基本上就记了:
assertEqual
assertNotEqual
assertTrue
assertFalse
assertRaises
因为大多数都可以根据这些转化出来,当然,如果记住最好了,可以帮你一定程度上简化代码,以及增加代码的可读性。比如:要明确判别一个正则输出是否符合预期,用assertRegexpMatches,一看就知道是验证正则表达式的,就比单纯的assertEqual或assertTrue的可读性强。
当然,根据自己项目中实际情况,完全可以基于上述组合,封装出更具项目中的语义表达,提高下代码的可读性,比如:下几篇文章会讲到的Django中的单元测试框架,就封装了不少适合Web开发中的assertXXXX,比如:判断是否URL跳转等。
另外,需要说明的是几个failXXXX的判断方法、assertEquals、assert_,已经不推荐使用了。
搭建自己项目中的单元测试框架
这篇文章就先引出这个主题,暂时不详细展开,后续几篇文章逐渐来展开。
下面几个也会用到,但对于一个项目,已经搭建起来了比较完善的测试框架后,这些就不会经常用到或去改动了。组合使用下面几个,就可以根据各自项目中的实际情况,来搭建一个基本的单元测试框架,后来者基于这个框架,按照约定来填充单元测试代码就可以了。
上面也提到了,TestSuite可以认为是一堆TestCase根据需要打个包,实际运行测试还是以TestCase为单位的。看官方文档,可以知道TestSuite有两个常用的方法,addTest和addTests,addTests可以认为是循环调用了多次addTest。这里add的Test可以是TestCase,也可以是TestSuite,反正是一个套一个,大鱼吃小鱼的关系。
几个实例,可以修改需要执行的不同suite自己执行下试试:
#-*- encoding: UTF-8 -*-
import unittest
class ExampleTestCase(unittest.TestCase):
def test_do_somthing(self):
self.assertEqual(1, 1)
def test_do_somthing_else(self):
self.assertEqual(1, 1)
class AnoterExampleTestCase(unittest.TestCase):
def test_do_somthing(self):
self.assertEqual(1, 1)
def test_do_somthing_else(self):
self.assertEqual(1, 1)
def suite_use_make_suite():
"""想把TestCase下的所有测试加到TestSuite的时候可以这样用
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ExampleTestCase))
return suite
def suite_add_one_test():
"""想把TestCase下的某个测试加到TestSuite的时候可以这样用
suite = unittest.TestSuite()
suite.addTest(ExampleTestCase('test_do_somthing'))
return suite
def suite_use_test_loader():
"""想用TestLoader方式把测试加到TestSuite的死后可以这样用
test_cases = (ExampleTestCase, AnoterExampleTestCase)
suite = unittest.TestSuite()
for test_case in test_cases:
tests = unittest.defaultTestLoader.loadTestsFromTestCase(test_case)
suite.addTests(tests)
return suite
if __name__ == '__main__':
unittest.main(defaultTest='suite_use_test_loader')
TestLoader
可以看到上面最后一个例子,有用到TestLoader这个类,现在简单介绍下。根据刚才的例子,可以把TestLoader简单理解成辅助TestSuite的工具,用来收集符合要求的测试,或者可以认为是一个可以批量产生TestCase的工具。
看官方文档提供了很多方法,用于适应不同的场景,大多数都是类似loadTestsFromXXXX这种方法。
默认有个实例化完毕的可以直接拿来用,就是unittest.defaultTestLoader,上面示例代码中也有体现。如果你觉得默认不满足实际使用,那么就自己写个TestLoader也可以。
另外,还有TestResult和TextTestRunner这两个很有用的东西,可以在后续介绍Django中的单元测试中来重点说明,顺便也可以简单阅读下Django的单元测试框架代码,了解下还是有好处的。如果以后在项目中,需要自定义自己特殊需求的单元测试框架的时候还是有点参考意义的。
这里简单提下,Python中还自带doctest这种形式的单元测试,就是直接把测试写在文档注释。其中一个优点是,看到注释就知道这个模块、函数、类是怎么个用法了;而其中一个缺点是,测试代码的组织上很难模块化。这里就看个简单示例吧:
def show_me_the_money():
&&& print show_me_the_money()
return '$'
if __name__ == '__main__':
import doctest
doctest.testmod()
执行python test_doctest.py -v输出:
print show_me_the_money()
Expecting:
items had no tests:
items passed all tests:
tests in __main__.show_me_the_money
tests in 2 items.
passed and 0 failed.
Test passed.
如何来体会Python中的单元测试,直接在自己的项目中写段单元测试代码吧, show me the code 最实在了。所谓实践就得,Think -& Do -& Done -& Think
Think:就是得有这个意识或者说想法吧,没有意识的话,一切无从谈起。
Do:在自己参与的项目中,先开始尝试着写上一段单元测试代码吧。比如:修复缺陷的时候,增加新特性的时候等等。
Done:成为一种习惯,最后就跟呼吸一样,如果停止,你会觉得难受。
Think:继续Think,实践过后,每个人一定会有自己的感悟和理解。作为一个思考者、改良者、传道者,分享出来你的看法和经验吧。
这里只是很简单地介绍了下Python中的单元测试,更详细的其实还是直接把官方手册相关部分完整的读一遍最实在了,当然希望这篇文章不是官方手册的重复就好。
这里讲的示例,估计实际项目中用起来,也就能应付个基本的加减乘除那种业务逻辑的场景。实际的项目,根据不同类型的开发项目,会有各种需要模拟的测试场景,这个时候一般需要借助更高级抽象的单元测试框架、模块,比如:
可能你自己的项目中已经积累了适合你项目的单元测试类库,这样就挺好。
还有各种成熟的各种开源开发库,比如:Python的Web开发框架Django,它里面就提供了适合Web开发场景的单元测试各种类库。
还有需要模拟各种情况的类库,比如:网络请求、数据库存储、读写文件等等,Python中就提供了不少好的模拟的库(可以Google下Python Mock,官方文档给出的这个资源链接也不错:)。
接下去打算再简单介绍下Django中的单元测试,算是Web开发类型的场景吧,当然还是Python,有兴趣的话,还可以看下Django源代码中有关单元测试的部分,相信会有更大的收获吧。如果有别的开发类型的场景,各位也可以分享出来,大家一起开开眼界。
注解:这篇是个人总结的系列的一篇文章,更多更新内容,可以直接在线查看:。并且部分内容已经公布在GitHub上:
软体动物鼻涕虫的各种随便
原文地址:, 感谢原作者分享。
您可能感兴趣的代码unittest.TestCase中测试用例执行顺序问题
&我们在做自动化测试用例的时候,通常会把一个个测试用例放到一个unittest.TestCase的扩展类中,当我们运行测试用例文件时,测试文件中的测试用例会随机执行的。如:
#-*- coding: UTF-8 -*-
import time
import unittest
import sys
class DemoTest(unittest.TestCase):
def setUp(self):
Def test_a(self):
Def test_b(self):
Def test_c(self):
Def test_d(self):
Def tearDown(self):
if __name__ == '__main__':
unittest.TestLoader().loadTestsFromTestCase(DemoTest)
unittest.TextTestRunner(verbosity=2).run(suite)
上面的示例是包含四个测试用例的一个测试用例集,在我们执行这个测试文件后,四个测试用例的执行顺序是随机的。如果这几个测试用例有依赖关系,则会影响你们用例的执行,于是我在想能不能控制一下测试用例的执行顺序呢?虽然测试用例相互之间不能有依赖关系,可是这算是一个尝试吧!我在网上查到一个方法,是适用于junit的:
&&&&&&&&&&&&&&&&&&&&&&&&&&
换种顺序来执行TestCase(Junit适用)
Junit的TestCase,总是按固定的顺序执行的.
正如你在Eclipse中跑Run As Junit Test,
无论你跑多少次, TestCase的执行顺序都是一致的,可重复的.
这就导致一个问题, TestCase之间的独立性无法保证.
例如下面一个Test类中的2个TestCase:
public class DaoTest {
public void test_count() {
dao.insert(new User("root", "123456"));
assertEquals(1, dao.count(User.class));
public void test_insert() {
dao.clear(User.class, null);
dao.insert(new User("admin", "123456"));
assertEquals(1, dao.count(User.class));
如果先执行test_count()然后执行test_insert(),两个TestCase都能通过.
但如果先执行test_insert(),然后执行test_count(),则test_count()会失败.
所以,有必要去打乱TestCase的默认执行顺序,以暴露出TestCase本身的问题. TestCase更可靠,才能让主代码更可靠.
我实现了一个简单的方式,使用的是Junit的公开API,
测试过4.3和4.8.2,均可使用:
//得到所有带@Test的方法,这里用的是Nutz的资源扫描,反正你能得到全部Test类就行
&List list =
Scans.me().scanPackage("org.nutz");
List reqs = new ArrayList();
Map reqMap = new HashMap();
for (Class clazz : list) {
&&&&&&&&&&&
Method[] methods = clazz.getMethods();
&&&&&&&&&&&
for (Method method : methods) {
&&&&&&&&&&&&&&&
if (method.getAnnotation(Test.class) != null) {
&&&&&&&&&&&&&&&&//将单个TestCase(即一个Test Method),封装为Junit的Test Request
&&&&&&&&&&&&&&&&&&&
Request req = Request.method(clazz, method.getName());
&&&&&&&&&&&&&&&&&&&
reqs.add(req);
&&&&&&&&&&&&&&&&&&&
reqMap.put(req , method);//在最终打印测试结果时,方便查找具体出错的Method
&&&&&&&&&&&&}
&&&&&&&&&&&
是一个List,我们可以按需调整TestCase的顺序
正序 //nothing change.
反序Collections.reverse(reqs)
乱序Collections.shuffle(reqs)
//把执行顺序保存下来,方便重现执行顺序
&&&&&&&&&&&
FileWriter fw = new FileWriter("./test_order.txt");
&&&&&&&&&&&
for (Request request : reqs) {
&&&&&&&&&&&&&&&
fw.write(reqMap.get(request).toString());
&&&&&&&&&&&&&&&
fw.write("\n");
&&&&&&&&&&&
&&&&&&&&&&&
fw.flush();
&&&&&&&&&&&
fw.close();
catch (IOException e) {}
//到这里, List已经按我们预期的方式排好,可以执行测试了
final TestResult result = new TestResult();
RunNotifier notifier = new RunNotifier();
notifier.addListener(new RunListener() { //需要设置一个RunListener,以便收集测试结果
&&&&&&&&&&&
public void testFailure(Failure failure) throws Exception
&&&&&&&&&&&&&&&
result.addError(asTest(failure.getDescription()),
failure.getException());
&&&&&&&&&&&
&&&&&&&&&&&
public void testFinished(Description description) throws Exception
&&&&&&&&&&&&&&&
result.endTest(asTest(description));
&&&&&&&&&&&
&&&&&&&&&&&
public void testStarted(Description description) throws Exception
&&&&&&&&&&&&&&&
result.startTest(asTest(description));
&&&&&&&&&&&
&&&&&&&&&&&
public junit.framework.Test asTest(Description description)
&&&&&&&&&&&&&&&
return new junit.framework.Test() {
&&&&&&&&&&&&&&&&&&&
public void run(TestResult result) {
&&&&&&&&&&&&&&&&&&&&&&&
throw Lang.noImplement();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
public int countTestCases() {
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&
//来吧,执行之!!
for (Request request : reqs) {
&&&&&&&&&&&
request.getRunner().run(notifier);
//接下来,就是打印结果了.
System.out.printf("Run %d , Fail %d , Error %d \n",
result.runCount(), result.failureCount(),
result.errorCount());
if (result.failureCount() & 0) { //断言失败的TestCase
&&&&&&&&&&&
Enumeration enu = result.failures();
&&&&&&&&&&&
while (enu.hasMoreElements()) {
&&&&&&&&&&&&&&&
TestFailure testFailure = (TestFailure)
enu.nextElement();
&&&&&&&&&&&&&&&
System.out.println("--Fail------------------------------------------------");
&&&&&&&&&&&&&&&
System.out.println(testFailure.trace());
&&&&&&&&&&&&&&&
testFailure.thrownException().printStackTrace(System.out);
&&&&&&&&&&&
if (result.errorCount() & 0) { //抛异常的TestCase
&&&&&&&&&&&
Enumeration enu = result.errors();
&&&&&&&&&&&
while (enu.hasMoreElements()) {
&&&&&&&&&&&&&&&
TestFailure testFailure = (TestFailure)
enu.nextElement();
&&&&&&&&&&&&&&&
System.out.println("--ERROR------------------------------------------------");
&&&&&&&&&&&&&&&
System.out.println(testFailure.trace());
&&&&&&&&&&&&&&&
testFailure.thrownException().printStackTrace(System.out);
&&&&&&&&&&&
考验一下你的TestCase吧!!
让它在乱序中多次执行. Nutz按这种思路,已经爆出几个Bug(当然,我已经迅速fix了)
python中不好用,于是只好想一下其他的方法了。我想是不是可以把每个测试用例变成函数,然后再写一个函数来顺序调用它们呢?
这个方法虽然可以控制顺序,可以也有一定的风险,如果出错了,不会按测试用例给报错,不能准确地统计出测试用例地正确率!如果全部通过则没有问题,可是影响报告的结果,需要想办法来美化一下报告。
修改后的代码如下:
#-*- coding: UTF-8 -*-
import time
import unittest
import sys
class DemoTest(unittest.TestCase):
def setUp(self):
Def a(self):
Def b(self):
Def c(self):
Def d(self):
Def &test_demo(self):
Def tearDown(self):
if __name__ == '__main__':
unittest.TestLoader().loadTestsFromTestCase(DemoTest)
unittest.TextTestRunner(verbosity=2).run(suite)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。当前位置: →
→ Python单元测试——深入理解unittest
Python单元测试——深入理解unittest
& 作者及来源: hackerain - 博客园 &
&收藏到→_→:
摘要: Python单元测试——深入理解unittest
"Python单元测试——深入理解unittest"::
的重要性就不多说了,可恶的是python中有太多的框架和工具,什么unittest, testtools, subunit, coverage, testrepository, nose, mox, mock, fixtures, discover,再加上setuptools, distutils等等这些,先不说如何写,光是怎么运行就有n多种方法,再因为它是测试而非功能,是很多人没兴趣触及的东西。但是作为一个优秀的,不仅要写好功能代码,写好测试代码一样的彰显你的实力。如此多的框架和工具,很容易让人困惑,困惑的原因是因为并没有理解它的基本原理,如果一些基本的概念都不清楚,怎么能够写出思路清晰的测试代码?
今天的主题就是unittest,作为标准python中的一个模块,是其它框架和工具的基础,参考资料是它的官方文档:http://docs.python.org/2.7/library/unittest.html和源代码,文档已经写的非常好了,我在这里记录的主要是它的一些重要概念、关键点以及可能会碰到的一些坑,目的在于对unittest加深理解,而不是停留在泛泛的表面层上。
unittest是一个python版本的junit,junit是java中的框架,对java的,有一句话很贴切:keep the bar green,相信使用eclipse写过java的都心领神会。unittest实现了很多junit中的概念,比如我们非常熟悉的test case, test suite等,总之,原理都是相通的,只是此文来自: 马开东博客
转载请注明出处 网址:
用不同的语言表达出来。
在文档的开篇就介绍了unittest中的4个重要的概念:test fixture, test case, test suite, test runner,我觉得只有理解了这几个概念,才能真正的理解的基本原理,下面就主要围绕这几个概念来展开这篇文章。
首先通过查看unittest的源码,来看一下这几个概念,以及他们之间的关系,他们是如何在一起工作的,其静态类图如下:
一个testcase的实例就是一个。什么是呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setup),执行测试代码(run),以及测试后环境的还原(teardown)。元测试(unit test)的本质也就在这里,一个是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
而多个集合在一起,就是testsuite,而且testsuite也可以嵌套testsuite。
testloader是用来加载testcase到testsuite中的,其中有几个loadtestsfrom__()方法,就是从各个地方寻找testcase,创建它们的实例,然后add到testsuite中,再返回一个testsuite实例。
texttestrunner是来执行的,其中的run(test)会执行testsuite/testcase中的run(result)方法。
测试的结果会保存到texttestresult实例中,包括运行了多少此文来自: 马开东博客
转载请注明出处 网址:
,成功了多少,失败了多少等信息。
这样整个流程就清楚了,首先是要写好testcase,然后由testloader加载testcase到testsuite,然后由texttestrunner来运行testsuite,运行的结果保存在texttestresult中,整个过程集成在unittest.main模块中。
现在已经涉及到了test case, test suite, test runner这三个概念了,还有test fixture没有提到,那什么是test fixture呢??在testcase的docstring中有这样一段话:
test authors should subclass testcase for their own tests. construction&and deconstruction of the test's environment ('fixture') can be&implemented by overriding the 'setup' and 'teardown' methods respectively.
可见,对一个环境的搭建和销毁,是一个fixture,通过覆盖testcase的setup()和teardown()方法来实现。这个有什么用呢?比如说在这个中需要访问 ,那么可以在setup()中建立 连接以及进行一些初始化,在teardown()中清除在 中产生的数据,然后关闭连接。注意teardown的过程很重要,要为以后的testcase留下一个干净的环境。关于fixture,还有一个专门的库函数叫做fixtures,功能更加强大,以后会介绍到。
至此,概念和流程基本清楚了,下面通过简单的例子再来实践一下,就拿unittest文档上的例子吧:
import random
import unittest
class testsequencefunctions(unittest.testcase):
def setup(self):
self.seq = range(10)
def test_shuffle(self):
# make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertequal(self.seq, range(10))
# should raise an exception for an immutable sequence
self.assertraises(typeerror, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
self.asserttrue(element in self.seq)
def test_sample(self):
with self.assertraises(valueerror):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.asserttrue(element in self.seq)
if __name__ == '__main__':
unittest.main()
testsequencefunctions继承自unittest.testcase,重写了setup()方法,并且定义了三个以'test'开头的方法,那这个testsequencefunctions类到底是个什么呢?它是一个,还是三个?说是三个的话,它本身继承自testcase,说是一个的话,里面又有三个test_*()方法,明显是三个。其实,我们只要看一些testloader是如何加载的,就一清二楚了,在loader.testloader类中有一个loadtestsfromtestcase()方法:
def loadtestsfromtestcase(self, testcaseclass):
"""return a suite of all tests cases contained in testcaseclass"""
if issubclass(testcaseclass, suite.testsuite):
raise typeerror("test cases should not be derived from testsuite." \
" maybe you meant to derive from testcase?")
testcasenames = self.gettestcasenames(testcaseclass)
if not testcasenames and hasattr(testcaseclass, 'runtest'):
testcasenames = ['runtest']
loaded_suite = self.suiteclass(map(testcaseclass, testcasenames))
return loaded_suite
gettestcasenames()是从testcase这个类中找所有以&test&开头的方法,然后注意第9行,在构造testsuite对象时,其参数使用了一个map方法,即对testcasenames中的每一个元素,使用testcaseclass为其构造对象,其结果是一个testcase的对象集合,可以用下面的代码来分步说明:
testcases = []
for name in testcaenames:
testcases.append(testcase(name))
loaded_suite = self.suiteclass(tuple(testcases))
可见,对每一个以test开头的方法,都为其构建了一个testcase对象,值得注意的是,如果没有定义test开头的方法,而是将测试代码写到了一个名为runtest的方法中,那么会为该runtest方法构建tes搜索此文相关文章: ——深入理解unittest此文来自: 马开东博客
网址: 站长QQ
Python单元测试——深入理解unittest_博客园相关文章
博客园_总排行榜
博客园_最新
博客园_月排行榜
博客园_周排行榜
博客园_日排行榜}

我要回帖

更多关于 华为手环 零星小睡 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信