当前位置: 首页 > 工具软件 > Elastos > 使用案例 >

Elastos获取测试用例列表工具--gtci.py(get testcase info)

祁增
2023-12-01

1. gtci.py

# -*- coding: utf-8 -*-

import sys,os

from testcaseinfo import TestCaseInfo
from runlistinfo import RunListInfo

if __name__ == '__main__':
    reload(sys)
    if (len(sys.argv) < 2):
        print 'python gtci.py module ***'
        exit()

    #print sys.argv[1], sys.argv[2], sys.argv[3]
    module = sys.argv[1]

    if module == '-c':
        if (4 >= len(sys.argv)):
            print 'python gtci.py dirctory module author'
            print 'python gtci.py dirctory module bat'
            exit()

        if 0 == os.path.exists(sys.argv[2]):
            print 'the path does not exist, pls check it! ^_^\n'
            exit()

        if os.path.isfile(sys.argv[2]):
            print 'the path is file, pls use dirctory! ^_^\n'
            exit()

        sys.setdefaultencoding('utf-8')
        TestCaseInfo().GetTestCaseList(sys.argv[2], sys.argv[3], sys.argv[4])

    if module == '-r':
        if (len(sys.argv) < 3):
            print 'python gtci.py module path'
            exit()
        else :
            path = sys.argv[2]
            filepath = os.getcwd() + '/' + path
            print filepath
            RunListInfo().GetRunListInfo(filepath)


先来看一下导入了哪些模块

<pre name="code" class="python">import sys,os

from testcaseinfo import TestCaseInfo
from runlistinfo import RunListInfo

 

导入了两个python系统的模块和自定义的模块,自定义的模块后面再说,先来讲一下sys这个模块在这里的一个注意点。我们看到后面有这样一条代码:

reload(sys)
这时候为什么要动态加载sys模块呢,我们前面不是import过了吗?

原因:

sys.setdefaultencoding('utf-8')
我们看到这里调用setdefaultencoding去设置默认编码格式,而reload(sys)就是为了让这个方法可以被调用。

因为python解释器在启动的时候会调用site.py,在里面有这样一段代码:

# Remove sys.setdefaultencoding() so that users cannot change the
# encoding after initialization.  The test for presence is needed when
# this module is run as a script, because this code is executed twice.
if hasattr(sys, "setdefaultencoding"):
    del sys.setdefaultencoding
这里看出解释器在启动的时候,实际上是把setdefaultencoding方法删除了,所以你想在你自己的程序中调用该方法,就必须重新加载sys模块。


下面根据两个不同的选项-c,-r分别调用两个不同的自定义模块

option: -c

TestCaseInfo().GetTestCaseList(sys.argv[2], sys.argv[3], sys.argv[4])
传入三个参数:参数一  测试用例所在文件路径;参数二  测试模块划分 例如Testing/Framework/Framework.app;参数三  模块负责人  nitibu


2. 接着看TestCaseInfo.py

def GetTestCaseList(self, testCasePath, module, author):
        if (0 == cmp(author,'bat')) : #只获取运行列表
            self.getrunlist = True
            filetype = '.sh'
        else :
            filetype = '.lst'

        listname = module[module.rfind('/')+1:] + filetype
        f = open(listname,"w")
        f.close()

        #get testcases of classed added in dirs
        dailyBuildCases = self.GetDailyBuildTestCaseList(testCasePath)
        print dailyBuildCases

        if os.path.exists(testCasePath + "/sources") :
            self.GetTestCaseInfo(testCasePath, module, author, listname)

        for root, dirs, files in os.walk(testCasePath, True, None, True):
            for f in dirs:
                path = os.path.join(root, f)
                #only make a list with classes added in dirs
                if path[path.rfind('/')+1:] in dailyBuildCases:
                    if os.path.exists(path + "/sources") :
                        self.GetTestCaseInfo(path, module, author, listname)
        print "-----------------Testcase Count:",self.caseCount,"-----------------"

根据模块名module生成对应的运行列表。

根据每个模块下面的dirs文件去判断是否需要生成对应类的测试用例运行列表

