将QC的COM接口开放成Rest服务[续]

利用QC的开放架构平台的COM组建,
给HP的QC写一个MetaServer,
将我用到的接口写成Rest服务。

我用到的接口是向测试计划树中添加测试文件夹及节点。

输入是一个代表树结构的Json对象。


QCMetaServer源码:

require 'rubygems'
require 'activerecord'
require 'win32ole'
require 'pp'

require 'sinatra/base'
require 'coderay'

class PRJAlreadyExist < RuntimeError; end
class TestCaseCreateError < RuntimeError; end

class QCMeta < Sinatra::Base

get '/' do
h = {}
h[:ProjectName] = $qc.qc.ProjectName
h[:ServerURL] = $qc.qc.ServerURL
h[:ServerTime] = $qc.qc.ServerTime
h[:ProjectProperties] = $qc.qc.ProjectProperties
h[:ServerName] = $qc.qc.ServerName
h.to_json
end

get '/ole' do
h = {
"TDApiOle80.TDConnection<functional>" => $qc.qc.ole_func_methods.map{|f|f.to_s},
"TDApiOle80.TDConnection<property(get)>" => $qc.qc.ole_get_methods.map{|f|f.to_s},
"TDApiOle80.TDConnection<property(set)>" => $qc.qc.ole_put_methods.map{|f|f.to_s}
}.to_json
params[:color].downcase == "true" ? CodeRay.scan(h,:json).div(:line_number => :tables) : h
end

get '/projects' do
{:ProjectsList => $qc.qc.ProjectsList}.to_json
end

=begin
<C#>

int intSub = 286;
SubjectNode nodSub = objTree.get_NodeById(intSub) as SubjectNode;
TestFactory objTF = nodSub.TestFactory as TestFactory;
lstList = objTF.NewList("");
foreach (Test objTest in lstList)
{
MessageBox.Show((string)objTest.Name);
}
=end


=begin
<VB>
Dim BugFactory, BugList
Set BugFactory = QCConnection.BugFactory
Set BugList = BugFactory.NewList("") 'Get a list of all the defects.
=end


get "/bugs/:list" do
bf = $qc.qc(params[:doamin],params[:project]).BugFactory
bflist = bf.NewList("")
i = 0
h = {}

max = params[:list] || 100
case params[:list]
when /\d+/ then
bflist.each do |bug|
h[bug.ID] = {
:Status => bug.Status,
:AssignedTo => bug.AssignedTo,
:DetectedBy => bug.DetectedBy,
:Priority => bug.Priority,
:Summary => bug.Summary
}
i >= max.to_i ? break : i+=1
end
when /[aA]ll/ then
bflist.each do |bug|
h[bug.ID] = {
:Status => bug.Status,
:AssignedTo => bug.AssignedTo,
:DetectedBy => bug.DetectedBy,
:Priority => bug.Priority,
:Summary => bug.Summary
}
end
end

{:BUGS => h,:COUNT => h.size}.to_json
end

=begin
约定:
项目的层级为多层,
第一层级为"Subject",
末级为测试用例
=end
post "/testcase/create" do
return "参数错误,需要提供测试路径信息" unless params[:info]
$log.info "/testcase/create => params[:info] == #{params[:info]}"
info = ActiveSupport::JSON.decode(params[:info])
begin
$qc.create_testcase($qc.rootNode(params[:subject]||"Subject",params[:doamin],params[:project]),info)
return {:sucess=>true,:msg=>"创建测试用例成功"}.to_json
rescue TestCaseCreateError =>ex
return {:sucess=>false,:msg=>"请检查info参数是否为空或者不是JSON格式 #{ex.to_s}"}.to_json
rescue => ex
return {:sucess=>false,:msg=>"#{ex.to_s}"}.to_json
end
end

post "/testcase/createex" do
return "参数错误,需要提供测试路径信息" unless params[:info]
$log.info "/testcase/createex => params[:info] == #{params[:info]}"
info = ActiveSupport::JSON.decode(params[:info])
begin
$qc.create_testcase_ex(self.rootNode(params[:subject]||"Subject",params[:doamin],params[:project]),params[info])
return {"success"=>true,"msg"=>"OK"}.to_json
rescue => ex
return {"success"=>false,"msg"=>ex.to_s}.to_json
end
end

def self.run!(options={},&trap_handler)
set options
handler = detect_rack_handler
handler_name = handler.name.gsub(/.*::/, '')
puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
"on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/i
handler.run self, :Host => host, :Port => port do |server|
trap(:INT) do
trap_handler.call
## Use thins' hard #stop! if available, otherwise just #stop
server.respond_to?(:stop!) ? server.stop! : server.stop
puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
end
set :running, true
end
rescue Errno::EADDRINUSE => e
puts "== Someone is already performing on port #{port}!"
end
end

=begin
#初始化QC对象,QC对象的连接为单例模式
$qc = QC.new("http://10.1.157.110/qcbin/","cuizheng","",$log)
#测试数据一
case_suite_01 = {
"苍天啊!"=>{
"xxxxxxx"=>{
"崔峥测试文件夹"=>{
"Name"=>"我测试一下",
"Type"=>"MANUAL",
"Tester"=>"Cuizheng"
}
}
}
}
#该方法简单的插入一个路径,路径最后是个testcase
$qc.create_testcase($qc.rootNode("Subject","ALISOFT_CRM","ALISOFT_CRM2006"),case_suite_01)

