-
Watir Web-Driver Element 的通用方法(2)
2013-01-15 17:48:24
- (Object) flash
修改的元素背景颜色,从而高亮该元素。browser.div(:id => "draggable").flash
- (Object) focus
将focus置于指定的元素之上。
browser.div(:id => "draggable").focus
- (Object) focused?
判断指定元素是否已经被focused。注意,不是所有元素都支持该方法,不支持的一律返回false。
browser.div(:id => "draggable").focused?
- (Object) hash
返回指定元素的哈希值
browser.div(:id => "draggable").hash
- (Object) hover
将鼠标移至指定元素的中间位置。并非所有的浏览器都支持该操作。
browser.div(:id => "draggable").hover
- (String) html
返回该元素所包含的HTML编码。
browser.button(:name, “btnK”).html
#=> “<input value =\”Google Search\” name=\”btnK\” type=\”submit\” jsaction=\”sf.chk\” >”
- (Object) inspect
返回指定元素对象的检查信息。
browser.button(:name, “btnK”).inspect
#=> “#<Watir::Button:0x..f8cf0d9 located =false selector={:name=>\”btnK\”, :tag_name=>\”button\”}>”
- (Object) parent
返回指定元素对象的父元素。
browser.button(:name, “btnK”).parent
#=> #<Watir::HTMLElement:0x16d0c6ce located=false selector={:element=>(webdriverelement)}>
- (Boolean) present?
指定元素是否在页面上存在并显示。
browser.button(:name, “btnK”).present?
#=> true
- (Object) right_click
右键点击指定元素。并非所有的浏览器都支持该方法。
browser.button(:name, “btnK”).right_click
- (Object) run_checkers
返回指定元素对象的包含的checker列表
Check_for_bad_things = Proc.new do
puts “Server Error!” if @browser.text.include?(Server error”)
end
@browser.add_checker(Check_for_bad_things)
@browser.run_checkers
#=> [#<Proc:0x1053a50@(irb):69>]
-
Watir Web-Driver Element 的通用方法(1)
2013-01-15 17:47:16
- (Object) == (other) (also: #eql?)
返回是否两个element是相同的。要注意的是是两个Object相同,不是相等。
browser.a(:id => "foo") == browser.a(:id => "foo")
#=> true
- (String) attribute_value(attribute_name)
返回元素的指定属性的值。
browser.a(:id => "foo").attribute_value ("href")
#=> "http://watir.com"
- (Watir::Browser) browser
返回当前的browser。
browser.browser
#=> #<Watir::Browser:0x..fa487467e url=”http://www.ggogle.com.hk/” title=”Google”>
- (Object) click(*modifiers)
点击当前元素,同时可以提供可选值用于复杂的点击情况,例如Ctrl+click。
element.click
element.click(:shift)
element.click(:shift, :control)
可支持的可选值有::shift, :alt, :control, :command, :meta
- (Object) double_click
双击当前元素。
browser.a(:id => "foo").double_click
- (Object) drag_and_drop_by(right_by, down_by)
拖拽元素对象到指定的位置。位置指定为目标区域的右边线和下边线。
browser.div(:id => "draggable").drag_and_drop_by (100, -200)
- (Object) drag_and_drop_on(other)
拖拽元素对象到指定的对象上。例如从左边列表拖拽一个选项到右边列表中。
a = browser.div(:id => "draggable")
b = browser.div(:id => "droppable")
a.drag_and_drop_on(b)
- (Object) driver
元素对象的driver信息。
browser.driver
#=> #<Selenium::WebDriver::Driver:0x67382c7e browser=:chrome>
- (Boolean) exists? (Also known as: exist?)
判断元素对象是否存在。
browser.a(:id => "foo") .exists?
#=> true
- (Object) fire_event(event_name)
在指定的元素上执行一个JavaScript事件。
browser.a(:id => "foo").fire_event(:click)
browser.a(:id => "foo").fire_event("mousemove")
browser.a(:id => "foo").fire_event "onmouseover"
-
如何在 Watir 中识别各种 HTML 对象(7)
2013-01-14 17:55:27
Table元素
HTML tag - <table>
可以用来定位的方法有:
Browser.table(:class, “table class”)
Browser.table(:id, “table id”)
Browser.table(:index, 0)
Browser.table(:name, “table name”)
Browser.table(:text, “table text”)
Browser.table(:xpath, “table xpath”)
Browser.table(:class=>“table class name”, :index, 0) (Mulitple Attributes)
Text_field元素
HTML tag - <input type=”password”>/<input type=”text”>
可以用来定位的方法有:
Browser.textfield(:class, “textfield class”)
Browser.textfield(:id, “textfield id”)
Browser.textfield(:index, 0)
Browser.textfield(:name, “textfield name”)
Browser.textfield(:text, “textfield text”)
Browser.textfield(:value, “textfield value”)
Browser.textfield(:xpath, “textfield xpath”)
Browser.textfield(:class=>“textfield class name”, :index, 0) (Mulitple Attributes)
Textarea元素
HTML tag - <textarea>
可以用来定位的方法有:
Browser.textarea(:class, “textarea class”)
Browser.textarea(:id, “textarea id”)
Browser.textarea(:index, 0)
Browser.textarea(:name, “textarea name”)
Browser.textarea(:text, “textarea text”)
Browser.textarea(:value, “textarea value”)
Browser.textarea(:xpath, “textarea xpath”)
Browser.textarea(:class=>“textarea class name”, :index, 0) (Mulitple Attributes)
ul元素
HTML tag - <ul>
可以用来定位的方法有:
Browser.ulist(:class, “ulist class”)
Browser.ulist(:id, “ulist id”)
Browser.ulist(:index, 0)
Browser.ulist(:name, “ulist name”)
Browser.ulist(:text, “ulist text”)
Browser.ulist(:xpath, “ulist xpath”)
Browser.ulist(:class=>“ulist class name”, :index, 0) (Mulitple Attributes)
New Browser Windows 对象
可以用来定位的方法有:
Browser.window(:href, “new window href”)
Browser.window(:title, “new window title”)
-
如何在 Watir 中识别各种 HTML 对象(6)
2013-01-14 17:54:40
Radio元素
HTML tag - <input type=”radio”>
可以用来定位的方法有:
Browser.radio(:class, “radio class”)
Browser.radio(:id, “radio id”)
Browser.radio(:index, 0)
Browser.radio(:name, “radio name”)
Browser.radio(:text, “radio text”)
Browser.radio(:value, “radio value”)
Browser.radio(:xpath, “radio xpath”)
Browser.radio(:class=>“radio class name”, :index, 0) (Mulitple Attributes)
Tr元素
HTML tag - <tr>
可以用来定位的方法有:
Browser.tr(:class, “tr class”)
Browser.tr(:id, “tr id”)
Browser.tr(:index, 0)
Browser.tr(:name, “tr name”)
Browser.tr(:text, “tr text”)
Browser.tr(:xpath, “tr xpath”)
Browser.tr(:class=>“tr class name”, :index, 0) (Mulitple Attributes)
Select_list元素
HTML tag - <select>
可以用来定位的方法有:
Browser.select(:class, “select class”)
Browser.select(:id, “select id”)
Browser.select(:index, 0)
Browser.select(:name, “select name”)
Browser.select(:text, “select text”)
Browser.select(:value, “select value”)
Browser.select(:xpath, “select xpath”)
Browser.select(:class=>“select class name”, :index, 0) (Mulitple Attributes)
Span元素
HTML tag - <span>
可以用来定位的方法有:
Browser.span(:class, “span class”)
Browser.span(:id, “span id”)
Browser.span(:index, 0)
Browser.span(:name, “span name”)
Browser.span(:text, “span text”)
Browser.span(:xpath, “span xpath”)
Browser.span(:class=>“span class name”, :index, 0) (Mulitple Attributes)
-
如何在 Watir 中识别各种 HTML 对象(5)
2013-01-14 17:51:04
Link元素
HTML tag - <link>
可以用来定位的方法有:
Browser.link(:after?, “after link”)
Browser.link(:class, “link class”)
Brower.link(:href, “link href”
Browser.link(:id, “link id”)
Browser.link(:index, 0)
Browser.link(:name, “link name”)
Browser.link(:text, “link text”)
Browser.link(:xpath, “link xpath”)
Browser.link(:class=>“link class name”, :index, 0) (Mulitple Attributes)
Map元素
HTML tag - <map>
可以用来定位的方法有:
Browser.map(:class, “map class”)
Browser.map(:id, “map id”)
Browser.map(:index, 0)
Browser.map(:name, “map name”)
Browser.map(:text, “map text”)
Browser.map(:xpath, “map xpath”)
Browser.map(:class=>“map class name”, :index, 0) (Mulitple Attributes)
P元素
HTML tag - <p>
可以用来定位的方法有:
Browser.paragraph(:class, “paragraph class”)
Browser.paragraph(:id, “paragraph id”)
Browser.paragraph(:index, 0)
Browser.paragraph(:name, “paragraph name”)
Browser.paragraph(:text, “paragraph text”)
Browser.paragraph(:xpath, “paragraph xpath”)
Browser.paragraph(:class=>“paragraph class name”, :index, 0) (Mulitple Attributes)
Pre元素
HTML tag - <pre>
可以用来定位的方法有:
Browser.pre(:class, “pre class”)
Browser.pre(:id, “pre id”)
Browser.pre(:index, 0)
Browser.pre(:name, “pre name”)
Browser.pre(:text, “pre text”)
Browser.pre(:xpath, “pre xpath”)
Browser.pre(:class=>“pre class name”, :index, 0) (Mulitple Attributes)
-
如何在 Watir 中识别各种 HTML 对象(4)
2013-01-14 17:49:50
Head元素
HTML tag - <h1><h2><h3><h4><h5><h6>
可以用来定位的方法有:
Browser.head(:class, “heading class”)
Browser.head(:id, “head id”)
Browser.head(:index, 0)
Browser.head(:name, “head name”)
Browser.head(:text, “head text”)
Browser.head(:xpath, “head xpath”)
Browser.head(:class=>“head class name”, :index, 0) (Mulitple Attributes)
Hidden元素
HTML tag - <hidden>
可以用来定位的方法有:
Browser.hidden(:class, “hidden class”)
Browser.hidden(:id, “hidden id”)
Browser.hidden(:index, 0)
Browser.hidden(:method, “hidden method”)
Browser.hidden(:name, “hidden name”)
Browser.hidden(:text, “hidden text”)
Browser.hidden(:value, “hidden value”)
Browser.hidden(:xpath, “hidden xpath”)
Browser.hidden(:class=>“hidden class name”, :index, 0)(Mulitple Attributes)
Image元素
HTML tag - <img>
可以用来定位的方法有:
Browser.image(:alt, “image alt”)
Browser.image(:class, “image class”)
Browser.image(:for,”image for”)
Browser.image(:id, “image id”)
Browser.image(:index, 0)
Browser.image(:name, “image name”)
Browser.image(:src,”image src”)
Browser.image(:text, “image text”)
Browser.hidden(:value, “hidden value”)
Browser.hidden(:xpath, “hidden xpath”)
Browser.hidden(:class=>“hidden class name”, :index, 0)(Mulitple Attributes)
Label元素
HTML tag - <label>
可以用来定位的方法有:
Browser.label(:class, “label class”)
Browser.label(:id, “label id”)
Browser.label(:index, 0)
Browser.label(:name, “label name”)
Browser.label(:text, “label text”)
Browser.label(:xpath, “label xpath”)
Browser.label(:class=>“label class name”, :index, 0) (Mulitple Attributes)
Li元素
HTML tag - <li>
可以用来定位的方法有:
Browser.li(:class, “li class”)
Browser.li(:id, “li id”)
Browser.li(:index, 0)
Browser.li(:name, “li name”)
Browser.li(:text, “li text”)
Browser.li(:xpath, “li xpath”)
Browser.li(:class=>“li class name”, :index, 0) (Mulitple Attributes)
-
如何在 Watir 中识别各种 HTML 对象(3)
2013-01-14 17:48:45
Div元素
HTML tag - <div>
可以用来定位的方法有:
Browser.div(:class, “div class”)
Browser.div(:id, “div id”)
Browser.div(:index, 0)
Browser.div(:name, “div name”)
Browser.div(:text, “div text”)
Browser.checkbox(:xpath, “div xpath”)
Browser.checkbox(:class=>“div class name”, :index, 0) (Mulitple Attributes)
File_field元素
HTML tag - <input type=”file”>
可以用来定位的方法有:
Browser.filefield(:class, “file class”)
Browser.filefield(:id, “file id”)
Browser.filefield(:index, 0)
Browser.filefield(:name, “file name”)
Browser.filefield(:title, “file title”)
Browser.filefield(:value, “file value”)
Browser.filefield(:xpath, “file xpath”)
Browser.filefield(:class=>“file class name”, :index, 0) (Mulitple Attributes)
Form元素
HTML tag - <form>
可以用来定位的方法有:
Browser.form(:action, “form. action”)
Browser.form(:class, “file class”)
Browser.form(:id, “form. id”)
Browser.form(:index, 0)
Browser.form(:method, “form. method”)
Browser.form(:name, “form. name”)
Browser.form(:xpath, “form. xpath”)
Browser.form(:class=>“form. class name”, :index, 0) (Mulitple Attributes)
Frame元素
HTML tag - <frame>/<iframe>
可以用来定位的方法有:
Browser.frame(:id, “frame. id”)/
Browser.frame(:index, 0)
Browser.frame(:name, “frame. name”)
Browser.frame(:src, “frame. src”)
Browser.frame(:text, “frame. text”)
Browser.frame(:id=>“frame. id”, :index, 0) (Mulitple Attributes)
-
如何在 Watir 中识别各种 HTML 对象(2)
2013-01-14 17:47:48
Area元素
HTML tag - <area>
可以用来定位的方法有:
Browser.area(:class, “area class name”)
Browser.area(:id, “area id”)
Browser.area(:index, 0)
Browser.area(:name, “area name”)
Browser.area(:text, “area text”)
Browser.area(:xpath, “area xpath”)
Browser.area(:class=>“area class name”, :id=>“area id”, :index, 0) (Mulitple Attributes)
Button元素
HTML tag - <button>/<input type=”button”>/<input type=”image”>/<input type=”reset”>
/<input type=”submit”>
可以用来定位的方法有:
Browser.button(:alt, “alt button name”)
Browser.button(:class, “button class”)
Browser.button(:id, “button id”)
Browser.button(:index, 0)
Browser.button(:name, “button name”)
Browser.button(:src, “image button src”) (only for type is image)
Browser.button(:text, “button text”)
Browser.button(:value, “button default value”)
Browser.button(:xpath, “button xpath”)
Browser.button(:class=>“button class name”, :id=>“button id”, :index, 0) (Mulitple Attributes)
Cell元素
HTML tag - <td>
可以用来定位的方法有:
Browser.td(:alt, “alt button name”)
Browser.td(:class, “td class”)
Browser.td(:id, “td id”)
Browser.td(:index, 0)
Browser.td(:name, “td name”)
Browser.td(:text, “td text”)
Browser.button(:xpath, “td xpath”)
Browser.button(:class=>“td class name”, :id=>“td id”, :index, 0) (Mulitple Attributes)
Checkbox元素
HTML tag - <input type=”checkbox”>
可以用来定位的方法有:
Browser.checkbox(:class, “checkbox class”)
Browser.checkbox(:id, “checkbox id”)
Browser.checkbox(:index, 0)
Browser.checkbox(:name, “checkbox name”)
Browser.checkbox(:text, “checkbox text”)
Browser.checkbox(:value, “checkbox value”)
Browser.checkbox(:xpath, “checkbox xpath”)
Browser.checkbox(:class=>“checkbox class name”, :index, 0) (Mulitple Attributes)
-
如何在 Watir 中识别各种 HTML 对象(1)
2013-01-14 17:43:29
Watir Web-driver 支持的 HTML elements 如下所列:
-
Cucubmer 没有when
2013-01-14 10:45:51
呵呵,今天突然想试试看,如果没有when的cucubmer是不是还能跑的通。这是原始文件:# language: zh-CN功能:加法为了避免一些愚蠢的错误作为一个数学白痴我希望有人告诉我数字相加的结果场景: 两个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7当我按相加按钮那么我应该在屏幕上看到的结果是13场景: 三个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7而且我已经在计算器里输入1当我按相加按钮那么我应该在屏幕上看到的结果是14相应的define step文件是:# encoding: utf-8begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; endrequire 'cucumber/formatter/unicode'$:.unshift(File.dirname(__FILE__) + '/../../lib')require 'calculator'Before do@calc = Calculator.newendAfter doendGiven /我已经在计算器里输入(\d+)/ do |n|@calc.push n.to_iendWhen /我按(.*)按钮/ do |op|if p == '相加'@result = @calc.send "add"endendThen /我应该在屏幕上看到的结果是(.*)/ do |result|@result.should == result.to_fend这是原始例子 可以正常跑通:2 scenarios (2 passed)9 steps (9 passed)0m0.016s这是没有when的文件:# language: zh-CN功能:加法为了避免一些愚蠢的错误作为一个数学白痴我希望有人告诉我数字相加的结果场景: 两个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7而且我按相加按钮那么我应该在屏幕上看到的结果是13场景: 三个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7而且我已经在计算器里输入1而且我按相加按钮那么我应该在屏幕上看到的结果是14相应修改的step define文件是:# encoding: utf-8begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; endrequire 'cucumber/formatter/unicode'$:.unshift(File.dirname(__FILE__) + '/../../lib')require 'calculator'Before do@calc = Calculator.newendAfter doendGiven /我已经在计算器里输入(\d+)/ do |n|@calc.push n.to_iendGiven /我按(.*)按钮/ do |op|if p == '相加'@result = @calc.send "add"endendThen /我应该在屏幕上看到的结果是(.*)/ do |result|@result.should == result.to_fend也可以正常跑通:2 scenarios (2 passed)9 steps (9 passed)0m0.016s其实为了更好的能够分隔Given和Then,还是加一个什么都不做的When比较好:# language: zh-CN功能:加法为了避免一些愚蠢的错误作为一个数学白痴我希望有人告诉我数字相加的结果场景: 两个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7而且我按相加按钮当我开始验证结果那么我应该在屏幕上看到的结果是13场景: 三个数相加假如我已经在计算器里输入6而且我已经在计算器里输入7而且我已经在计算器里输入1而且我按相加按钮当我开始验证结果那么我应该在屏幕上看到的结果是14相应的step define 文件是:# encoding: utf-8begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; endrequire 'cucumber/formatter/unicode'$:.unshift(File.dirname(__FILE__) + '/../../lib')require 'calculator'Before do@calc = Calculator.newendAfter doendGiven /我已经在计算器里输入(\d+)/ do |n|@calc.push n.to_iendGiven /我按(.*)按钮/ do |op|if p == '相加'@result = @calc.send "add"endendWhen /我开始验证结果/ do ||puts '我开始验证结果'endThen /我应该在屏幕上看到的结果是(.*)/ do |result|@result.should == result.to_fend正常跑通:2 scenarios (2 passed)11 steps (11 passed)0m0.016s说明,cucumber是完全按照关键词+行去进行正则表达式的匹配的,各个步骤之间并没有逻辑关系,只是通过你的组织,实现了产品本身的业务逻辑。 -
Watir在cucumber上的应用
2013-01-10 15:12:15
接着昨天的table搞,那个table从上倒下一个value,id都没有,而且是动态的,偏偏还要像这样选择匹配行的链接进行操作。后来研究了半天发现element有个parent的方法,所以,简单了先匹配“地图楼层”这个td,然后返回该td的parent,即该行的tr,然后再index到该tr的第二个td,就可进行操作了:$browser.td(:text, '3333').parent.[](1).link(:text, '修改').click看来什么东西想精通,就得多用啊。然后根据cucumber的架构,搞了一些测试用例:在feature 文件中是这样的:# language: zh-CN功能:楼层管理作为一个管理人员我能够进行楼层管理场景: Case 1 - 验证界面元素(S2-ST-JBXXGL-LCGL-0001)假如进入基本信息管理界面当转入楼层管理界面那么我可以看到楼层编号并且我可以看到楼层名称并且我可以看到修改并且我可以看到删除并且我可以看到添加楼层场景: Case 2 - 正常添加楼层(S2-ST-JBXXGL-LCGL-0002)假如进入基本信息管理界面而且我进入楼层管理界面而且点击添加楼层#而且我已经在楼层编号里输入001而且我已经在楼层名称里输入地下一层当点击添加楼层那么我应该在楼层管理界面#并且我可以看到001并且我可以看到地下一层然后再初期的define step中有这样的两行:Given /进入(.*)界面/ do |module_name|$autotest.navigate_to_module(module_name)endWhen /进入(.*)界面/ do |module_name|$autotest.navigate_to_module(module_name)end然后很和谐的就报错了,cucumber在匹配假如进入基本信息管理界面当进入楼层管理界面这两行的时候,神经错乱了,只好改成:假如进入基本信息管理界面当转入楼层管理界面和Given /进入(.*)界面/ do |module_name|$autotest.navigate_to_module(module_name)endWhen /转入(.*)界面/ do |module_name|$autotest.navigate_to_module(module_name)end看来用中文写测试用例,也够费脑子的。经过一个模块的实验,发现435个手工测试用例,大概要定义45个step,然后需要定义56个functional不过,发现剩下的2000多个手工测试用例,需要新加的step应该不会超过20个 定义的功能也不会超过100个,就完成了所有的手工测试测试用例----》自动化测试用的转变哈哈 还是很厉害的,执行了20条case,大概一条在45秒, 就算一分钟, 2500个测试用里 差不多5个小时也能执行一遍,而手工测试用例,大概需要500个人/时所以,使用cucumber进行自动化测试,首先需要高质量的测试用例,然后还要进行挑选,没必要所有的测试用例都进行自动化。 -
Watir的应用
2013-01-09 14:41:26
SDD解决后,问题还是集中在Watir-webdriver的上应用。现在每天记录一点在开发过程中碰到的问题,以及解决的方法1. 支持中文因为要测试的网站是中文的,一开始搞了好久老是出错,后来偶然发现在Cucumber的step define 文件中,抬头的第一行就是: #encoding:utf-8。 copy过来,果然好使,哈哈。2. 企图添加assert发现老是报错,后来回头老老实实的看了一遍文档发现是这样的:首先 需要 require 'test/unit'其次 需要 class TC_myTest < Test::Unit::TestCase然后 需要 def mytestcase最后 把你的测试代码置入,就可以加assert了3. 操作页面上一个table常规的操作很简单:- $browser.table(:id=>"t1").rows #所有的行
- $browser.table(:id=>"t1").[](0) #获取第一行
- $browser.table(:id=>"t1").[](0).cells #获取第一行的所有单元格
- $browser.table(:id=>"t1").[](0).[](0) #获取第一行第一列的单元格
偏偏碰上了个巨懒的程序员,代码中就一行: <table width="90%">研究了半天,只要用最笨的方法:$browser.table(:index, 7).rows一个个数了半天,回头要求开发加上 -
SDD开发实例(6)
2012-12-07 16:32:57
经过一周的练习,发现最大的问题就是QA开发的test case质量不高,很多人把测试用例写的跟流程文档或者需求文档很类似。其实这个问题由来已久,很多QA都觉得写QA很简单,翻来覆去就是那几种正交,等价类之类的,其实产品的质量基于测试的质量,而测试的质量依赖于test case的质量。在SDD中,我们是基于Story去开发测试用例,所以我们要明确出来的是我们系统中存在哪些对象,这些对象有哪些方法可以被调用,一个data-driven的书写标准,不单能让我们获得最小的step集合,从而能够尽量的代码复用,而且能够很清楚的表明这些对象所自有的方法(inside)和互相传递数据的方法(outside),从而获得足够高的cover率和尽可能低的duplicate coverage。我们以下面为例子:在界面中,有很多流程都是在一个手机号text field中输入不同的数据,所以Qa们都是根据流程去书写这些测试用例:2. 不输入手机号
13. 输入手机号
2. 输入超过20个字符的手机号
2. 输入特殊字符的手机号信息
实际上,所有的这些测试步骤都可以用一个步骤代替
输入手机号XXX
我们只需要在test description分别说明,就能让其他测试人员明白你要干什么
这样 test description 就分别为:
手机号码为空
输入正常手机号
输入超过11个数字的手机号
输入特殊字符的手机号
而依据data-driven方式书写的测试用例步骤为:
(XXX为该条语句的输入值)
输入手机号(空)
输入手机号13800138000
输入手机号1234567890123
输入手机号123AAA
从上面我们可以看出,良好的书写格式和习惯,实际上使你的测试用例不但更加健壮,而且易于进行automation。
很多项目的automation进展困难,就是因为依据这些手工测试脚本创建自动化脚本过于复杂化,重新书写测试用例又代价太高,就在这进退为难的过程中,从而失败的推广自动化测试。
-
SDD开发实例(5)
2012-12-07 16:30:27
很多人可能对正则表达式不太清楚,而我们要在Define steps中使用这些正则表达式 所以 给出这些常用的:正则表达式全集
字符
描述
\
将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\\”匹配“\”而“\(”则匹配“(”。
^
匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$
匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*
匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
+
匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?
匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
{n}
n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}
n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}
m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?
当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
.
匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern)
匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。
(?:pattern)
匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)
正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)
正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?<=pattern)
反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)
反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y
匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。
[xyz]
字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]
负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z]
字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z]
负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b
匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B
匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx
匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d
匹配一个数字字符。等价于[0-9]。
\D
匹配一个非数字字符。等价于[^0-9]。
\f
匹配一个换页符。等价于\x0c和\cL。
\n
匹配一个换行符。等价于\x0a和\cJ。
\r
匹配一个回车符。等价于\x0d和\cM。
SDD开发实例(4)
2012-12-04 17:26:55
首先,我们看看从客户方面得到的测试用例case 1: 第一次正常开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入该卡号对应的”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 返回”定位卡管理“界面,刚输入的卡号可以在该界面查询case 2: 不输入任何信息”开卡“进入”定位卡管理“界面"1. 点击”开卡“2. 不输入任何信息3. 点击开卡4. 输入正确的”卡号“5. 不输入”激活码“6. 点击”开卡“7. 输入正确的卡号、激活码、不输入”初始金额“8. 点击开卡"结果:"3. 输入框为”红框“提醒→”请输入卡号“,如图6. 输入框为”红框“提醒→”请输入激活码“8.1 界面弹出提示”开卡成功“8.2 界面返回”定位卡管理“信息页面8.3 初始金额默认为0"case 3: 输入已存在的卡号开卡已存在定位卡信息"1. 点击”开卡“2. 输入已存在的”卡号“3. 输入该卡号对应的”激活码“4. 点击”开卡“"结果:4. 提示→”该卡号已存在“case 4: 输入不符合格式标准的卡号开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入错误格式的”卡号“3. 输入任意”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”卡号有误“case 5: 超长字符的卡号开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入超长的”卡号“3. 输入正确的”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”卡号有误“case 6: 特殊字符卡号开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入特殊字符的”卡号“3. 输入正确的”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”卡号有误“case 7: 取消按钮验证进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入正确的”激活码“4. 输入”初始金额300“5. 点击”取消“"结果:"5.1 界面返回”定位卡管理“信息页面5.2 不增加新的定位卡信息"case 8: 输入正确的卡号,错误的激活码开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入错误格式”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”激活码有误“(待议)case 9: 输入超长激活码开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入超长的”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”激活码有误“(待议)case 10: 特殊字符激活码开卡进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入特殊字符”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→”激活码有误“(待议)case 11: 卡号正确定性验证进入”定位卡管理“界面"1. 点击”开卡“2. 输入正确的”卡号“3. 输入不匹配的”激活码“4. 输入”初始金额300“5. 点击”开卡“"结果:5. 提示→“卡号和激活码不匹配”(待议)依照以上的测试用例 书写feature文件:# language: zh-CN功能:开卡作为一个管理人员我能够给新用户激活一张新定位卡场景: Case 1 - 正常开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且刚输入的卡号可以在该界面查询场景: Case 2 - 不输入任何信息“开卡”假如点击开卡按键#而且我已经在卡号框里输入#而且我已经在激活码框里输入#而且我已经在初始金额框里输入当我点击开卡按键那么我应该在定位卡管理界面并且提醒请输入卡号并且提醒请输入激活码场景: Case 3 - 输入已存在的卡号开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒该卡号已存在场景: Case 4 - 输入不符合格式标准的卡号开卡假如点击开卡按键而且我已经在卡号框里输入错误卡号1-2-3而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒卡号有误场景: Case 5 - 输入超长字符的卡号开卡假如点击开卡按键而且我已经在卡号框里输入错误卡号aaa而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒卡号有误场景: Case 6 - 输入特殊字符的卡号开卡假如点击开卡按键而且我已经在卡号框里输入错误卡号@#¥而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒卡号有误场景: Case 7 - 取消开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击取消按键那么我应该在定位卡管理界面并且不增加新的定位卡信息场景: Case 8 - 输入正确的卡号,错误的激活码开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入错误激活码aaa而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒激活码有误场景: Case 9 - 输入超长激活码开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入错误激活码aaaaaaa而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒激活码有误场景: Case 10 - 特殊字符激活码开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入错误激活码aaaa@#$而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒激活码有误场景: Case 11 - 卡号正确定性验证假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入错误激活码123而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒激活码有误而与之关联的define_step 文件为:# encoding: utf-8begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; endrequire 'cucumber/formatter/unicode'require "watir-webdriver"$:.unshift(File.dirname(__FILE__) + '/../../lib')Before do#$page=Watir::Browser.new:ff#Login_action#Navigate_to_manage_card_actionendAfter do#Logout_actionendGiven /^点击(.*)按键$/ do |button|if button =="开卡"#$page.button(:name, "开卡").clickendendGiven /^我已经在卡号框里输入(\d+)$/ do |card_number|#$page.text_field(:name,"card_number").set(card_number)endGiven /^我已经在卡号框里输入错误卡号(.*)$/ do |card_number|#$page.text_field(:name,"card_number").set(card_number)endGiven /^我已经在激活码框里输入(\d+)$/ do |act_number|#$page.text_field(:name,"act_number").set(act_number)endGiven /^我已经在激活码框里输入错误激活码(.*)$/ do |act_number|#$page.text_field(:name,"act_number").set(act_number)endGiven /^我已经在初始金额框里输入(\d+)$/ do |ini_money|#$page.text_field(:name,"money").set(ini_money)endWhen /^我点击(.*)按键$/ do |button_name|if button_name =="开卡"#$page.button(:name, "开卡").clickelsif button_name == "消卡"#do cancelendendThen /^我应该在定位卡管理界面$/ do#page_on_manage_card_pageendThen /^刚输入的卡号可以在该界面查询$/ do#card_number_can_search_outendThen /^不增加新的定位卡信息$/ do# logendThen /^提醒(.*)$/ do |message|if message =="请输入卡号"# logendif message =="请输入激活码"# logendif message == "该卡号已存在"#logendif message =="卡号有误"#logendif message =="激活码有误"#logendend现在我们对这些进行分析:首先:我们需要在before do里面做一系列的操作1. login2. 进入”定位卡管理“界面在 after do 里面 可考虑的是1. logout然后 我们看这些具体的实例很显然 case 1 的结果判断过于复杂 是通过一系列的查询和匹配工作来确定卡是否被正确的开通。这个代码,我们完全可以跟查询模块的代码进行复用。只学要按照刚输入的卡号去查询,能够显示在查询列表中,表示该卡已经激活。(隐含,也许是需要获得该卡的状态)另外 有些case是判断输入的开号是否超长 实际上 我们不需要去判断一个超长的卡号是否返回正确的信息,我们只需要判断一下该文本域的length即可另外 对于错误的输入,错误的格式输入,特殊字符的输入 都是同一个类型的检验所以我们可以使用tag 然后在回归测试中 只需要执行一条即可对于激活码和卡号不匹配 其实是等同于错误的卡号/错误的激活码最后 就是所有的结果判断都不是明确的判断 容易引起歧义所以 通过这个过程我们可以将case 重新组织为:# language: zh-CN功能:开卡作为一个管理人员我能够给新用户激活一张新定位卡场景: Case 1 - 正常开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且刚输入的卡号可以在该界面查询场景: Case 2 - 不输入任何信息“开卡”假如点击开卡按键#而且我已经在卡号框里输入#而且我已经在激活码框里输入#而且我已经在初始金额框里输入当我点击开卡按键那么我应该在定位卡管理界面并且提醒请输入卡号并且提醒请输入激活码场景: Case 3 - 输入已存在的卡号开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒该卡号已存在场景: Case 4 - 输入不符合格式标准的卡号开卡假如点击开卡按键而且我已经在卡号框里输入错误卡号1-2-3而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒卡号有误场景: Case 7 - 取消开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入999而且我已经在初始金额框里输入300当我点击取消按键那么我应该在定位卡管理界面并且不增加新的定位卡信息场景: Case 8 - 输入正确的卡号,错误的激活码开卡假如点击开卡按键而且我已经在卡号框里输入123而且我已经在激活码框里输入错误激活码aaa而且我已经在初始金额框里输入300当我点击开卡按键那么我应该在定位卡管理界面并且提醒激活码有误SDD开发实例(3)
2012-12-04 15:14:43
cucumber是一个SDD框架,使用Gherkin语言。当你编写一个feature文件的时候,会用到很多Gherkin语言里特定的关键字,主要包括下这面些:• Feature - 功能• Background - 背景• Scenario - 场景• Scenario outline - 场景• Scenarios (or examples) - 实例• Given - 假如• When - 当• Then - 那么• And (or but) -并且/但是• | (用来定义表格)• """ (定义多行字符串)• # (注释)每一个feature文件必须以关键字Feature开始,且紧跟着一个冒号和一个描述。一个feature文件里面可以有很多个Scenario,一个Scenario就是一个具体的你想要测试的功能点关键字Given, When, Then, And 和 But用来指示一个Scenario中的步骤。在define steps中 我们可以使用正则表达式Given /我已经在计算器里输入(\d+)/ do |n|@calc.push n.to_iendThen /我应该在屏幕上看到的结果是(.*)/ do |result|@result.should == result.to_fend(\d+) 用于匹配数字 例如上例 将输入后面的数字赋值给n(.*) 用于匹配字符 例如上例 将结果是后面的字符串赋值给resultSDD开发实例(2)
2012-12-04 14:20:39
敏捷开发,基本上属于现在软件开发的主潮流。但是很多人还没有真正的理解它。敏捷开发并不是指特定某种开发模式,而是概指所有符合以下特性的任意开发模式:通过更加频繁有效的交流,更早的发现问题,解决问题。
基本上主流的敏捷方法,都是依赖于测试的质量,所以测试驱动开发(Test Driven Development)可以称为敏捷开发的基柱。TDD的思想就是通过测试活动来驱动开发活动从而达到将客户需求能够精确的反应到开发过程中,从而降低开发的成本。在这过程中,最典型的特点就是先完成测试程序,在实现能够通过测试程序验收的代码,经过反复迭代,从而使得产品顺利发布。
在TDD的进化过程中,出现了一个更加有趣的BDD分支,即行为驱动开发(Behavior. Driven Development)。在不断的迭代过程和OO思想影响下,我们会发现有很多产品的设计思路从总体来看就是一些特定对象的行为集合。我们的产品,就是不断的完善这些对象的行为。因此,TDD的真正价值就在于能够更加清晰有效的对对象的行为进行分解实现。对于拥有BA的开发团队,一般将用户的需求描述为产品的设计理念,例如UML的介入,大量的流程图和关系图的出现,将简单的需求复杂化,模块化。那么为什么不直接从真正用户如何使用产品入手呢?这样我们直接就从客户的角度考虑,如何设计产品,从而使其的行为能够符合用户的习惯(UE)和流程。BDD就是依据这一理念出现了。
BDD通过定义用户和开发团队所共同接受的“通用语言”来实现对接。从而避免双方表达不一致的出现,导致产品开发出现产品功能偏差。
而SDD(Story Driven Development)就是对BDD的一种具体的实现。使用Story来定义用户和系统行为,从而达到测试驱动开发的目的。
一般常用的story格式如下:
Story:subject
As a (role)
In order to (behavior)
So that (benefit)
然后通过一系列的场景来验证该story的实现。
如果我们把AC 看作test case outline,这些scenario 就等同于一个个我们要使用的test case。
一个scenario一般是如下格式:
Scenario 1: subject
Given 【上下文】
And 【更多的上下文或步骤】
When 【要完成的事件】
Then 【期望的结果】
And 【更多的期望结果】
场景很容易去理解,Given 和 And 给出了一些的上下文,就等同于测试用例中的precondition和steps。 When给出的就是最后要验证的系统的behavior或者要验证的操作。Then和And给出的是这个behavior或者操作的正确期望结果。
Story, As a, In order to, So that,Scenario,Given,And,When,Then这些就是我们在SDD这种模式中定义的用户和开发团队所共同接受的“通用语言”的一些关键词。SDD框架能够理解和解释这些关键词从而使得SDD得到实现。
而Cucumber就是一个实现的SDD框架。它通过feature文件来保存story和相关的scenario。使用任意支持的语言来完成scenario中的steps与自动化测试脚本的mapping。然后就可以在执行feature文件时,直接执行相关的自动化测试脚本。
SDD开发实例(1)
2012-12-04 10:01:52
现在越来越多的项目采用敏捷开发模式。不管是真的敏捷,还是假的敏捷,总之接触到的国内项目基本上都是挂着羊头卖狗肉。不过不管怎么着,很多人越来越熟悉user story。其实,作为一个测试人员,如果只会单纯的测试将来的路只会越来越窄,复合型人才才是最终的目标。所以,一个QA,如果想将来有所成就,而不是混吃等死,最起码应该具备BA,QA,Automation Development,Configuration Admin,Network topology 等方面的相关知识。本篇开始,我们就讨论一下一个QA怎么去充当一个BA的角色。那就是SDD开发模式。SDD,Story Driven Development,是以user story为驱动方式的开发模式,主要是:BA(QA)书写user story =》QA 实现测试用例 =》测试 =》发布=》Dev 开始实现代码所以从上可知,主要是QA在Dev完成代码开发的同时完成了测试用例,从而并发节省时间。一般来说SDD都是以自动化测试为住。我们就拿一个ruby+cucubmer+watir的自动化框架来作为实例。怎么去安装这些工具很简单,我们就不多说了,自己google吧。首先我们要理解cucubmer实现SDD的方法:1. 书写user story 和每个story所可能出现的scenario2. 将scenario的每个step通过正则表达式来map到自动化测试脚本3. 实现自动化测试脚本按上面的步骤 我们现在举一个实例现在有一个俱乐部的会员系统,能实现的功能有:基本信息管理,积分管理,产品管理和机构管理在基本信息管理中,我们可以开卡,删卡和改卡那么我们就可以有如下user storyuser story 1:作为一个信息管理人员我可以开通一个新的会员卡user story 2:作为一个信息管理人员我可以修改一个指定的会员卡user story 3:作为一个信息管理人员我可以删除一个指定的会员卡我们拿user story 1来进行scenario的描述user story 1:作为一个信息管理人员我可以开通一个新的会员卡scenario 1:假如我已经输入了新的会员卡卡号123并且输入了卡号对应的激活码999并且输入了初始金额500当我点击开卡按键时系统报告新卡正确开通scenario 2:假如我输入了卡号对应的激活码999并且输入了初始金额500当我点击开卡按键时系统报错需要输入用户卡号scenario 3:假如我已经输入了新的会员卡卡号123并且输入了初始金额500当我点击开卡按键时系统报错需要输入激活码scenario 4:假如我已经输入了新的会员卡卡号123并且输入了卡号对应的激活码999当我点击开卡按键时系统报错需要输入初始金额scenario 5:假如我已经输入了新的会员卡卡号123并且输入了卡号对应的激活码000并且输入了初始金额500当我点击开卡按键时系统报错错误的激活码scenario 6:假如我已经输入了新的会员卡卡号1234并且输入了卡号对应的激活码000并且输入了初始金额500当我点击开卡按键时系统报错卡号已经使用我们可以研究一下上面的scenario,simple的步骤,或者说唯一的步骤有我已经输入了新的会员卡卡号#d (#d 代表卡号)我输入了卡号对应的激活码#d (#d 代表激活码)我输入了初始金额#d (#d 代表金额)我点击开卡按键系统报告新卡正确开通系统报错错误的激活码/需要输入初始金额/需要输入激活码/卡号已经使用/需要输入用户卡号也就说 我只需要把以上的步骤进行整合,就能用如下语句描述scenario 1:假如我输入了123在会员卡卡号并且我输入了999在激活码并且我输入了500在初始金额当我点击开卡按键系统显示信息新卡正确开通scenario 2:假如我输入了999在激活码并且我输入了500在初始金额当我点击开卡按键系统显示信息需要输入用户卡号scenario 3:假如我输入了123在会员卡卡号并且我输入了500在初始金额当我点击开卡按键系统显示信息需要输入激活码scenario 4:假如我输入了123在会员卡卡号并且我输入了999在激活码当我点击开卡按键系统显示信息需要初始金额scenario 5:假如我输入了123在会员卡卡号并且我输入了000在激活码并且我输入了500在初始金额当我点击开卡按键系统显示信息错误的激活码scenario 6:假如我输入了1234在会员卡卡号并且我输入了000在激活码并且我输入了500在初始金额当我点击开卡按键系统显示信息已使用的会员卡这样,这些就可以存储在一个properties文件中然后 我们define这些stepGiven /我输入了#d在会员卡卡号/ then docustomer_number.entry(#d)endGiven /我输入了#d在激活码/ then docustomer_actcode.entry(#d)endGiven /并且我输入了#d在初始金额/ then docustomer_inimoney.entry(#d)endGiven /当我点击#s按键/ then dobutton(:value, #s).clickendGiven/ 系统显示信息#s/ then domessage.verify(#s)end这样 我们就完成了每个自然语言描述的步骤对应的自动化测试脚本的步骤然后 我们就可以去实现这些自动化步骤,即使我们不知道最后的代码如何,但是依据我们的自动化测试框架,我们就可以开始构建这些自动化测试代码Module New_Customer_Carddef customer_number.entry(no)$page.text_field(:value, customer number).set(no)end......def message.verify(message)if case 1 then message == "新卡正确开通"...end当然 你也可以把你的代码构建的更加简练:在define 步骤中:Given /我输入了#d在#s/ then docustomer.entry(#d,#s)end在自动化测试脚本:def customer.entry(number_value,field_label)$page.text_field(:vaule, field_label).set(number_value)end好了 现在大家大概能明白 如何使用cucumber去实现SDD了,我们接下来将会详细的进行分析和实现。测试用例能带来的(测试人生系列之六)
2012-08-02 16:47:39
通过测试用例,我们都能获得些什么呢?1. 测试团队的质量判断。例如,测试用例的覆盖率。我们只需要去把所有的valid的功能bug去做一个分析,用所有在测试用例覆盖范围之外的bug数/总bug数,就可以作为测试用例覆盖率使用。一个良好的测试团队,这个覆盖率应该在80%以上。2. 测试人员的质量判断。一个测试人员,最重要的是测试用例的质量,而不是发现的bug的多少。3. 提高开发代码的质量。选择高severity和priority的测试用例,给开发人员进行smoke testing。从而使得进入测试阶段的代码已经避免了大部分P1和P2的bug存在。提高了测试的效率,减少了测试的资源消耗。4. 合理的制定测试计划。在制定功能测试阶段的计划,需要的人力资源,可以通过测试用例的执行平均效率来估算。从而得出大致的测试跨度。5. 通过对测试文档的共同review,可以让BA能够确认他们设计和需求分析转换的效率。开发人员能够更详细细致的了解所要开发的模块。6. 通过测试用例的complete rate,failed rate等,管理层可以很好的跟踪项目的质量状况和进度。7. 通过测试用例的分析,可以避免overlap区域测试用例的缺失。8. 最终用户可以使用测试用例熟悉产品。9. Tech writer使用测试用例来书写用户手册是产品说明。10. 开发人员通过bug相关的测试用例能够更快的发现问题和更好的修复问题,减少带来的间接影响导致的新bug。11. 配置管理人员根据测试用例来更有效率的管理测试资源和环境。12. support人员可以根据测试用例来对客户进行更加有效的支持。QA的核心价值(测试人生系列之五)
2012-08-02 09:23:16
任何事物都有一个核心,QA也有自己的独特的核心价值。那么这个核心价值是什么呢?我认为就是测试用例。测试用例作为QA的核心价值,起到了如下的作用:1.产品质量的评判依据。一个产品的质量到底如何,在release之前,我们需要一个风向标来判断是否可以进行release。对一个健康的项目来说,这个风向标一般都是所有的测试用例已经处于pass的状态。2.需求确认的载体。当BA人员对客户的需求进行分析,总结和形成文档后,如何保证需求能够被真实的实现?BA部门就是对测试用例进行审核,通过测试用例的分析,来确保需求实现的完整度。3. 开发的自我分析的依据。当测试用例完成后,开发阶段往往还在进行中。开发人员在完成单元测试和集成测试后,如果利用测试用例对自己的模块进行冒烟测试,那么即增加了开发提交给测试的代码的质量,又减少了项目的整体反转时间。从而能够把工作强度和风险管理压制在合理的成度。4. 测试计划的基石。对于产品的测试计划,首要的依据就是测试用例。需要根据测试用例来填写时间表,进度表,资源表,风险表等等。而且一个计划完成之后,需要进行不停动态更新,依据也是测试用例的状态分析结果。5. 管理的对象。对于项目测试进行管理,各种报告的形成,都是来源于测试用例的各种分析。6. 工作的内容。测试人员的主要工作内容就是进行测试用例的编写,审核,执行,分析。7. 培训的资料。测试用例是最简单,最直接,最有效的用户培训资料。产品的使用文档,用户说明等等都是tech writer基于测试用例进行升华的。8. 团队的桥梁。测试用例作为一个唯一的桥梁连接着最终用户,需求人员,设计人员,开发人员,管理人员,测试人员,过程控制人员,文档人员,资源管理人员,支持人员,销售人员等所有项目有关人员。所以,测试用例的质量基本上是产品质量的唯一决定因素。作为QA的核心价值,是我们主要目的。标题搜索
我的存档
数据统计
- 访问量: 147457
- 日志数: 185
- 文件数: 6
- 建立时间: 2007-08-06
- 更新时间: 2015-01-06
清空Cookie - 联系我们 - 51Testing软件测试网 - 交流论坛 - 空间列表 - 站点存档 - 升级自己的空间
Powered by 51Testing © 2003-2021
沪ICP备05003035号