os.walk返回元组(dirpath, dirnames, filenames),分别表示--文件夹路径,子文件夹列表,文件夹下文件的列表(不是文件夹)

os.path.join合成子文件夹路径,然后再去调用GetTestCaseInfo去获取运行列表。


def GetTestCaseInfo(self, testCasePath, module, author, listname):

        print "GetTestCaseInfo:",testCasePath

        #if (0 == strcmp(author,'bat')) :
        #    self.getrunlist = True

        CaseSets = []

        item = (['00测试用例', '//测试用例: '],['01所属模块', '//所属模块: '],['02测试对象', '//测试对象: '],
                ['03函数原形', '//函数原形: '],['04参数说明', '//参数说明: '],['05运行环境', '//运行环境: '],
                ['06设计编码', '//设计编码: '],['07完成时间', '//完成时间: '],['08测试简述', '//测试简述: '],
                ['09测试类型', '//测试类型: '],['10优先级别', '//优先级别: '],['11输入文件', '//输入文件: '],
                ['12输出文件', '//输出文件: '],['13预期结果', '//预期结果: '],['14结果检查', '//结果检查: '],
                ['15运行方式', '//运行方式: '],['16补充说明', '//补充说明: '],['17测试路径', '//测试路径: '])

        targetName,caseType = self.GetTestCaseName(testCasePath)
        className = 'C' + targetName

        if caseType == 'eco':
            item[15][1] += 'am instrument -w -e class ' + className + '#'
        else :
            item[15][1] += targetName + ' '

        strTime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()));
        item[7][1] += strTime
        item[1][1] += module
        item[6][1] += author
        item[2][1] += testCasePath[testCasePath.rfind('/')+1:]

        f = open(listname,"a")
        for infile in glob.glob(testCasePath + "/*.cpp"):
            testPath = infile[infile.find('/ElastosTest')+1:]
            TestCaseInfo = dict(item)

            caseStart = False
            caseEnd = False
            findCase = False
            caseIndex = 00  #find case number
            infoPre = ''

            #if the encode is 'utf-8', chane it to 'GB2312'
            # encodeType = self.GetEncodeType(infile)
            # if "utf-8" == encodeType['encoding']:
            #     self.ChangeEncodeType(infile)

            fileSources = open(infile)
            try:
                while True:
                    chunk = fileSources.readline()
                    if not chunk:
                        break
                    line = chunk.strip()
                    if 0 == line.find('/*') and -1 == line.find('*/'):
                        caseStart = True
                        findCase = False
                    if 0 == line.find('*/') and -1 == line.find('/*'):
                        caseEnd = True
                        findCase = True
                        caseStart = False

                    if findCase == True and -1 != line.find(className + '::Test') and -1 != line.find('('):
                        start = line.find('::Test')
                        end = line.find('(')
                        caseName = line[start+2:end]

                        findCase = False
                        caseStart = False
                        caseEnd = False
                        self.caseCount += 1
                        TestCaseInfo['00测试用例'] += str(self.caseCount)
                        TestCaseInfo['12输出文件'] += className + '_' + caseName + '.out'
                        TestCaseInfo['15运行方式'] += caseName + ' ' + targetName + '/Elastos.Droid.Test.CInstrumentationTestRunner'
                        TestCaseInfo['17测试路径'] += testPath

                        self.CheckTestCaseInfo(TestCaseInfo)
                        CaseSets.append(TestCaseInfo) #save caseinfo
                        TestCaseInfo = dict(item)

                    if findCase == True and -1 != line.find('CTest::') and -1 != line.find('('):
                        start = line.find('CTest::')
                        end = line.find('(')
                        caseIndex = line[start+11:end]

                        findCase = False
                        caseStart = False
                        caseEnd = False
                        self.caseCount += 1
                        TestCaseInfo['00测试用例'] += str(self.caseCount)
                        TestCaseInfo['12输出文件'] += targetName + '.out'
                        TestCaseInfo['15运行方式'] += str(caseIndex)
                        TestCaseInfo['17测试路径'] += testPath

                        self.CheckTestCaseInfo(TestCaseInfo)
                        CaseSets.append(TestCaseInfo) #save caseinfo
                        TestCaseInfo = dict(item)

                    if caseStart == True and 0 == line.find('* '):
                        pos = line.find("测试简述")
                        if -1 != pos:
                            TestCaseInfo['08测试简述'] += line[pos + 9:].strip()
                            infoPre = '08测试简述'
                            continue
                        pos = line.find("测试类型")
                        if -1 != pos:
                            TestCaseInfo['09测试类型'] += line[pos + 9:].strip()
                            continue
                        pos = line.find("优先级别")
                        if -1 != pos:
                            TestCaseInfo['10优先级别'] += line[pos + 9:].strip()
                            continue
                        pos = line.find("输入文件")
                        if -1 != pos:
                            TestCaseInfo['11输入文件'] += line[pos + 9:].strip()
                            continue
                        pos = line.find("预期结果")
                        if -1 != pos:
                            TestCaseInfo['13预期结果'] += line[pos + 9:].strip()
                            infoPre = '13预期结果'
                            continue
                        pos = line.find("结果检查")
                        if -1 != pos:
                            TestCaseInfo['14结果检查'] += line[pos + 9:].strip()
                            continue
                        pos = line.find("补充说明")
                        if -1 != pos:
                            TestCaseInfo['16补充说明'] += line[pos + 9:].strip()
                            infoPre = '16补充说明'
                            continue
                        #函数原型
                        #参数说明

            finally:
                fileSources.close()
        for item in CaseSets:
            if self.getrunlist :
                f.write("%s" % item['15运行方式'][12:].strip()) #只获取运行列表
            else :
                for key in sorted(item.keys()):
                    f.write("%s\n" % item[key])
            f.write('\n')
        f.close()