#测试数据二
case_suite_02 = {
"Leaf"=>false,
"Description"=>"测试一下一级菜单",
"Name"=>"测试一级菜单",
"Children"=>[
{
"Leaf"=>false,
"Description"=>"测试一下二级菜单A",
"Name"=>"测试二级菜单A",
"Children"=>{
"Leaf"=>true,
"Description"=>"测试一下三级菜单",
"Name"=>"测试三级菜单",
"Type"=>"MANUAL"
}
},{
"Leaf"=>true,
"Description"=>"测试一下二级菜单B",
"Name"=>"测试二级菜单B"
}
]
}
#该方法可以一次插入一个树状testcase
$qc.create_testcase_ex($qc.rootNode("Subject","ALISOFT_CRM","ALISOFT_CRM2006"),case_suite_02)
=end

=begin
QC对象的初始化中,传入的帐号需要具有所有Doamin和Project的读写权限
=end
class QC
def initialize(qcpath,user,passwd,log = Logger.new(STDOUT))
@@connPrj={} unless @@connPrj
@tdc,@treeMgr = [nil]*2
@qcpath = qcpath
@user = user
@passwd = passwd
@log = log
@log.info("QC init.")
end

def conn(domain,prj)
@log.info "Global initializion."
tdc=WIN32OLE.new("TDApiOle80.TDConnection")
@log.info "Loaded COM => TDApiOle80.TDConnection"
tdc.InitConnectionEx(@qcpath)
@log.info "QC connection init."
tdc.ConnectProjectEx(domain,prj,@user,@passwd)
@log.info "QC project connection init."
tdc
end

def qc(domain,prj)
if(@@connPrj) then
if(@@connPrj[domain])
if(@@connPrj[domain][prj])
return @@connPrj[domain][prj]
else
@@connPrj[domain][prj]=conn(domain,prj)
end
else
@@connPrj[domain]={}
return qc(domain,prj)
end
else
@@connPrj={}
else
end
end

def treeMgr(domain,prj)
unless @treeMgr then
@treeMgr = self.conn(domain,prj).TreeManager
end
@treeMgr
end

def rootNode(sub="Subject",domain,prj)
self.treeMgr(domain,prj).TreeRoot(sub)
end


=begin
prj_exist?(prj_name)
该方法所指的项目(prj)其实是QC中测试计划中的小项目
=end
def prj_exist?(prj_name,domain,prj)
1.upto(self.rootNode("Subject",domain,prj).Count.to_i) do|node|
return true if(self.rootNode("Subject",domain,prj).child(node).Name == prj_name)
end
false
end

def node_exist?(parent,name)
1.upto(parent.Count.to_i) do|node|
return parent.child(node) if(parent.child(node).Name == name)
end
false
end

def item_exist?(parent,name)
list = parent.FindTests(name,true)
return false unless list
case list.count
when 0 then
@log.info "No Item(named #{name}) exist."
when 1 then
@log.info "Item #{list.Item(1).Name} Already Exist."
return list.Item(1)
else
@log.info "Item.counts => #{list.count}"
end
false
end

=begin
add_prj(prj_name)
该方法项目名称一定要唯一,
否则会抛出PRJAlreadyExist异常
=end
def add_prj(prj_name,domain,prj)
raise PRJAlreadyExist if(self.prj_exist?(prj_name))
self.rootNode("Subject",domain,prj).AddNode(prj_name)
end

=begin
create_testcase(parent=self.rootNode,info={})
该方法的info为需要创建的测试用例及其路径
info[:Type]默认为MANUAL

=end
def create_testcase(parent,info={})
raise TestCaseCreateError if info=={}
if info.values.size == 1 then
pchild = self.node_exist?(parent,info.keys[0])
if(pchild) then
create_testcase(pchild,info.values[0])
else
create_testcase(parent.AddNode(info.keys[0]),info.values[0])
end
elsif info.values.size > 1 then
item = item_exist?(parent,info["Name"])
parent.TestFactory.AddItem([info["Name"],info["Type"],info["Tester"],parent.NodeID]) unless item
end
end

def create_testcase_ex(parent,info={})
raise TestCaseCreateError if info=={}
@log.info info.inspect
case info["Leaf"]
when false,/[fF]alse/ then
@log.info "Branch"
@log.debug "info => "+info.inspect
pchild = self.node_exist?(parent,info["Name"]) || parent.AddNode(info["Name"])
pchild.Description = info["Description"] if info["Description"]
pchild.Post()

@log.info "info[\"Children\"].class => " +info["Children"].class.to_s
case info["Children"].class.to_s
when "Array",Array,/Array/i then
info["Children"].each do |x|
@log.info "create_testcase_ex iteration.(Array)"
@log.info x.inspect
create_testcase_ex(pchild,x)
end
when "Hash",Hash,/Hash/i then
@log.info "create_testcase_ex iteration.(Hash)"
@log.info info.inspect
create_testcase_ex(pchild,info["Children"])
else
@log.error "Children nodes is not Array or Hash."+$/+"info => #{info.inspect}"
end

when true,/[tT]rue/ then
item = item_exist?(parent,info["Name"])
parent.TestFactory.AddItem([info["Name"],info["Type"]||"MANUAL",info["Tester"]||@user,parent.NodeID]) unless item
else
@log.error "Leaf is not true or false"
end
end
end



执行的main文件源码:

require 'rubygems'
require 'QCMetaServer'

require 'logger'

#~ $log = Logger.new("./log/access.log")
$log = Logger.new(STDOUT)
$log.level = Logger::INFO

$qc = QC.new("http://10.1.157.110/qcbin/","cuizheng","",$log)

=begin
下面是Hack后的服务器启动代码
=end

QCMeta.run!(:host=>'0.0.0.0', :port => 4567){
begin
$qc.qc.DisconnectProject
p "QCMeta disconnected to QC."
$qc.qc.ReleaseConnection
p "QCMeta released to QC."
p "QCMeta will shutdown."
rescue => e
p "QCMeta disconnect and release faile."
p "But server still going to shutdown."
p e.to
end
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值