`
CharlesCui
  • 浏览: 416496 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

将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
}
分享到:
评论

相关推荐

    QC8.2开放式架构指南

    QC8.2开放式架构指南。 虽然有些过时,但是还是比较经典的,结合QC8.2指南一起,基本上可以触类旁通到9.2

    QC8.2和QC9.0相关资料大全

    (4)QC8.2开放式测试体系架构指南.pdf (5)QC9.0BPT英文指南.pdf (6)QC9.0Site_Admin_API_Reference英文版 (7)QC9.0安装指南英文版 (8)QC9.O中文版用户手册 (9)QC操作汇总.doc (10)QC测试用例管理.ppt ...

    QC资料 QC资料 QC资料

    QC资料 QC资料 QC资料QC资料QC资料QC资料QC资料QC资料

    QC使用流程QC使用方法

    QC使用流程QC使用流程QC使用流程QC使用流程QC使用流程QC使用流程QC使用流程

    QC9.0License+QC9.2License+QC10.0License

    QC9.0License+QC9.2License+QC10.0License,使用时将扩展名"txt"修改成"license

    测试管理工具QC培训

    测试管理工具QC培训测试管理工具QC培训测试管理工具QC培训测试管理工具QC培训

    QC-LDPC译码器设计_续

    这些是我收集的有关QC-LDPC码译码器设计的FPGA实现相关的文章,上次传了一部分,这是下部分。希望对大家有用

    QC错误解决方法

    QC错误解决方法,关于QC各种问题的详细解决方法,都可以在这里找到

    qc论文如何吸引技术人员积极参加QC活动

    QC小组活动是企业提高工作质量、服务质量、提高职工素质、发挥职工聪明才智、满足职工实现自身价值的有效途径。职工素质的提高、工作质量的改善必将促进人的安全行为的养成和物及周围环境安全状态的形成。QC小组活动...

    高通快充协议QC3.0介绍

    快充协议QC3.0官方介绍文档,英文版

    2015年QC优秀成果汇编.zip

    QC小型化油罐清洗装置的研制.doc QC提高国际项目采办竣工资料一次交验合格率.doc QC提高干挂圆弧石材安装的一次验收合格率.doc QC提高砂岩幕墙面板安装一次合格率.docx QC提高钢筋混凝土坡屋面质量一次合格率.doc QC...

    QC9.0+SQLServer2005安装问题解决办法

    QC9.0+SQLServer2005安装问题解决办法

    QC Excel导入插件

    QC Excel导入插件,经典导入插件,方便使用

    QC插件

    QC插件QC插件QC插件QC插件QC插件QC插件QC插件QC插件QC插件

    QC 10.0安装和操作手册

    HP Quality Center10.00安装手册 QC10.0操作手册

    QC教程,qc使用说明

    QC教程,有关QC使用方面的相关说明。 qc简介、需求制定、制定计划测试等方面的说明

    QC(ALM)与vbs之间的接口

    类似QTP提供的组件式接口,HP公司的QC(ALM)同样提供了组件式接口。 从tcl程序中,收集了QC常用的接口,包括测试计划、测试集、测试实验室、测试报告等。 该组件对象为:TDApiOle80.TDConnection,希望能给大家提供...

    适用于高通QC2.0/QC3.0快充识别IC-UP9616

    up9616是一个高效率同步整流降压...up9616具有恒定的输出快速充电电压5.1v/9.2v/12.1v(qc2.0 / qc3.0)从D +和D -线和自动检测检测是否连接的供电设备(局部放电)是快速充电(qc2.0 / qc3.0)能够在使输出电压调整。

    QC入门到精通

    QC入门到精通,快速上手,使用qc。

    qc小组活动记录配电带电检修班QC小组

    qc小组活动记录配电带电检修班QC小组

Global site tag (gtag.js) - Google Analytics