记得原来在一个公司时,具体很多原因,testlink上项目中的用例都需要执行形成漂亮的报告,但实际测试中又不需要去执行,所以就必须将用例根据上一次测试报告一个一个手工去贴结果刷用例,几百条用例,几天就浪费了,做完还什么都没获得。正好这二天没事,就用python写一个自动执行的小程序!~~~~~

思路:从测试计划及测试报告中提取caseID,及测试结果,使用webdriver去执行用例,使用yaml配置文件,将测试产品、测试计划、报告设成可配

需安装selenium、yaml组件

在TestLink 1.9.13上成功运行

代码是王道,直接上代码,如下:

#coding:utf-8
'''
Created on 2015-11-6
@author: Administrator
'''
from selenium import webdriver
from selenium.webdriver.support.ui import Select
import time,random
import re,os
import urllib2
import yaml
print os.path.dirname(__file__) #获取当前文件绝对路径
try:
f=open('testlinkauto.yaml')
datadict=yaml.load(f)
testconfig=datadict['testlink']
except Exception,e:
print "The error is :",e start=time.clock()
chrome_driver_path=r'C:\\Program Files (x86)\Google\Chrome\Application\chromedriver.exe' #这里使用chrome,所以必需下载chromedriver驱动,否则无法执行
browser = webdriver.Chrome(chrome_driver_path)
print testconfig.get('address')
browser.get(testconfig.get('address')) #登陆
browser.find_element_by_id('login').clear()
browser.find_element_by_id('login').send_keys(testconfig.get('user'))
browser.find_element_by_name('tl_password').send_keys(testconfig.get('password'))
browser.find_element_by_name('login_submit').click()
time.sleep(2) #执行用例程序
def testCaseWrite(resultdict):
for case,result in resultdict.items():
print "%s The case is %s and result is %s" % (time.strftime('%Y-%m-%d %H:%M:%S'),case,result)
browser.switch_to_default_content() #切回默认的frame
browser.switch_to_frame('mainframe') #切到主frame
#切到左侧例表frame
browser.switch_to_frame('treeframe')
#选择要执行的用例
browser.find_element_by_name('filter_tc_id').clear()
browser.find_element_by_name('filter_tc_id').send_keys(case)
browser.find_element_by_id('doUpdateTree').click()
browser.find_element_by_id('expand_tree').click()
time.sleep(2)
#browser.find_elements_by_css_selector("//a[@href='javascrpit:ST(29,30)']").click()
#browser.find_element_by_xpath('//*[@id="ext-gen21"]/li/div/a').click()
#browser.find_element_by_xpath('//*[@id="ext-gen21"]/li/div/a').click()
browser.find_element_by_xpath("//a[contains(@href,'javascript:ST')]").click() #点击执行
time.sleep(5) #切换至右侧的用例frame
browser.switch_to_default_content()
browser.switch_to_frame('mainframe')
browser.switch_to_frame('workframe') #写执行记录并确定提交
#browser.find_element_by_class_name('step_note_textarea').send_keys(u'成功')
#browser.find_element_by_id('notes').send_keys(u'成功')
browser.find_element_by_xpath("//textarea[starts-with(@name,'notes')]").send_keys(result.decode('utf-8'))
time.sleep(2) #Select(browser.find_element_by_name('statusSingle')).select_by_value("p") #选择项目
Select(browser.find_element_by_xpath("//select[contains(@name,'statusSingle')]")).select_by_value("p")
#//*[@id="step_status_31"]
time.sleep(1)
browser.find_element_by_xpath("//input[contains(@name,'save_results')]").click()
time.sleep(random.uniform(2,4))#获取测试计划用例列表并去重排序
def getTestPlan(url):
date=urllib2.urlopen(url).read()
varpatten=testconfig['testprojectid']+'-\d{1,5}'
testlist=re.findall(varpatten,date)
aa=list(set(testlist))
aa.sort(key=lambda x:int(re.match('\D+-(\d+)',x).group(1))) #根据ID来排序
return aa #获取原来测试报告中用例及执行结果对应字典关系
def getTestResult(url):
date=urllib2.urlopen(url)
data=date.read()
global caselist
varpatten='测试用例 ('+testconfig['testprojectid']+'-\d+)'
print varpatten
caselist=re.findall(varpatten,data)
#caselist=re.findall('测试用例 (GX-\d+)',data)
resultlist=re.findall('执行备注.*?">(.*)</td',data)
return dict([(x,y) for x in caselist for y in resultlist ]) if __name__=='__main__':
#定位工具栏选项
browser.switch_to_frame('titlebar') #切换到iframe为titlebar上
print browser.current_url
#browser.find_element_by_name('testproject').click()
#遍历下拉框并选择需要的项目
select = browser.find_element_by_name("testproject")
allOptions = select.find_elements_by_tag_name("option") for option in allOptions:
print "Value is: " + option.get_attribute("value")
print "Text is:" +option.text
if testconfig['testprojectid'] in option.text:
option.click()
break time.sleep(5)
browser.find_element_by_xpath("//img[@title='执行']").click() #执行用例
browser.switch_to_default_content() #切回默认的frame
browser.switch_to_frame('mainframe') #切到主frame
print browser.current_url #执行程序
TestPlanCase=getTestPlan(testconfig['testplanurl'])
TestResultCase=getTestResult(testconfig['testreporturl'])
print TestResultCase #未有结果的列表并排序
print "计划中要执行的用例列表:" ,list(set(TestPlanCase))
print "原测试报告中已执行的用例列表:",list(set(caselist))
unuse=set(TestPlanCase)^set(caselist)
unuselist=list(unuse)
unuselist.sort(key=lambda x:int(re.match('\D+-(\d+)',x).group(1))) print "此次未执行的case列表为:",unuselist
print "总共%s个!" % len(unuselist)
print "大约要花费%d分钟" % (len(unuselist)*14/60) #执行
print TestResultCase
testCaseWrite(TestResultCase)
end=time.clock()
print "执行结束,总共花费%6.2f 秒时间" % (end-start) '''
#定位测试计划并选用
browser.switch_to_default_content()
browser.switch_to_frame('mainframe')
print browser.current_url
print testconfig['testplan']
browser.find_element_by_xpath("//div[contains(@class,'chosen-c')]/div/ul").click
#browser.find_element_by_xpath("//div[contains(@class,'chosen-c')]/div/ul/li[3]").click
#browser.find_element_by_xpath("//div[contains(@class,'chosen-c')]").click()
#WebDriverWait(browser,10).until(lambda the_driver: the_driver.find_element_by_tag_name('li').is_displayed())
#menu=browser.find_element_by_tag_name('li').find_element_by_link_text('GXVCP_IOS_D10V100_rc4')
#webdriver.ActionChains(browser).move_to_element(menu).perform()
#drop_down=browser.find_element_by_xpath("//div[contains(@class,'chosen-c')]/div/ul")
print drop_down
time.sleep(1)
#browser.find_element_by_link_text('GXVCP_IOS_D10V100_rc4') allOptions1 = drop_down.find_elements_by_tag_name("li")
print allOptions1
drop_down.find_element_by_link_text('GXVCP_IOS_D10V100_rc4')
browser.find_element_by_name('testplan')
Select(browser.find_element_by_name('testplan')).select_by_visible_text(testconfig['testplan']) '''
最后这个在定位测试计划时,一直定位不出来,所以还是得手工点击测试计划。 yaml配置文件内容:
testlink:
address: http://192.168.3.247:8080/testlink/login.php
user: xxxxx
password: 111111
testprojectid: GX
testplanurl: file:///F:/Private/testplan%20GXVCP_IOS_D10V100_rc3.htm
testreporturl: file:///F:/Private/testreport%20GXVCP_IOS_D10V100_rc4.htm