这里看到一个有关测试用例说明的元组:

item = (['00测试用例', '//测试用例: '],['01所属模块', '//所属模块: '],['02测试对象', '//测试对象: '],
        ['03函数原形', '//函数原形: '],['04参数说明', '//参数说明: '],['05运行环境', '//运行环境: '],
        ['06设计编码', '//设计编码: '],['07完成时间', '//完成时间: '],['08测试简述', '//测试简述: '],
        ['09测试类型', '//测试类型: '],['10优先级别', '//优先级别: '],['11输入文件', '//输入文件: '],
        ['12输出文件', '//输出文件: '],['13预期结果', '//预期结果: '],['14结果检查', '//结果检查: '],
        ['15运行方式', '//运行方式: '],['16补充说明', '//补充说明: '],['17测试路径', '//测试路径: '])
一堆中文,挺奇怪,很少见测试用例说明要求写中文的。建议过写英文,没人理会,后来才知道公司用的bug管理系统自己开发的,识别的就是中文,汗。。。


        targetName,caseType = self.GetTestCaseName(testCasePath)
        className = 'C' + targetName

        if caseType == 'eco':
            item[15][1] += 'am instrument -w -e class ' + className + '#'
        else :
            item[15][1] += targetName + ' '

        strTime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()));
        item[7][1] += strTime
        item[1][1] += module
        item[6][1] += author
        item[2][1] += testCasePath[testCasePath.rfind('/')+1:]
上面的代码获取了测试用例的运行方式、完成时间(没什么用,记录下当前时间吧)、所属模块、设计编码(这里就用来记录作者)、测试对象(代码所在路径)

上面的运行方式是必要的,其他暂时还用不到。


for infile in glob.glob(testCasePath + "/*.cpp"):
     testPath = infile[infile.find('/ElastosTest')+1:]
     TestCaseInfo = dict(item)
通过glob.glob获取指定路径下的所有cpp文件

记录某个测试文件cpp在测试目录ElastosTest下的path

根据item生成一个TestCaseInfo字典,这样就可以根据关键字去调用了


            caseStart = False
            caseEnd = False
            findCase = False
            caseIndex = 00  #find case number
            infoPre = ''
用例说明模型

