将qc的com接口开放成rest服务[续]-你我皆凡人,生在人世间-iteye技术网站
2011年07月01日
利用QC的开放架构平台的COM组建,
给HP的QC写一个MetaServer,
将我用到的接口写成Rest服务。
我用到的接口是向测试计划树中添加测试文件夹及节点。
输入是一个代表树结构的Json对象。
QCMetaServer源码:
require 'rubygems' require 'activerecord' require 'win32ole' require 'pp' require 'sinatra/base' require 'coderay' class PRJAlreadyExist " => $qc.qc.ole_func_methods.map{|f|f.to_s}, "TDApiOle80.TDConnection" => $qc.qc.ole_get_methods.map{|f|f.to_s}, "TDApiOle80.TDConnection" => $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 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 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]).BugFactor y 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[:subje ct]||"Subject",params[:doamin],params[:project]),pa rams[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","ALISOF T_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","ALI SOFT_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.t o_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_na me) 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["Typ e"],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["Typ e"]||"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 }
2011年07月01日
利用QC的开放架构平台的COM组建,
给HP的QC写一个MetaServer,
将我用到的接口写成Rest服务。
我用到的接口是向测试计划树中添加测试文件夹及节点。
输入是一个代表树结构的Json对象。
QCMetaServer源码:
require 'rubygems' require 'activerecord' require 'win32ole' require 'pp' require 'sinatra/base' require 'coderay' class PRJAlreadyExist " => $qc.qc.ole_func_methods.map{|f|f.to_s}, "TDApiOle80.TDConnection" => $qc.qc.ole_get_methods.map{|f|f.to_s}, "TDApiOle80.TDConnection" => $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 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 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]).BugFactor y 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[:subje ct]||"Subject",params[:doamin],params[:project]),pa rams[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","ALISOF T_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","ALI SOFT_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.t o_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_na me) 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["Typ e"],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["Typ e"]||"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 }