testlink根据关联的jenkins测试job执行结果自动更新测试用例结果

试了大半天,终于给弄通了。主要坑在Testlink Plugin的文档掉线看不到了,只能瞎子似的尝试摸索网上到处乱搜,还是记录一下吧:

1. Testlink和jenkins的安装略,没啥好说的。

2. Testlink Plugin插件安装完之后,需要做一下插件的配置:
Jenkins->系统管理->系统设置(全局设置&管理),现在会多一项Testlink:

Name填testlink+版本号
URL如果testlink是用默认安装的方式,那就填testlink的访问link+lib/api/xmlrpc/v1/xmlrpc.php,如果安装过程中改了默认配置,那就填xmlrpc.php相对于testlink的url根路径的位置
Developer Key,Testlink的个人API访问密钥,在用户的个人设置里可以找到或者新生成。考虑到权限控制,可以考虑在testlink里专门创建一个jenkins的用户,用这个用户的api密钥,以免和正常的用户互相干扰


3. 接下来就是在Testlink里写测试用例。按testlink的做法,先创建测试项目Test Project,再创建测试计划Test Plan,再创建测试用例集Test Set,最后创建测试用例Test Case。需要注意的是,因为后面要建立关联,所以项目Project和计划Plan的名字不要用中文,都用英文,否则jenkins关联时插件很可能直接抛异常

4. 接下来需要创建一个自定义字段,专门用来关联testlink和jenkins:
Testlink->自定义字段管理->创建:




名称和标签自己定义,但最好保持一致(虽然我也没试过不一致会咋样)
类型选string,因为后面关联的时候多半会用用例名称、类名、方法名,都是字符串
启用选测试用例设计,因为这个字段是测试用例设计阶段就需要填写的
测试执行中是否显示无所谓,选否吧


5. 接下来让创建的自定义字段生效:
Testlink->指派自定义字段,选中自定义字段前面的方框,配置,点下面的指派使之生效。
配置可以再改,更新就行了。建议不要选中“必填项”,这样如果一个测试计划关联的既有自动运行的case,也有手动运行的case,就不会干扰了。当然如果出于管理的考虑,或者知道这个测试计划就是全都关联自动化测试的,选上也行,如果有手动的case,随便填点儿啥就是了。


6. 接下来先去jenkins里配置自动运行的job:
创建job前面配git啥的都和普通的测试job一样,只是在构建那里,增加构建步骤,选Invoke Testlink,插件出来三大块:
1) Testlink Configuration:

Testlink Version:下拉框里就是上面第2步配的Name
Test Project Name:输入上面第3步里的测试项目Project名称,我就是这里用中文抛异常了
Test Plan Name:输入上面第3步里的测试计划Plan名称
Build Name:正常就是jenkins每次build的号,插件会把这个作为每次运行的版本标识回写到testlink用例的执行结果里,所以这里可以利用jenkins的变量写些有意义的字符
剩下两项Custom Fields和Test Plan Custom Fields都填上面第5步的自定义字段的名字

2) Test Excution:

和普通CI job一样,add action增加一些shell命令把你的测试用例跑起来能生成测试结果报告就行。我是都写到代码里了,所以直接一行运行就完了。顺便放一下我这段例子吧,大家想试的话比较方便:
# cat simple.py
#!/usr/bin/env python
# encoding: utf-8

import os
import logging
import unittest
import xmlrunner

