• 国乒男女队出征第54届世乒赛“盼天晴” 2018-04-24
  • 崔世安会见吴政隆 双方就推进苏澳合作深入交谈 2018-04-24
  • 音乐剧《朝暮有情人》演绎港穗两地三代情 2018-04-24
  • 3月70城房价环比涨幅扩大 2018-04-24
  • 国际油价4月19日涨跌互现 2018-04-23
  • 南平市人民防空办公室成立武夷新区人防办事处 2018-04-23
  • 劳动者合法权利也不可“任性”滥用 2018-04-22
  • SKT招募绝地求生队员 网友迫切看到faker与韦神对枪! 2018-04-22
  • 送别余光中:诗人虽远行,乡愁永流传 2018-04-22
  • 连超模肯豆都“爱不释脚”的穆勒鞋 你不了解一下?|穆勒鞋|肯豆|超模 2018-04-22
  • 国家国际发展合作署举行揭牌仪式 2018-04-21
  • 春潮涌动,千余青少年相约科技馆 2018-04-21
  • 英俄用“关闭电视台”互相威胁 双边关系雪上加霜 2018-04-21
  • 拔不拔赖清德?蔡英文何去何从 2018-04-21
  • 我国阅读指数首次发布 人均纸书阅读量为4.66本 2018-04-20
  • python 小工具:用 python 操作 HP 的 Quality Center

    栏目: IT技术资讯 发布于: 2017-07-22 02:06:01


    来源:http://www.rocksun.cn/201705/84984.html


    背景是这样的:

    这个组的测试人员每跑一个 case 都要上传测试结果附件到 QC。每个待测功能??榭赡馨甘习俚?case。于是手工上传测试结果变成了繁重的体力劳动。令人惊讶的是我们的工具开发组竟然说做不了 QC 的测试结果附件上传。更让我惊讶的是,测试人员竟然真的手工上传结果上传了大半年了。


    以下我写了个小工具解决这个问题:思路很简单,调用 hp 提供的 ALM Rest api 接口。把一个个用户操作转化成 http 请求。然后按照接口要求,把附件一个一个上传到指定的 QC test instance 上。主要用的库是:requests:负责发送 http 请求 BeautifulSoup4:负责解析 QC 服务器返回的响应。整个工具非常简单。


    具体步骤如下:先让用户登录进 QC

    [2017-05-17 13:57:25,023] Starting new HTTP connection (1): XXXXX.com
    [2017-05-17 13:57:25,430] post http://XXXXX.com:80/qcbin/authentication-point/authenticate[2017-05-17 13:57:25,430] headers = {'Authorization': 'Basic XXXXXXX'}
    [2017-05-17 13:57:25,430] 200 OK
    [2017-05-17 13:57:25,430] --------------------

    ?

    (上面这个带了时间戳的东西是我的 log。每个请求都会自己记下来发了些啥。)然后按照用户给定的的 test_set_id 去 QC 里搜索一下这个 test set 下的 test instance 有哪些。

    [2017-05-17 13:57:25,430] --------------------[2017-05-17 13:57:26,303] get http://XXXXX.com:80/qcbin/rest/domains/{Domain name}/projects/{Project name}/test-instances?query={contains-test-set.id[XXXXXX]}&fields=id,test-id&page-size=2000[2017-05-17 13:57:26,303] 200 OK
    [2017-05-17 13:57:26,303] --------------------

    ?

    然后每个 test instance id 去查一下 qc 里对应的 test id,也就是测试用例的 id,再根据这个 id,从 qc 里查出测试用例的名字。搜索的时候,这样指定返回值的字段名,以下是搜索某个 test set id 下的 test-instance,并且要求返回值只包含 test instance id 和 test idtest-instances?query={contains-test-set.id[XXX]}&fields=id,test-id&page-size=2000

    [2017-05-17 13:57:26,303] --------------------[2017-05-17 13:57:26,516] get http://XXXXX.com:80/qcbin/rest/domains/XXX/projects/XXX/tests?query={id[XXXXXX]}&fields=name&page-size=2000[2017-05-17 13:57:26,516] 200 OK
    [2017-05-17 13:57:26,516] --------------------

    ?

    根据上面查出来的 test-id 再次查询,得到这个 test 的 name 字段值查出了测试用例的名字是用来和我要上传的附件做匹配的,这两个名字对上了,就会把某个附件传到这个用例对应的 test-instance 上。上传文件部分调用的是这样的一个 requests 请求:

    data = {'filename': ("", attachment_path+attachment_name), ? ? ? ? ? ?'override-existing-attachment':("","y")
     ? ? ? ?}
    file = {'file': open(attachment_name, 'rb')
     ? ? ? ?}
    response = self.session.post(url, files=file,data=data)

    ?

    最后附上一些代码,供参考:这个类是用来做 get 请求和 post 请求的。auto_log 装饰器会把发了什么请求打成 log。不像某些 QC 操作的库里一样满屏的打 log

    import logging as logimport requestsclass RestClient: ? ?def __init__(self):
     ? ? ? ?self.headers={}
     ? ? ? ?self.session = requests.Session()
     ? ? ? ?log.basicConfig(level=log.INFO, format='[%(asctime)s] %(message)s') ? ?def auto_log(func): ? ? ? ?def wrapper(*args, **kw):
     ? ? ? ? ? ?r = func(*args, **kw)
     ? ? ? ? ? ?log.info("%s %s", func.func_name, args[1]) ? ? ? ? ? ?for key in kw:
     ? ? ? ? ? ? ? ?log.info("%s = %s",key, kw[key])
     ? ? ? ? ? ?log.info("%s %s",r.status_code,r.reason)
     ? ? ? ? ? ?log.info("--------------------") ? ? ? ? ? ?return r ? ? ? ?return wrapper
     ? ?@auto_log ? ?def get(self, url): ? ? ? ?return self.session.get(url)
     ? ?@auto_log ? ?def post(self, url, files=None, data=None,headers=None): ? ? ? ?if headers is None:
     ? ? ? ? ? ?headers = self.headers ? ? ? ?return self.session.post(url, headers=headers,files=files,data=data)

    ?

    第二个类是用来操作 QC 的,现在我做了用户登录、搜索 entity、添加附件三个功能。后续还会加上更新 entity 和创建 entity 等,把参考文档里的 common tasks 全都实现在这个类里。

    class QCSession: ? ?def __init__(self, username, password, qc_url):
     ? ? ? ?self.api_client=RestClient()
     ? ? ? ?auth = base64.b64encode("{}:{}".format(username, password))
     ? ? ? ?self.api_client.session.headers['Authorization'] = "Basic {}".format(auth)
     ? ? ? ?self.qc_url = qc_url
     ? ? ? ?self.login() ? ?def login(self):
     ? ? ? ?r = self.api_client.post(self.qc_url.auth, headers=self.api_client.session.headers) ? ? ? ?assert(r.status_code is 200) ? ?def get(self, *args):
     ? ? ? ?r = self.api_client.get(self.qc_url.path(*args)) ? ? ? ?assert (r.status_code is 200 or r.status_code is 201) ? ? ? ?return r ? ?def add_attachment(self, filename, over_ride,*args):
     ? ? ? ?data = { ? ? ? ? ? ?'filename': ("", filename), ? ? ? ? ? ?'override-existing-attachment': ("", over_ride)
     ? ? ? ?}
     ? ? ? ?files = { ? ? ? ? ? ?'file': open(filename, 'rb')
     ? ? ? ?}
     ? ? ? ?r = self.api_client.post(self.qc_url.path(*args),data=data,files=files) ? ? ? ?assert (r.status_code is 200 or r.status_code is 201) ? ? ? ?return r ? ?def query_entitys(self, entity_name, query_expression, fields=None, page_size="2000"): ? ? ? ?"""
     ? ? ? ?:param entity_name: the entity to query 
     ? ? ? ?:param query_expression: the query expression
     ? ? ? ?:param fields: the files to return in results
     ? ? ? ?:param page_size: the result page size, by default is 2000 which is the max value
     ? ? ? ?:return: resturn the BeautifulSoup parsed result ? ? ? ?"""
     ? ? ? ?query_url=u"%s?query={%s}&fields=%s&page-size=%s" %(entity_name,query_expression,fields,page_size)
     ? ? ? ?r = self.get(query_url)
     ? ? ? ?res = BeautifulSoup(r.content, "lxml") ? ? ? ?return res

    ?

    还有一个保存和生成 QC 的各种 url 地址的类:

    class QCURL: ? ?def __init__(self, hostname, domain, project, port='80'):
     ? ? ? ?self.__base = u'http://{}:{}/qcbin/'.format(hostname,port)
     ? ? ? ?self.__work = self.__base + u'rest/domains/{}/projects/{}/'.format(domain,project)
     ? ? ? ?self.auth = self.__base + u'authentication-point/authenticate'
     ? ? ? ?self.logout = self.__base + u'authentication-point/logout/'
     ? ?def path(self, *args): ? ? ? ?return self.__work + '/'.join([str(arg) for arg in args])

    ?

    还有第四个类就是用 QC Session 类来实现我要的业务功能了。具体代码就不贴了,里面没什么可以让别人重用的东西。拿上面三个类就可以用了。给个例子:登录 QC,并查询指定的 testset_id 下所有的 test-instances,并返回其 id 和 test-id 下面所有没赋值的变量都换成自己环境的真实值的字符串就行了。

    qc_url = QCURL(hostname, domain, project, port)
    qc_session = QCSession(username, password, qc_url)
    qc_session.query_entitys('test-instances', 'contains-test-set.id[%s]' % testset_id, "id,test-id")

    ?

    希望这篇文章可以帮到一些有同样问题的人。以上代码在 HP ALM 11.52 上测试通过。

    参考文档:

    http://alm-ehlp.saas.hpe.com/en/12.53/api_refs/REST_TECH_PREVIEW/ALM_REST_API_TP.html


    推荐一个专注技术架构和行业解决方案的公众号“架构师技术联盟”,文章内容涉云计算、存储、服务器、网络、软件定义和虚拟化等,相信对完善您的知识体系架构大有裨益。??????????????

    ?????????????????????????????

    荐文章:




    本站文章除注明转载外,均为本站原创或编译?;队魏涡问降淖?,但请务必注明出处。
    转载请注明:文章转载自 七星彩票平台
    本文标题:python 小工具:用 python 操作 HP 的 Quality Center
    IT技术书籍推荐:
    细说PHP(第2版)
    细说PHP(第2版)
    高洛峰 (作者)
    《细说PHP(第2版)》内容简介:PHP是开发Web应用系统最理想的工具,易于使用、功能强大、成本低廉、高安全性、开发速度快且执行灵活。全书以实用为目标设计,包含PHP开发最主流的各项技术,对每一个知识点都进行了深入详细的讲解,并附有大量的实例代码,图文并茂。系统地介绍了PHP的相关技术及其在实际Web开发中的应用。 《细说PHP(第2版)》共六个部分,分为30个章节,每一章都是PHP独立知识点的总结。内容涵盖了动态网站开发的前台技术(HTML+CSS)、PHP编程语言的语法、PHP的常用功能??楹褪涤眉记?、MySQL数据库的设计与应用、PHP 面向对象的程序设计思想、数据库抽象层PDO、Smarty模板技术、Web开发的设计模式、自定义框架BroPHP、Web项目开发整个流程等目前PHP开发中最主流的技术。每一章中都有大量的实用示例,以及详尽的注释,加速读者的理解和学习,也为每章的技术点设置了大量的自测试题。最后以一个比较完整的、采用面向对象思想,以及通过MVC模式设计,并结合Smarty模板,基于BroPHP框架的CMS系统为案例,详细介绍了Web系统开发从设计到部署的各个细节,便于更好地进行开发实践。