`
CharlesCui
  • 浏览: 427759 次
  • 性别: 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,但其核心理念和原则仍然具有很高的参考价值,尤其在理解如何将这些原理应用于更新的版本如QC9.2时。这份指南旨在帮助IT专业人员和质量管理人员理解和实施开放式架构,以提高系统的...

    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 ...

    高通快充协议QC3.0介绍

    - **效率提升**:据高通宣称,与传统的充电方式相比,QC3.0可以将充电速度提高4倍,而发热降低25%。这意味着用户可以在较短时间内充满电池,且设备不会过热。 - **兼容性**:虽然QC3.0是新一代的快充标准,但它向下...

    STM32 驱动IO模拟QC2.0握手程序

    标题中提到的“STM32 驱动IO模拟QC2.0握手程序”表明本文将介绍如何使用STM32微控制器,通过硬件抽象层(HAL)库来模拟快速充电2.0(Quick Charge 2.0, QC2.0)协议的握手过程。QC2.0是高通公司开发的一种用于快速充电的...

    QC资料 QC资料 QC资料

    QC,全称为Quality Control,中文译为质量控制,是产品或服务生产过程中确保质量的一系列管理活动。质量控制旨在发现并消除可能导致产品或服务不符合规定要求的因素,以达到预期的质量标准。在IT行业中,QC是软件...

    高通快充协议QC4.0介绍

    QC4.0协议向下兼容前几代的QC技术,这意味着配备了QC4.0的设备也可以使用支持QC3.0或更低版本的充电器,但充电速度将受到限制。此外,QC4.0不仅适用于手机,还广泛应用于平板电脑、笔记本电脑、智能穿戴设备等,甚至...

    QC-LDPC译码器设计_续

    **QC-LDPC译码器设计** 在无线通信和数据传输领域,低密度奇偶校验(Low-Density Parity Check, LDPC)码因其优良的纠错性能而被广泛研究和应用。特别是量子化(Quasi-Cyclic, QC)结构的LDPC码,由于其结构简单、...

    QC9.0资料大全(安装、使用和管理)

    在本资料大全中,我们将深入探讨如何安装、使用和管理QC9.0,以便您能够充分利用这个工具来优化您的测试流程。 ### 一、QC9.0的安装 安装QC9.0是一个系统性的过程,需要考虑服务器配置、数据库设置以及客户端部署...

    QC客户端插件,IE7,IE8下可以完美运行

    QC客户端插件是与QC服务器进行交互的必备组件,它允许用户在本地计算机上通过浏览器或者其他特定的接口直接访问和操作QC的数据。 标题提到的"QC客户端插件,IE7,IE8下可以完美运行",意味着这个插件是针对旧版本的...

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

    【QC9.0 License、QC9.2 License、QC10.0 License】是与IBM Rational Quality Manager(RQM)相关的授权文件,该软件是IBM提供的一款强大的质量管理工具,主要用于测试管理和质量保证。这些版本号代表着不同的软件...

    QC浏览器.rar

    6. **更新和支持**:作为专门针对QC的浏览器,开发者会持续关注QC平台的更新,确保其始终保持兼容性,并提供及时的技术支持和更新服务。 使用"QC浏览器"解压后的文件可能包含安装程序和其他相关文档,如用户手册、...

    通过excel将用例导入到QC

    不过,值得注意的是,自动化导入虽然便利,但也需要对Excel和QC接口有一定的了解,以及对数据处理的谨慎态度,避免数据丢失或错误导入。因此,在实际操作中,应当充分测试和验证导入过程,确保其稳定可靠。

    QC9.0 安装步骤

    QC9.0作为其中的一个版本,其安装过程涉及多个步骤与特定的环境要求,以下将对QC9.0的安装步骤及其所需环境进行详细解析。 #### 安装前准备与环境要求 QC9.0的安装首先需要一个稳定且满足一定硬件和软件条件的操作...

    QC安装部署教程

    Jboss是一个开源的应用服务器,用于托管QC的应用服务。启动成功后,用户可以通过浏览器访问QC的界面。 7. **完成安装** 最后一步,安装程序会显示“大功告成”的消息,并提示用户可以通过特定的URL访问QC9界面。...

    QC3.0_DEMO.zip_qc3.0_电源_移动电源_移动电源QC3.0_程序

    移动电源程序,QC3.0协议,完整的移动电源模块,带充放电,保护功能

    通过excel导入QC

    在IT行业中,质量中心(Quality Center,简称QC)是一款由HP公司开发的强大的测试管理和缺陷跟踪工具,广泛应用于软件测试领域。...在实际应用中,不断熟悉和掌握Excel与QC的接口特性,将有助于进一步优化工作流程。

    最新QC浏览器1.5版本,打开即可以用

    它可能包含了一些特定的插件或者技术调整,以适应QC的Web服务接口,提供稳定且高效的访问体验。此外,考虑到不同用户的需求,它支持跨平台使用,无论是在Windows、Mac还是Linux环境下,都能提供一致的用户体验。 **...

    TD8和QC9差异比较图

    ### TD8与QC9的主要差异分析 #### 技术架构 **TestDirector 8.0 (TD8):** - **编程语言**: 使用C++作为主要开发语言。 - **中间件**: 依赖Internet Information Services (IIS) 和Component Object Model (COM) ...

    QC 10.0安装和操作手册

    总之,HP Quality Center 10.00提供了一套全面的质量管理解决方案,其安装和操作涉及多个环节,熟练掌握这些知识将有助于提升软件项目的质量管理效率。通过详细阅读和实践提供的安装手册和操作指南,用户可以更好地...

    QC Excel导入插件

    **QC Excel导入插件**解决了这个问题,它允许用户在Excel环境中预先编辑和格式化数据,然后一次性将这些数据批量导入到QC系统中,降低了人为错误的可能性。 使用这个插件,首先需要在本地计算机上安装**...

Global site tag (gtag.js) - Google Analytics