class TestSuite1(unittest.TestCase):
    """ test cases defined here """

    @classmethod
    def setUpClass(cls):
        """ test suite's init """
        logging.debug('suite begin')

    @classmethod
    def tearDownClass(cls):
        """ test suite's finalize """
        logging.debug('suite end')

    def setUp(self):
        """ each test case's init """
        logging.debug('init testcase')

    def tearDown(self):
        """ each test case's finalize """
        logging.debug('un-init testcase')

    def dtp1(self):
        """ test 1+1 """
        rst = 1 + 1
        self.assertEqual(2, rst)
   
    def dtp2(self):
        """ test 1-1 """
        rst = 1 - 1
        self.assertEqual(1, rst)
   
    def dtp3(self):
        """ test 1*1 """
        rst = 1 * 1
        self.assertEqual(1, rst)

    def dtp4(self):
        """ test 1/1 """
        rst = 1 / 1
        self.assertEqual(1, rst)
   
    def dtp5(self):
        """ test 1%1 """
        rst = 1 % 1
        self.assertEqual(100, rst)

if __name__ == '__main__':
    FILE_NAME = os.path.basename(__file__)
    FILENAME = os.path.splitext(FILE_NAME)[0]
    LOG_NAME = FILENAME + '.log'

    os_alias = os.name
    if os_alias == 'nt':
        LOG_DIR = 'D:/temp/'
    else:
        LOG_DIR = os.getcwd()

    logging.basicConfig(level=logging.DEBUG,
                        format='[%(asctime)s] %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s',
                        datefmt='%Y-%b-%d %H:%M:%S %a',
                        filename=LOG_DIR + '/' + LOG_NAME,
                        filemode='w')

    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('%(levelname)-s: %(message)s')
    console.setFormatter(formatter)
    logging.getLogger('').addHandler(console)

    suite = unittest.TestSuite()

    tests = [TestSuite1("dtp1"),
             TestSuite1("dtp2"),
             TestSuite1("dtp3"),
             TestSuite1("dtp4"),
             TestSuite1("dtp5"),]
    suite.addTests(tests)

    # runner = unittest.TextTestRunner(verbosity=2)
    runner = xmlrunner.XMLTestRunner(output='test-reports')
    runner.run(suite)

所以我是在代码里写了生成unittest的xml格式的结果,放到test-reports目录下去

3) Result Seeking Strategy:

这部分是我摸索最多的地方。这一部分主要就是起关联测试用例的作用,告诉jenkin该通过什么方法知道jenkins ci job里的每个测试项应该对应到testlink里的哪个测试用例上去。


这里可以选择多种策略,首先分为JUnit和TestNG两个大方向。因为我上面的测试代码是按照XUnit的方式写的,所以我选JUnit。然后下面的Junit case name,意思是告诉jenkins将来要按照用例的名字去建立联系;class name用测试类的类名;method name用测试类里面的方法名;suite name用测试类中的suite名。那么可以想见,case name和method name的粒度最细,suite name居中,class name肯定最粗。这里我选了Junit method name的方式:

然后填要解析的测试结果所在Include Pattern:如上面第2)步贴的代码所示,我生成的结果文件会是在test-report目录下,所以这里相应地填test-reports/*.xml
key custom fields:仍然填testlink里的自定义的那个字段
保存后,jenkins上的配置完成

7. 接下来修改希望关联jenkins里自动执行的那些测试用例:
编辑测试用例->选中测试用例,主要将测试方式从默认的手动改成自动,另外根据上面第3)步的选择,给自定义字段填入相应的关联字串:
比如我选了按method name来,那就找到这个测试用例想关联的测试代码中的类和方法名,填入:类#方法,类和方法之间用#分隔。如果上面选的策略是按class name来,那这里就只需要填类名。以此类推。


8. 好了,接下来就可以运行了。不用去testlink指派执行人,当初用的是哪个用户的api密钥,执行人就是会谁。所以再一次的,开始的时候最好创建一个专门的jenkins用户。无论是手动在jenkins里立即构建,还是通过jenkins和git的关联自动触发,jenkins执行完了之后,会有testlink的结果:

而如果去testlink里找到这个test plan,也可以看到这些测试用例的结果:

评论

此博客中的热门博文

Windows上调试C/C++程序时自动产生coredump的设置方法

利用Gitlab的Jira issue tracker实现Jira issue自动根据Gitlab commit/merge更新状态

go用xorm去update数据库的一个坑