--更新,为了执行用例时间上不一致,使用random函数进行sleep,time.sleep(random.uniform(2,4))

测试计划定位方法已找到:详细见http://www.cnblogs.com/landhu/p/5010723.html

这里就不更新刷用例的程序了,有需要的朋友自行完善!

如使用有问题,请联系:

362299908@qq.com

Testlink自动执行用例小程序的更多相关文章

  1. Python小任务 - 如何编写指定时间执行的Python小程序

    我们在平时的工作中经常会遇到这样的需求,需要再某个时间点执行一段程序逻辑. 那么,在python中我们是怎么做的呢? 下面看代码: waitDesignatedTimeToRun.py import ...

  2. 在Java中如何设置一个定时任务,在每天的一个时间点自动执行一个特定的程序

    Quartz定时机制 首先导入jar包到程序内 quartz-all-1.6.0.jar 然后创建一个XML TimeConfig.xml 名字可以自己定义 <?xml version=&quo ...

  3. Asp.Net(C#)自动执行计划任务的程序实例分析

    在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务.实现计划任务的方法也有很多,可以采用SQ ...

  4. 零基础入门微信小程序开发

    注:本文来源于:<零基础入门微信小程序开发> 课程介绍 本达人课是一个系列入门教程,目标是从 0 开始带领读者上手实战,课程以微信小程序的核心概念作为主线,介绍配置文件.页面样式文件.Ja ...

  5. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  6. [转]微信小程序、微信公众号、H5之间相互跳转

    本文转自:https://www.cnblogs.com/colorful-paopao1/p/8608609.html 转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加 ...

  7. 微信小程序、微信公众号、H5之间相互跳转

    转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息 ...

  8. 京东购物小程序 | Taro3 项目分包实践

    背景 京东购物小程序作为京东小程序业务流量的主要入口,承载着许多的活动和页面,而很多的活动在小程序开展的同时,也会在京东 APP 端进行同步的 H5 端页面的投放.这时候,一个相同的活动,需要同时开发 ...

  9. 小程序跳转H5及其他页面

    一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息等场景中. ...

随机推荐

  1. QT编译错误:member access into incomplete type 'QMouseEvent'

    想在QT程序中使用鼠标事件,添加重载的响应函数,并实现后,一直提示 member access into incomplete type 'QMouseEvent' 既然使用了QMouseEvent类 ...

  2. 小白扫盲:Android 设备的CPU类型(通常称为”ABIs”)

    早期的Android系统几乎只支持ARMv5的CPU架构,但是现在不同了,你知道现在它支持多少种吗?7种! Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起 ...

  3. activeMq的helloword

    http://blog.csdn.net/clj198606061111/article/details/38236679 点对点的同步消息模型 http://blog.csdn.net/jiuqiy ...

  4. 关于redis连接池

    1.redis-py不需要显式使用连接池. 在幕后,redispy使用一个连接池来管理与Redis服务器的连接.默认情况下,每个Redis实例将依次创建自己的连接池.您可以通过将已创建的连接池实例传递 ...

  5. Go之简单并发

    func Calculate(id int) { fmt.Println(id) } 使用go来实现并发 func main() { for i := 0; i < 100; i++ { go ...

  6. php扩展AMQP,安装报错解决

    接下来来安装php扩展AMQP,安装了它以后,才能用PHP操作rabbitmq.wget https://pecl.php.net/get/amqp-1.4.0.tgztar -zxvf amqp-1 ...

  7. YUV格式学习笔记

    YUV与RGB表现图像的方法不同,其采用的是一个亮度信号加两个色差信号的方式来表现图像.其中UV表示的是CbCr,常见的YUV格式有:YUV4:2:0,YUV4:2:2,YUV4:1:1,YUV4:4 ...

  8. SpringBoot(十三)-- 不同环境下读取不同配置

    一.场景: 在开发过程中 会使用 开发的一套数据库,测试的时候 又会使用测试的数据库,生产环境中 又会切换到生产环境中.常用的方式是 注释掉一些配置,然后释放一下配置.SpringBoot提供了在不同 ...

  9. flask操作mongo两种方式--ORM

    #manage.py #coding=utf-8 #Flask-Script是一个可以在flask应用外部编写脚本的扩展 #常用功能: #运行一个开发的服务器 #python shell中操作数据库看 ...

  10. python --葵花宝典

    1.python 函数 定义 ---def() def  fun(): print(“我是小甲鱼!!”) 调用函数 a =fun() print (a) 即可  ,注:函数调用是由上而下: 2.pyt ...