/*
 * 测试简述: TestGetCallingPackage
 * 测试类型: 功能测试
 * 优先级别: P3
 * 结果检查: Dailybuild
 */

检测到 /* 时表示检测到新用例,caseStart = True

检测到 */ 表示用例说明结束,caseEnd = True,这个时候下一行就是测试用例的执行体,设置findCase = True

ECode CActivityTest::TestGetCallingPackage()
{
    String pkgName;
    mActivity->GetCallingPackage(&pkgName);
    AssertStringEquals(pkgName, String("FrameworkTestStub"));

    return NOERROR;
}
找到测试用例后,每条测试用例都是Test开头,所以可以根据这个来获取测试用例方法名称。


                    if findCase == True and -1 != line.find(className + '::Test') and -1 != line.find('('):
                        start = line.find('::Test')
                        end = line.find('(')
                        caseName = line[start+2:end]

                        findCase = False
                        caseStart = False
                        caseEnd = False
                        self.caseCount += 1
                        TestCaseInfo['00测试用例'] += str(self.caseCount)
                        TestCaseInfo['12输出文件'] += className + '_' + caseName + '.out'
                        TestCaseInfo['15运行方式'] += caseName + ' ' + targetName + '/Elastos.Droid.Test.CInstrumentationTestRunner'
                        TestCaseInfo['17测试路径'] += testPath

                        self.CheckTestCaseInfo(TestCaseInfo)
                        CaseSets.append(TestCaseInfo) #save caseinfo
                        TestCaseInfo = dict(item)
设置测试用例编号、输出文件格式、运行方式、测试路径。

运行方式:am instrument -w -e class CComponentNameTest#TestConstructor ComponentNameTest/Elastos.Droid.Test.CInstrumentationTestRunner

然后检测下获取到的这些信息是否正确,由于编码不一样,会有获取的信息没法识别,这里判断的方式是计算一下获取到的信息的长度。

比如:'//优先级别: ' 一共有12个字节的长度,如果后面跟的是乱码,那就没法识别,信息长度就会小于等于12。如下:

    def CheckTestCaseInfo(self, TestCaseInfo):
        if len(TestCaseInfo['08测试简述']) <= 12:
            print "warning: need case summary!!", " case : ",self.caseCount
        if len(TestCaseInfo['09测试类型']) <= 12:
            print "warning: need case type!!", " case : ",self.caseCount
        if len(TestCaseInfo['10优先级别']) <= 12:
            print "warning: need case priority!!", " case : ",self.caseCount
        if len(TestCaseInfo['14结果检查']) <= 12:
            print "warning: need case run mode!!", " case : ",self.caseCount

                        CaseSets.append(TestCaseInfo) #save caseinfo
                        TestCaseInfo = dict(item)
把获取到的信息追加到列表CaseSets中去,重新初始化TestCaseInfo,循环去获取测试用例信息。


最后把CaseSets中的信息都写到前面生成的列表文件中

for item in CaseSets:
            if self.getrunlist :
                f.write("%s" % item['15运行方式'][12:].strip()) #只获取运行列表
            else :
                for key in sorted(item.keys()):
                    f.write("%s\n" % item[key])
            f.write('\n')
        f.close()

可以根据self.getrunlist的值去获取单一的运行列表信息或者全面的用例信息

最后获得的用例信息如下:

//测试用例: 1
//所属模块: Testing/Framework2/Framework.content
//测试对象: ComponentName
//函数原形: 
//参数说明: 
//运行环境: 
//设计编码: nitibu
//完成时间: 2015-08-13 08:52:18
//测试简述: TestConstructor
//测试类型: 功能测试
//优先级别: P1
//输入文件: 
//输出文件: CComponentNameTest_TestConstructor.out
//预期结果: 
//结果检查: Dailybuild
//运行方式: am instrument -w -e class CComponentNameTest#TestConstructor ComponentNameTest/Elastos.Droid.Test.CInstrumentationTestRunner
//补充说明: 
//测试路径: ElastosTest/Elastos/Framework/content/ComponentName/CComponentNameTest.cpp







 类似资料: