信息系统开发平台OpenExpressApp:【OpenTest】 之 框架实现说明

  在信息系统开发平台OpenExpressApp:【OpenTest】 之 如何实现自动化测试框架中说了一下在OEA中使用IronRuby开发了一个自动化UI测试工具,在给测试人员使用后,他们提出一些问题,本篇将介绍一下OpenTest的内部实现的一些内容

问题

  1. 现有自动化框架的运行机制是怎样的?
  2. Utils中定义的是通用方法吗?TestObject和Utils的关系是什么?TestObject的运行是否以Utils为基础?
  3. 可以依靠哪些对象属性来定位对象?在类FindControlHelper中,是以AutomationId、Name两种属性进行定位,当AutomationId或Name相同时该如何处理?
  4. ....

框架使用方法介绍

  1. 修改inc.rb中的$ExePath = "d:/GZJ/OpenExpressApp/OpenExpressApp.Host.WPF/bin/Debug"为你的程序路径
  2. 在框架的TestCase目录下编写测试用例功能脚本文件:XXX.rb,文件大致结构如下
    $用例名称 = "这个测试用例的中文名称"  #出现错误后,邮件中会使用这个名称来报错
    
    #以下两个require是必须的
    require "inc.rb"                       
    require "TestCase/run_app.rb"
    
    #以下为用例步骤描述区域,相当于以前写的测试用例步骤
    #用例步骤描述:
    # 1 新增部门, 编码:Test  名称:自动化测试
    # 2 .....
    打开模块 "部门管理"
    
    # 1 新增部门, 编码:Test  名称:自动化测试
    添加
    属性编辑器("编码").输入("Test")
    属性编辑器("名称").输入("自动化测试")
    ....
    
  3. 在框架入口文件main.rb中增加测试用例的启动命令
    require "inc.rb"
    require "mail.rb"
    
    运行测试用例文件 "demo/project.rb"
    运行测试用例文件 "demo/org_manage.rb"
    #运行测试用例文件 "demo/contract.rb"
    
    发送邮件
    
    # TestApplication.instance.app.close
    Playback.Cleanup()
    
  4. 在框架main.rb中增加邮件接收人地址
    #增加收件人列表
    $收件人 << "zhoujg@grandsoft.com.cn"
    
  5. 执行rub.bat运行自动化测试脚本

运行机制

脚本运行是由run.bat启动,main.rb作为入口文件执行功能脚本文件,每个功能脚本文件最上面都有【require "TestCase/run_app.rb"】,以保证主程序已经启动。

# 保证引用此单元的测试用例的先决条件是应用程序已经启动
TestApplication.instance.run "d:/GZJ/OpenExpressApp/OpenExpressApp.Host.WPF/bin/Debug/OpenExpressApp.Host.WPF.exe", "admin", "" unless 主窗口.Exists

在功能测试脚本中,基本上都是以【打开模块】函数作为开头,打开模块内部通过模拟点击功能模块列表来打开功能模块,

def 打开模块(title)
  begin
    m = TestApplication.instance.open_module(title)
    设置当前测试对象 m
    m
  rescue
    raise "没有打开模块 #{title}"
  end    
end

打开模块后会把当前打开的模块设置为默认对象,要明白这个机制就需要知道Ruby的元编程特性,【设置当前测试对象】是在object.rb中实现的。在object.rb还实现了一个重要方法【method_missing】,这可以保证后续编写的脚本作用范围都是针对当前打开模块来操作的。可以参考IronRuby:元编程特性【method_missing】的使用

#测试对象链表,最后一个为当前测试对象,执行Object方法时会执行此对象的方法。加上链表主要是为了处理弹出窗口又关闭后自动切换测试对象的情况
$CurTestObject = []

class Object
  def 设置当前测试对象(test_object)
    $CurTestObject << test_object
    $CurTestObject.each { |item| puts item.FriendlyName }
  end        
  
  def method_missing(name, *args, &block)    
    if @test_control.respond_to?(name)      
       return @test_control.send(name, *args, &block)    
    else      
       raise  "没有定义方法:" + name.to_s    
    end  
endend

打开模块后,后续脚本的基本语法参考信息系统开发平台OpenExpressApp:【OpenTest】 之 语法及其使用介绍

一个简单的语法如下:属性编辑器("编码").输入("Test")

为了理解这个脚本是如何执行以及什么意思,下面我将介绍TestObject

TestObject

