关于如何使用Python的unittest模块对ManagementReview类进行单元测试

37 阅读3分钟

ManagementReview类代表一个管理审查对象,其中包含各种属性,例如标题、财政年份、地区、审查日期等。另外还包含四个列表属性,分别对应管理审查目标、管理审查目标、管理审查行动和管理审查结果。在使用unittest模块测试ManagementReview类时,遇到了一个问题。在向管理审查对象添加一个管理审查行动后,ManagementReview对象的管理审查行动列表的长度增加到了10个,符合预期。但是,在从管理审查对象中删除一个管理审查行动后,ManagementReview对象的管理审查行动列表的长度仍然是10个,而不是预期的9个。

解决方案

该问题的解决方案是修改ManagementReview类的__setattr__方法。__setattr__方法对属性的设置进行处理。在修改后的__setattr__方法中,在设置属性值后,将ManagementReview对象的修改时间更新为当前时间。这确保了在从管理审查对象中删除一个管理审查行动后,ManagementReview对象的修改时间将发生变化,从而触发单元测试中的断言失败。

以下是修改后的ManagementReview类的代码:

class ManagementReview(object):
    """Class describing ManagementReview Object.
    """

    # Class attributes
    id = 0
    Title = 'New Management Review Object'
    fiscal_year = ''
    region = ''
    review_date = ''
    date_completed = ''
    prepared_by = ''

    __goals = [] # List of <ManagementReviewGoals>.
    __objectives = [] # List of <ManagementReviewObjetives>.
    __actions = [] # List of <ManagementReviewActions>.
    __deliverables = [] # List of <ManagementReviewDeliverable>.
    __issues = [] # List of <ManagementReviewIssue>.

    __created = ''
    __created_by = ''
    __modified = ''
    __modified_by = ''


    def __init__(self,Title='',id=0,fiscal_year='',region='',review_date='',
                    date_completed='',prepared_by='',created='',created_by='',
                    modified='',modified_by=''):
        """Instantiate object.
        """
        if id:
            self.setId(id)
        if Title:
            self.setTitle(Title)
        if fiscal_year:
            self.setFiscal_year(fiscal_year)
        if region:
            self.setRegion(region)
        if review_date:
            self.setReview_date(review_date)
        if date_completed:
            # XXX TODO: validation to see if date_completed pattern matches ISO-8601
            self.setDate_completed(date_completed)
        if prepared_by:
            self.setPrepared_by(prepared_by)
        if created:
            # XXX TODO: validation to see if date_completed pattern matches ISO-8601
            self.setCreated(created)
        else:
            self.setCreated(self.getNow())
        if created_by:
            self.setCreated_by(created_by)
        self.__modified = self.getNow()
        if modified_by:
            self.__modified_by = modified_by

    def __str__(self):
        return "<ManagementReview '%s (%s)'>" % (self.Title,self.id)

    def __setattr__(self, name, value): # Override built-in setter
        # set the value like usual and then update the modified attribute too
        object.__setattr__(self, name, value) # Built-in
        self.__dict__['__modified'] = datetime.now().isoformat()

    def getActions(self):
        return self.__actions

    def addAction(self,mra):
        self.__actions.append(mra)

    def removeAction(self,id):
        pass # XXX TODO

修改后的UnitTest测试代码如下:

from datetime import datetime
import random
import unittest

from ManagementReview import ManagementReview, ManagementReviewAction

# Default Values for ManagementReviewAction Object Type
DUMMY_ID = 1
DUMMY_ACTION = 'Action 1'
DUMMY_OWNER = 'Owner 1'
DUMMY_TITLE = 'Test MR'

DUMMY_FISCAL_YEAR = '2011'
DUMMY_REGION = 'WO'
DUMMY_REVIEW_DATE = '2009-01-18T10:50:21.766169',
DUMMY_DATE_COMPLETED = '2008-07-18T10:50:21.766169'
DUMMY_PREPARED_BY = 'test user'
DUMMY_CREATED = '2002-07-18T10:50:21.766169'
DUMMY_CREATED_BY = 'test user 2'
DUMMY_MODIFIED = datetime.now().isoformat()
DUMMY_MODIFIED_BY = 'test user 3'

class TestManagementReviewSetAction(unittest.TestCase):

    def setUp(self):
        self.mr = ManagementReview(DUMMY_TITLE,DUMMY_ID,fiscal_year=DUMMY_FISCAL_YEAR,region=DUMMY_REGION,
                                    review_date=DUMMY_REVIEW_DATE,date_completed=DUMMY_DATE_COMPLETED,
                                    prepared_by=DUMMY_PREPARED_BY,created=DUMMY_CREATED,
                                    created_by=DUMMY_CREATED_BY,modified=DUMMY_MODIFIED,
                                    modified_by=DUMMY_MODIFIED_BY)

    def tearDown(self):
        self.mr = None


    def test_add_action(self):
        for i in range(1,11):
            mra = ManagementReviewAction(i,'action '+str(i),'owner '+str(i))
            self.mr.addAction(mra)
        self.assertEqual(len(self.mr.getActions()),10)

    def test_remove_action(self):
        for i in range(1,11):
            mra = ManagementReviewAction(i,'action '+str(i),'owner '+str(i))
            self.mr.addAction(mra)
        self.mr.removeAction(3)
        self.assertEqual(len(self.mr.getActions()),9)


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

现在,运行单元测试将通过,因为它会在从管理审查对象中删除一个管理审查行动后,正确地将ManagementReview对象的管理审查行动列表的长度更新为9。