• python 测试 笔记


    python 提供了PyUnit用于组织测试,是java junit程序包的一个python版本。

    1 断言

    断言是在代码中使用的语句,在进行开发时,可以使用它们去测试代码的有效性,如果这个语言的结果不为真,将会引发一个AssertionError错误,如果这个错误未被捕获,那么程序将会停止。

    >>> large=1000
    >>> assert large>500
    >>> assert large<500
    Traceback (most recent call last):
    File "<pyshell#3>", line 1, in <module>
    assert large<500
    AssertionError
    >>> string="this is a string"
    >>> assert type(string)==type("")
    >>> assert type(string)!=type("")
    Traceback (most recent call last):
    File "<pyshell#6>", line 1, in <module>
    assert type(string)!=type("")
    AssertionError

    如果一个称为__debug__的特殊内部变量为True,就检查断言。如果任何一个断言没有成功,就会引发一个AssertionError错误。因为断言实际上是一个if语句与raise的组合,当出现问题时,就会raise引发一个异常,所以可以指定一个自定义的消息。

    >>> try:
    assert type(string)==type(1),"string is broken"
    except AssertionError:print("Handle the error here.")

    Handle the error here.
    >>> try:
    assert type(string)==type(""),"string is broken"
    except AssertionError:print("Handle the error here.")

    激活断言的变量__debug__是一个特殊的变量,在python启动之后它便不可改变

    对python指定-O 短划线后面接着大写字母O参数,对代码进行优化,意味着除了执行其他优化处理外还将删除断言测试。

    在部署一个程序的时候将用到-O,因此它删除被认为是开发阶段特性的断言

    如果认为自己可以已经犯了一个错误,并希望在之后的开发周期中捕获它,那么可以放入一个断言去捕获此错误,并继续完成其他的工作,直到对该代码进行测试为止。

    2 测试用例和测试套件

    PyUnit是其开发者为这个程序包起的名称,但是导入的模块是:unittest

    每个测试用例都是TestCase类的子类,只要重写TestCase类的runTest方法,就可以定义一个基本的测试,

    可以在单个测试用例类中定义若干不同的测试方法

    测试套件是同时运行于一个特定项目的一系列测试用例。

     assertTrue 是testcase类的属性

    import unittest #导入unittest模块
    class ArithTest(unittest.TestCase):#继承TestCase类
    def runTest(self):#重写runTest方法
    '''test addition and succeed.'''
    self.assertTrue(1+1==2,'one plus one fails!')
    self.assertFalse(1+1!=2,'one plus one fails again!')
    self.assertEqual(1+1,2,'more trouble with one plus one!')
    def suite():
    suite=unittest.TestSuite()#实例化测试套件
    suite.addTest(ArithTest())#加入单元测试
    return suite#返回

    if __name__=='__main__':
    runner=unittest.TextTestRunner()
    test_suite=suite();
    runner.run(test_suite)

    返回单个句点表明已经成功地运行了一个单元测试,相反,如果返回一个F,测试失败了

    import unittest
    class ArithTest(unittest.TestCase):
    def runTest(self):
    '''test addition and succeed.'''
    self.assertTrue(1+1==2,'one plus one fails!')
    self.assertFalse(1+1!=2,'one plus one fails again!')
    self.assertEqual(1+1,2,'more trouble with one plus one!')
    class ArithTestFail(unittest.TestCase):
    def runTest(self):
    '''Test addition and fail.''' #定义文档字符串出错时会显示在错误信息中
    self.assertTrue(1+1==2,'one plus one fails!')
    self.assertFalse(1+1!=2,'one plus one fails again!')
    self.assertEqual(1+1,2,'more trouble with one plus one!')
    self.assertNotEqual(1+1,2,'expected failure here') #定义失败时指定的消息
    self.assertNotEqual(1+1,2,'second failure')
    def suite():
    suite=unittest.TestSuite()
    suite.addTest(ArithTest())
    suite.addTest(ArithTestFail())
    return suite

    if __name__=='__main__':
    runner=unittest.TextTestRunner()
    test_suite=suite();
    runner.run(test_suite)

    =================== RESTART: E:/pythonscript/ch12/test1.py ===================
    .F
    ======================================================================
    FAIL: runTest (__main__.ArithTestFail)
    Test addition and fail.
    ----------------------------------------------------------------------
    Traceback (most recent call last):
    File "E:/pythonscript/ch12/test1.py", line 14, in runTest
    self.assertNotEqual(1+1,2,'expected failure here')
    AssertionError: 2 == 2 : expected failure here

    ----------------------------------------------------------------------
    Ran 2 tests in 0.018s

    FAILED (failures=1)
    >>>

    3 测试装置

    在PyUnit中,测试用例所运行的环境被称为测试装置text fixture 基本的TestCase类定义了两个方法:setUp在运行测试前调用

    tearDown在测试用例完成后调用。这两个方法用于处理测试装置的创建和清理中所涉及的工作。

    setUp失败,tearDown将不被调用。测试用例本身失败,tearDown被调用

    当创建测试时,每个测试的初始状态不应该依赖于之前的测试成功还是失败。每个测试用例应该为自身创建一个原始的测试装置。

    当在一个相同配置的测试装置上重复运行一些测试时,1 可以创建testcase类的子类来定义设置方法和清除方法,然后使用这个子类定义每个测试用例;2 也可以选择在单元测试用例类中定义若干个测试用例方法,然后为每个方法实例化测试用例对象。

    import unittest
    class ArithTestSupper(unittest.TestCase):
    def setUp(self):
    print("setting up arithTest cases")
    def tearDown(self):
    print("cleaning up arithtest cases")
    class ArithTest(ArithTestSupper):
    def runTest(self):
    '''test addition and succeed.'''
    print('running arithtest')
    self.assertTrue(1+1==2,'one plus one fails!')
    self.assertFalse(1+1!=2,'one plus one fails again!')
    self.assertEqual(1+1,2,'more trouble with one plus one!')
    class ArithTestFail(ArithTestSupper):
    def runTest(self):
    '''test addition and fail.'''
    print('running arithtestfail')
    self.assertNotEqual(1+1,2,'expected failure here')
    self.assertNotEqual(1+1,2,'second failure')


    class ArithTest2(unittest.TestCase):
    def setUp(self):
    print('setting up arithTest2 cases')
    def tearDown(self):
    print('cleaning up arithTest2 cases')
    def runArithTest(self):#这里没有重写 runTest函数
    '''test addition and succeed,in one class.'''
    print('running arithtest in arithTest2')
    self.assertTrue(1+1==2,'one plus one fails')
    self.assertFalse(1+1!=2,'one plus one fails again')
    self.assertEqual(1+1,2,'more trouble with one plus one')
    def runArithTestFail(self):
    '''Test addition and fail,in one class.'''
    print('running arithtestfail in arithtest2')
    self.assertNotEqual(1+1,2,'expected failure here')
    self.assertNotEqual(1+1,2,'second failure')

    def suite():
    suite=unittest.TestSuite()
    #first style:
    suite.addTest(ArithTest())
    suite.addTest(ArithTestFail())
    #second style:
    suite.addTest(ArithTest2("runArithTest"))#创建测试用例-显示调用测试方法
    suite.addTest(ArithTest2("runArithTestFail"))
    return suite
    if __name__=='__main__':
    runner=unittest.TextTestRunner()
    test_suite=suite()
    runner.run(test_suite)

    4 用极限编程整合 XP extreme programming

    对编码进行计划,然后将测试用例集合编写为一种框架; 之后才编写实际的代码。在完成编码任务的任何时候,可以重新运行该测试套件以查年接近设计目标的程序。

    测试用例方法的命名约定:"test"+方法名,使unittest.main过程能够对它们进行自动地识别和运行 。

     testfind.py

    import unittest
    import find
    import os,os.path

    def filename(ret):
    return ret[1]

    class FindTest(unittest.TestCase):
    def setUp(self):
    os.mkdir("_test")
    os.mkdir(os.path.join("_test","subdir"))
    f=open(os.path.join("_test","file1.txt"),"w")
    f.write("""first line
    second line
    third line
    fourth line""")
    f.close()
    f=open(os.path.join("_test","file2.py"),"w")
    f.write("""this is a test file.
    it has many words in it.
    this is the final line.""")
    f.close()

    def tearDown(self):
    os.unlink(os.path.join("_test","file1.txt"))
    os.unlink(os.path.join("_test","file2.py"))
    os.rmdir(os.path.join("_test","subdir"))
    os.rmdir("_test")
    def test_01_SearchAll(self):
    """1:test searching for all files."""
    res=find.find(r".*",start="./_test")
    print(res)
    self.assertTrue(map(filename,res)==['file1.txt','file2.py'],'wrong results')
    def test_02_SearchFileName(self):
    '''2:test searching for specific file by regexp.'''
    res=find.find(r"file",start="./_test")
    self.assertTrue(map(filename,res)==['file1.txt','file2.py'],'wrong results')
    res=find.find(r'py$',start="_test")
    self.assertTrue(map(filename,res)==['file2.py'],'Python file search incorrect')

    def test_03_SearchByContent(self):
    '''3:test searching by content.'''
    res=find.find(start="_test",content="first")
    self.assertTrue(map(filename,res)==['file1.txt'],'did not find file1.txt')
    res=find.find(where="py$",start="_test",content="line")
    self.assertTrue(map(filename,res)==['file2.py'],'did not find file2.py')
    res=find.find(where='py$',start='_test',content='second')
    self.assertTrue(len(res)==0,'found something that did not exist')

    def test_04_SearchByExtension(self):
    '''4:test searching by file extension.'''
    res=find.find(start="_test",ext='py')
    self.assertTrue(map(filename,res)==['file2.py'],'did not find file2.py')
    res=find.find(start="_test",ext='txt')
    self.assertTrue(map(filename,res)==['file1.txt'],'did not find file1.txt')

    def test_05_SearchByLogic(self):
    '''5:test searching using a logical combination callback.'''
    res=find.find(start="_test",logic=lambda x:(x['size']<50))
    self.assertTrue(map(filename,res)==['file1.txt'],'failed to find by size')


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

    find.py

    import os,os.path
    import re
    from stat import *

    def find(where='.*',content=None,start='.',ext=None,logic=None):
    context={}
    context['where']=where
    context['content']=content
    context['return']=[]
    context['ext']=ext
    context['logic']=logic

    for root,dirs,files in os.walk(start):
    find_file(root,files,context)

    return context['return']


    def find_file(root,files,context):
    for file in files:
    #Find out things about this file.
    path=os.path.join(root,file)
    path=os.path.normcase(path)
    stat=os.stat(path)
    size=stat[ST_SIZE]

    try:
    ext=os.path.splitext(file)[1][1:]
    except:
    ext=''

    #don't treat directories like files
    #if S_ISDIR(stat(ST_MODE)):continue

    #do filtration based on passed logic
    if context['logic'] and not context['logic'](locals()):continue

    #do filtration based on extension
    if context['ext'] and ext!=context['ext']:continue

    #do filtration base on the original parameters of find()
    if not re.search(context['where'],file):continue

    #do content filtration last,to avoid it as much as possible
    if context['content']:
    f=open(path,'r')
    match=0
    for l in f.readlines():
    if re.search(context['content'],l):
    match=1
    break
    f.close()
    if not match:continue

    # build the return value for any files that passed the filtration tests.
    file_return=(path,file,ext,size)
    context['return'].append(file_return)

     在软件生命周期的维护阶段,对于故障报告,应该做的第一件事是使用它修改已有的用例,或从零开始定义一个新的用例,然后才应该开始修改目标代码本身。

    小结:

    测试最好在开发生命周期的一开始就着手进行。

    最基本的一类测试是断言。断言就是条件,它们被放置在程序中,用于确认应该存在的条件确实存在。

    断言是在代码中所做的陈述,允许对代码的有效性进行测试。如果测试失败,那么将产生AssertionError错误,可以使用断言创建一些测试。

    如 果python 以-O选项运行,则断言将被关闭,在一个运行的系统中,不应该依赖assert来捕获错误。

    在python中,PyUnit是进行全面测试的一种默认的方法,它使得对测试过程的管理变得非常简单,PyUnit是unittest模块中实现。

    应该创建TestCase类的子类,运行测试通过调用run方法来实现

    建立一个测试框架的两种方法,一种是创建自定义类的一个子类,另一种是使用单独的函数实现相同的功能。

    这些测试不需要与模块或程序处于相同的文件中,它们应该被放到其他地方。

    一个测试套件是一系列测试用例,它们是针对一个特定的项目共同运行的。

    在PyUnit中,一个测试用例的运行环境被称为测试装置,基类TestCase定义了两个方法 :setUp 在测试运行前被调用,tearDown在测试用例完成后被调用。这两个方法用于处理在测试装置的创建和清理中所涉及的任何工作 。

  • 相关阅读:
    接入SDK
    GSoap的使用(调用webservice接口)
    NSString/NSMutableString 字符串处理
    iOS Base SDK & Deployment Target 区别&设置
    No identities are available for signing 的解决办法
    GitHub 代码托管Mac下
    代理&Block 传值
    UItextField 的简单控制
    NSPredicate 的使用
    tableView 删除一行后下一行点击事件被忽略
  • 原文地址:https://www.cnblogs.com/caojuansh/p/11660685.html
Copyright © 2020-2023  润新知