TestObject是对我们设计来表示要测试的控件的一个抽象对象,我们先拿最常用的一个函数【属性编辑器】来说一下。

 

  def 属性编辑器(title,  type = nil)
    begin
      path = title.split(".")
      obj = self
      if path.length > 1
        path[0..-2].each{|page_title|
          obj = obj.页签(page_title)
        }
      end
      if type == nil
        puts "文本编辑框:" + title
        edt = WpfEdit.new(obj.test_control)
        edt.SearchProperties["Name"] = path[-1]  unless title == ""
        obj = EditTestObject.new(edt)
      elsif type == :下拉列表
        puts "下拉列表编辑框:" + title
        cb  = WpfComboBox.new(obj.test_control)
        cb.SearchProperties["Name"] = path[-1]  unless title == ""
        obj = ListComboBoxTestObject.new(cb) 
      ......
 end

通过【属性编辑器】方法,我们可以获取各种不同类型(文本、下拉、枚举等)的属性编辑器,前面几行考虑了通过页签来定位控件,对于文本编辑类型代码片段如下:

 

 

edt = WpfEdit.new(obj.test_control)
edt.SearchProperties["Name"] = path[-1]  unless title == ""
obj = EditTestObject.new(edt)

 

  • WpfEdit
    WpfEdit是VS2010 CodedUI中支持自动化测试框架中的类库,这个类库是针对WPF框架的UI测试对象,在使用VS2010的CodedUI来做自己的自动化测试框架中可以看到需要哪些.Net程序集,这里我们先了解,我们TestObject内部模拟UI操作来测试都是通过.Net下的测试对象来做的,所以上面提出的问题【我们依靠哪些对象属性来定位对象?】就有答案了,那就是微软提供的测试框架提供哪些属性,我们的脚本就可以用哪些属性来定位对象,只是我们现在的测试框架代码实现中考虑简单方便性而只实现了基于Name来定位的,代码如:edt.SearchProperties["Name"] = XXX (其中Name是由.Net自动化测试框架Microsoft::VisualStudio::TestTools::UITesting::WpfControls提供的),如果想根据更多条件查找,则需要写额外代码来处理。如果是共性需求,则可以修改通用方法,如果是个别控件,则需要为这个控件单独生成一个TestObject继承类,并修改传递WpfXXX测试控件的SearchProperties。
  • EditTestObject
    class EditTestObject < TestObject
      #动作
      def 输入(str)
        puts "输入:" + str
        @test_control.DrawHighlight
        @test_control.Text = str
      end
    end
    
    EditTestObject是OpenTest的测试对象,它继承自TestObject,覆盖了【输入】方法。

  • TestObject
    class TestObject
    
      attr_accessor :test_control
      attr_accessor :name
    
      def initialize(test_control)
        @test_control = test_control
      end
    
      def method_missing(name, *args, &block)
        if @test_control.respond_to?(name)
          return @test_control.send(name, *args, &block)
        else
          raise  "没有定义方法:" + name.to_s
        end
      end
    TestObject是所有测试对象的基类,它的构造函数需要传入一个.Net下的测试对象(例如WpfEdit),由于实现了method_missing,所以我们可以在代码中直接写.Net下的测试对象的具体方法,如DrawHighlight。(要想明白.Net和IronRuby的交互,可以参考书籍IronRuby Unleashed
  • TestObject子类介绍
    针对不同的测试控件,我们基本上会对应从TestObject继承下来生成一个新的测试对象,如果你想支持一个新的对象,那么也应该集成TestObject生成一个新的对象。
    在编写具体查找代码时,需要注意,如果父对象是page或者TreeItem等,需要把当前的测试对象的parent置为page或者Tree、TreeItem,否则找不到。
    以下简单说明一下现在实现的一些子类:
    • CheckTestObject:勾选框
    • GridTestObject:Grid列表
    • GroupTestObject:分组对象
    • ListGridTestObject:列表Grid
    • TreeTestObject:树形控件
    • TreeItemTestObject:树节点
    • EnumTestObject:枚举下拉对象
    • ComboBoxTestObject:ComboBox控件
    • ContextMenuTestObject:弹出菜单测试对象
    • ModuleTestObject:模块
    • PageTestObject:页
    • ButtonTestObject:按钮

其他文件说明

common_func.rb:这个单元中的函数是提供给编写脚本人员使用的一些常用函数,

FindControlHelper.rb:生成测试对象的通用函数,实现方法中以AutomationId或Id来定位,如果实际查找不是这个,可以在TestObject中直接写真正的查询定位条件

mail.rb:邮件相关函数

 

推荐:你可能需要的在线电子书

 

欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]

posted on 2010-11-04 15:18  周 金根  阅读(2764)  评论(3编辑  收藏  举报

导航