发布新日志

  • 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

    常规的操作很简单:
    1. $browser.table(:id=>"t1").rows #所有的行  
    2. $browser.table(:id=>"t1").[](0) #获取第一行  
    3. $browser.table(:id=>"t1").[](0).cells #获取第一行的所有单元格  
    4. $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)?可以匹配doesdoes中的do?等价于{0,1}

    {n}

    n是一个非负整数。匹配确定的n次。例如,o{2}不能匹配Bob中的o,但是能匹配food中的两个o

    {n,}

    n是一个非负整数。至少匹配n次。例如,o{2,}不能匹配Bob中的o,但能匹配foooood中的所有oo{1,}等价于o+o{0,}则等价于o*

    {n,m}

    mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,o{1,3}将匹配fooooood中的前三个oo{0,1}等价于o?。请注意在逗号和两个数之间不能有空格。

    ?

    当该字符紧跟在任何一个其他限制符(*,+,?{n}{n,}{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串ooooo+?将匹配单个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

    匹配xy。例如,z|food能匹配zfood(z|f)ood则匹配zoodfood

    [xyz]

    字符集合。匹配所包含的任意一个字符。例如,[abc]可以匹配plain中的a

    [^xyz]

    负值字符集合。匹配未包含的任意字符。例如,[^abc]可以匹配plain中的p

    [a-z]

    字符范围。匹配指定范围内的任意字符。例如,[a-z]可以匹配az范围内的任意小写字母字符。

    [^a-z]

    负值字符范围。匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在az范围内的任意字符。

    \b

    匹配一个单词边界,也就是指单词和空格间的位置。例如,er\b可以匹配never中的er,但不能匹配verb中的er

    \B

    匹配非单词边界。er\B能匹配verb中的er,但不能匹配never中的er

    \cx

    匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Za-z之一。否则,将c视为一个原义的c字符。

    \d

    匹配一个数字字符。等价于[0-9]

    \D

    匹配一个非数字字符。等价于[^0-9]

    \f

    匹配一个换页符。等价于\x0c\cL

    \n

    匹配一个换行符。等价于\x0a\cJ

    \r

    匹配一个回车符。等价于\x0d\cM

    查看(634) 评论(0) 收藏 分享 管理

  • 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-8
    begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end
    require 'cucumber/formatter/unicode'
    require "watir-webdriver"
    $:.unshift(File.dirname(__FILE__) + '/../../lib') 


    Before do
      #$page=Watir::Browser.new:ff
      #Login_action
      #Navigate_to_manage_card_action
    end

    After do
    #Logout_action
    end

    Given /^点击(.*)按键$/ do |button|
      if button =="开卡"
      #$page.button(:name, "开卡").click
      end
     
    end


    Given /^我已经在卡号框里输入(\d+)$/ do |card_number|
    #$page.text_field(:name,"card_number").set(card_number)
    end

    Given /^我已经在卡号框里输入错误卡号(.*)$/ do |card_number|
    #$page.text_field(:name,"card_number").set(card_number)
    end

    Given /^我已经在激活码框里输入(\d+)$/ do |act_number|
    #$page.text_field(:name,"act_number").set(act_number)
    end

    Given /^我已经在激活码框里输入错误激活码(.*)$/ do |act_number|
    #$page.text_field(:name,"act_number").set(act_number)
    end

    Given /^我已经在初始金额框里输入(\d+)$/ do |ini_money|
    #$page.text_field(:name,"money").set(ini_money)
    end


    When /^我点击(.*)按键$/ do |button_name|
      if button_name =="开卡"
      #$page.button(:name, "开卡").click
      elsif button_name == "消卡"
      #do cancel
      end
    end

    Then /^我应该在定位卡管理界面$/ do 
        #page_on_manage_card_page
    end

    Then /^刚输入的卡号可以在该界面查询$/ do 
      #card_number_can_search_out
    end

    Then /^不增加新的定位卡信息$/ do
    # log
    end

    Then /^提醒(.*)$/ do |message| 
      if message =="请输入卡号" 
      # log 
      end
      
      if message =="请输入激活码" 
      # log
      end

      if message == "该卡号已存在"
      #log
      end

      if message =="卡号有误"
      #log
      end

      if message =="激活码有误"
      #log
      end
    end


    现在我们对这些进行分析:

    首先:我们需要在before do里面做一系列的操作
    1. login
    2. 进入”定位卡管理“界面

    在 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_i 
    end

    Then /我应该在屏幕上看到的结果是(.*)/ do |result| 
     @result.should == result.to_f 
    end

    (\d+) 用于匹配数字 例如上例 将输入后面的数字赋值给n
    (.*) 用于匹配字符  例如上例 将结果是后面的字符串赋值给result

  • SDD开发实例(2)

    2012-12-04 14:20:39

    敏捷开发,基本上属于现在软件开发的主潮流。但是很多人还没有真正的理解它。敏捷开发并不是指特定某种开发模式,而是概指所有符合以下特性的任意开发模式:通过更加频繁有效的交流,更早的发现问题,解决问题。

     

    基本上主流的敏捷方法,都是依赖于测试的质量,所以测试驱动开发(Test Driven Development)可以称为敏捷开发的基柱。TDD的思想就是通过测试活动来驱动开发活动从而达到将客户需求能够精确的反应到开发过程中,从而降低开发的成本。在这过程中,最典型的特点就是先完成测试程序,在实现能够通过测试程序验收的代码,经过反复迭代,从而使得产品顺利发布。

     

    TDD的进化过程中,出现了一个更加有趣的BDD分支,即行为驱动开发(Behavior. Driven Development)。在不断的迭代过程和OO思想影响下,我们会发现有很多产品的设计思路从总体来看就是一些特定对象的行为集合。我们的产品,就是不断的完善这些对象的行为。因此,TDD的真正价值就在于能够更加清晰有效的对对象的行为进行分解实现。对于拥有BA的开发团队,一般将用户的需求描述为产品的设计理念,例如UML的介入,大量的流程图和关系图的出现,将简单的需求复杂化,模块化。那么为什么不直接从真正用户如何使用产品入手呢?这样我们直接就从客户的角度考虑,如何设计产品,从而使其的行为能够符合用户的习惯(UE)和流程。BDD就是依据这一理念出现了。

     

    BDD通过定义用户和开发团队所共同接受的“通用语言”来实现对接。从而避免双方表达不一致的出现,导致产品开发出现产品功能偏差。

     

    SDDStory Driven Development)就是对BDD的一种具体的实现。使用Story来定义用户和系统行为,从而达到测试驱动开发的目的。

     

    一般常用的story格式如下:

    Storysubject                           

    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 给出了一些的上下文,就等同于测试用例中的preconditionsteps When给出的就是最后要验证的系统的behavior或者要验证的操作。ThenAnd给出的是这个behavior或者操作的正确期望结果。

     

    Story As a In order to So thatScenarioGivenAndWhenThen这些就是我们在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所可能出现的scenario
    2. 将scenario的每个step通过正则表达式来map到自动化测试脚本
    3. 实现自动化测试脚本


    按上面的步骤 我们现在举一个实例

    现在有一个俱乐部的会员系统,能实现的功能有:基本信息管理,积分管理,产品管理和机构管理
    在基本信息管理中,我们可以开卡,删卡和改卡

    那么我们就可以有如下user story

    user 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这些step
    Given /我输入了#d在会员卡卡号/ then do
    customer_number.entry(#d)
    end

    Given /我输入了#d在激活码/ then do
    customer_actcode.entry(#d)
    end

    Given /并且我输入了#d在初始金额/ then do
    customer_inimoney.entry(#d)
    end

    Given /当我点击#s按键/ then do
    button(:value, #s).click
    end

    Given/ 系统显示信息#s/ then do
      message.verify(#s)
    end

    这样 我们就完成了每个自然语言描述的步骤对应的自动化测试脚本的步骤

    然后 我们就可以去实现这些自动化步骤,即使我们不知道最后的代码如何,但是依据我们的自动化测试框架,我们就可以开始构建这些自动化测试代码

    Module New_Customer_Card

    def 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 do
    customer.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的核心价值,是我们主要目的。
  • QA是如何体现价值的(测试人生系列之四)

    2012-08-01 16:02:07

    作为一个软件测试人员,如何才能体验出自己的价值呢?

    首先,我们要明白什么叫做软件测试人员的价值。

    从经济学来讲,价值,是凝结在商品中的无差别的人类劳动。从测试人员来说,我们可以狭义的理解,价值就是我们凝结在在软件产品中的测试活动。所以,软件测试人员的价值,可以直接由产品的质量体现。

    而反映出一个软件测试人员的价值,就是你给产品的质量带来了多少正向的收益。

    从统计学角度,一个软件测试人员的价值可以由如下统计数据反映:开发测试用例的数量,执行测试用例的数量,发现缺陷的数量等等。

    从逻辑学角度,可以由以下作为参考:负责功能区域的优先级,测试用例的结构性,缺陷的深度和广度等等。

    从行为学角度,可以参考:任务优先级的安排,测试用例执行的顺序,缺陷跟踪的过程等等。

    从社会学角度,可以参考:对用户真实需求的贴合度,用户体验的反馈,与其他角色的交流效率等等。


    总之,一个软件测试人员的价值体现是由多个因素构成的。所以,如果想做一个高价值的测试人员,不光光是从技术角度等等方面单纯的考虑。一个好的技术人员,只是作为一个高价值的测试人员的必要条件,不是充分条件。所以对于很多单纯的想通过掌握很多测试工具来体现自己价值的从业人员来说,这是一个美丽的陷阱。

    所谓德智体美劳全面发展,如何让人把你认可为一个高价值的测试人员呢?

    个人认为主要是从如下三个方面体现:

    第一,个人能力。个人的能力包括了你的技术力,经验力,创新力,交流力等等,作为必要的条件存在。

    如何衡量你的个人能力呢?说实话,很难有个简单有效的方法。但是,有些公认的方法都可以实现。比如说,测试用例的质量,组织,结构和逻辑都很好。发现的缺陷都是直达源头。总之,个人能力好,就是大家对你的工作很放心,拥有很高的信任感。

    第二,团队能力。不怕老虎一样的敌人,就怕猪一样的队友。可是,作为团队的成员,如果你只是不停抱怨你身边的队友如何拖后腿,那么你缺乏最起码的团队精神。作为一个优秀的团队成员,你的作用不仅仅是完成自己的工作,而且要和全体成员一起达到团队成就。让每个团队中的人,能够发挥出自己的长处,避免自己的短处,鼓励激励。这不是一个团队领导自己能完成的任务,靠的是团队中的每一个人。你要做的是,让你的团队能力把你的团队推向更好。

    第三,管理能力。有句老俗话,中国人个个都是龙,凑一起就是虫。不过,这很少是因为你缺乏团队能力。而是缺乏管理能力。管理,有个人的自我管理,有任务的效率管理,有团队的执行管理等等。每个人都处于自我管理和参与团队管理和监督管理中,这样的团队,才是个有核心的团队,你才是个高价值的成员。

    其实,还有另外一种说法:

    第一,你对自己的认成度。第二,你对对团的认成度。第三,你对产品的认成度。


    综合来讲,我们作为从业人员,拿工资,干活,就是参与了价值的创造,剩余价值的剥夺和交换过程。对老板来说,你能创造比别人多的剩余价值,就是高价值的。 可是,对于每个人来说,追求自己高价值的认同,不仅仅是为了物质利益,也同时是满足自己的精神追求。

    如果你连最起码的精神追求都没有,那就谈不上什么精神愉悦感,更谈不上什么人生理想,纯粹是机械的为了生存而生存着。那你何必还去追寻如何作为一个有价值的测试人员呢。你已经抛弃了自己,不需要别人再来否定你了。
  • 如何衡量一个QA(测试人生系列之三)

    2012-07-26 15:02:49

    最近在做performance review,很多人都只是简单的针对分数去争辩,都不在意为什么要做这个performance
    review了。

    实际上,在列出的指标中,能很好说明衡量一个QA的标准:

    Adaptability and Change Management Skills

    这一条,做一个合格的测试人员,就是能够接受频繁的任务转换。每个测试人员都是在不停的切换于不同的任务中。正常的,就是能够正常切换自己分配的任务。良好的测试人员,就是不光能够合理的切换,而且能加入自己的经验进行更高效率的切换。优秀的测试人员,不但能够更有效率的切换,还会对切换的需求进行分析,了解切换的原始目的,从而能够对切换的指令进行有效的回馈。

    Attendance and Punctuality

    一般来说,能够按时的参加各种会议,讨论和活动就是ok的。好一点的,会提前了解一下内容。更好点的,会不但了解内容,还会思考自己参加的意义,并提出自己的意见。

    Communication and Cooperation 

    能够交流和协作,这是必须的。能够作为发起人进行主动交流和协作,就是良好的。能够进行主动的进行高质量的交流和协作,并对整个过程进行掌控,就是优秀的。

    Initiative & Motivation

    能够主动去做一些份外的事,就是正常的。能够主动的去做,并且能够带来更有益的改进,就是良好的。主动做的事,能够带动team整体进行,就是优秀的。 

    Job Knowledge

    能够对自己工作的内容完全掌握,就是正常的。能够对整个项目熟悉,是良好的。能够主动的运用知识对项目进行有益的补充,就是优秀的。

    Judgment and Decision Making 

    能够对自己的工作内容进行合理的决定,就是正常的。能够对自己的决定给整个team带来的影响进行评估和管理,就是良好的。能够对自己的决定给整个项目带来的影响进行评估和管理,就是优秀的。

    Organization and Planning Skills 

    能够对自己的任务进行管理和计划,就是正常的。能够根据项目情况调整自己的管理和计划,就是良好的。能够根据自己的管理和计划对项目带来有益的补充,就是优秀的。

    Problem Solving Skills and Results Orientation 

    能够解决问题,就是正常的。能够够解决问题,并进行问题跟踪,分析和反馈就是良好的。能够解决问题,并引入风险管理,就是优秀的。 

    Quality

    能够保证工作的质量,就是正常的。能够提高team的质量,就是良好的。能够改善项目的整体质量,就是优秀的。 

    Reliability and Accountability

    能够被信任,就是正常的。能够被期望,就是良好的。能够被盼望,就是优秀的。

    Team-work and Inter-personal Skills 

    不做team的短板,就是正常的。帮助team的短板,就是良好的。team没有短板,就是优秀的。

    Technical Skills 

    项目的技术熟悉,就是正常的。能成功引入外部技术,是良好的。能够推动技术的潮流,就是优秀的。

    Information and Behavior.  

    提供最够的信息让外部识别,是正常的。拥有公司内部的知名度,是良好的。业界著名,就是优秀的。

    English Ability

    能够满足需要,就是正常的。能够去争论,就是良好的。能够去开讲论谈,就是优秀的。

    Goal and Objective Setting 

    能够制定个人目标,就是正常的。能够制定team共同目标,就是良好的。被所有人当作目标来追赶,就是优秀的。

    Leadership 

    能够当好leader,就是正常的。能够培养新的leader就是良好的。能够被人当作标杆,就是优秀的。

    Staff Development 

    管好项目的人,就是正常的。能够打成一片,就是良好的。能够被人信赖,就是优秀的。

    Responsibility

    做到职任所在,就是正常的。能够培养出有职业精神的团队,就是良好的。能够培养出有灵魂的团队,就是优秀的。
  • 我们为什么用bugzilla

    2012-07-19 21:10:01

    bugzilla作为测试人员最常见的测试工具,被所有人熟悉和使用着。

    可是,bugzilla究竟给我们带来了些什么呢?

    第一,bugzilla给了测试人员话语权。我们通过它,作为一个平等互利的角色向开发人员,官方的,正式的发出我们的成果宣言:一个bug。

    第二,bugzilla给了测试人员平等权。测试人员不再是开发人员的帮手,大家是从不同的视图来看待一个产品的质量。 bugzilla是作为开发人员和测试人员交流的平台。 同时,这个交流平台也连接了项目管理,过程管理,需求人员,设计人员,销售人员,技术支持人员,和最终客户,是大家能有一个平台去交换各自的想法。

    第三,bugzilla使得测试人员能使用一个标准化的对象去进行信息内容的沟通。

    第四,bugzilla使得测试人员能够更加迅速的了解产品的当前质量状态,从而调整各种计划和工作。

    第五,bugzilla使得测试人员能够积极的参与到产品的管理过程中,对整个产品的管理提供更多的技术细节和过程参数。


    对于如何使用bugzilla进行项目管理,我们不妨举几个例子:

    例子一:我们在测试过程中,经常会遇到这种现象,就是一个模块会突然爆发出很多bug来。难道bug就真的那么多吗,其实很多时候,是因为开发人员在修改一个bug时,引起其他已经修复的bug被reopen或者导致更多的新bug。

    我们如果有一个机制,去监控 最近3天内,新加的bug的原因。那么,这种问题就能够作为一个风险进入我们的风险管理过程。如果有相应的风险管理,那么就执行。如果没有,就需要加入。并且,根据实际情况,我们来判断,还有多少潜藏的bug会以这种方式出现。


    例子二,我们在做测试计划的时候,很难说我们的测试各个阶段都能够很详细的制定出内容来。比如回归测试,到底哪些东西要做回归测试呢,什么样的频度,什么样的深度?

    我们可以在功能测试结束前的2周,就对现有的bug进行分析,依据bug的在各个模块的分布数量,优先级的加权等,来确定哪些需要重点进行回归,那些可以忽略。从而对各个模块的功能测试用例进行筛检,从而得到回归测试需要执行的规模和频度。

    例子三,当一个产品被release之后,或者一个sprint结束之后,我们也可以对bug进行分析,通过bugzilla自带的很多图表,我们能够对上个阶段的产品质量有一个很直接的可视化分析,然后写出QA角度的分析报告来,提供给管理层和开发团队作为参考,从而在下一个阶段中能够更好的提高质量和效率。甚至,可以以QA的视角,去管理下个阶段的开发过程和质量保证过程。

    总之,bugzilla不是仅仅作为我们QA跟开发交流的工具,还可以作为测试驱动开发的工具,可以作为产品质量衡量的工具。
  • Road to Revolution (测试人生之二)

    2012-07-19 20:40:12

    最近开QA Forum,发现大家越来越急切的想通过学习一种自动化工具来摆脱所谓的低级测试人员的帽子,从而能找一份更好的工作。

    我不禁想起前段时间跟朋友讨论的什么是企业文化。

    企业文化,就是你为什么想进入这个公司,你想在这个公司获得什么,你想在离开这个公司的时候有什么变化。为什么大家都想进入500强,张口闭口他们的企业文化好,无非就是高薪,高福利,工作压力小,适合养老。 呵呵。

    对一个发展中的中小企业,尤其是一个处于瓶颈期的企业,其实更需要企业文化来拯救自己。企业文化,其实就是一个企业的独特魅力,也是这个企业赖以生存的核心竞争力。

    一个没有文化的企业,压根就没有什么凝聚力,更谈不上什么团队。大家都是在混吃等死,完全看不到自己个人的职业方向,要么就是赶紧学点什么高精尖的技术,跳槽走人,要么就是得过且过,那天面到一个合适的就撤。

    一个有文化的企业,就是流氓会武术,谁也挡不住,再念几句经,皇帝也保护。

    但是,企业很难去形成自己的文化,为什么呢?缺乏改革的动力,没有想法,没有信心去改变,高层混吃等死的想法,比下边干活的人想的还多。反正公司倒了,我再换个公司去当高管。

    如此下去,就是典型的2年之内从10个人的小公司到500人的中型公司,然后大家就开始吃老本,3,5年内被打回原形。

    企业之道,就在于你需要跟随市场的需要不断进化。诺基亚如此,当年的通用也是如此。当高管们桎梏了企业的发展,我们就需要一场revolution。


    而测试人员来说,他的职业之路,其实就是一条revolution之路。 测试的最高境界,就是你从客户的角度来使用一个产品,也就是现在吵闹最多的用户体验决定产品质量。而用户的体验,就是随着时代不断变化中,你如果想在这条路上走的更好,不要去顾及太多的技术,去迎合那些软件开发公司的短期需求,你需要的是站在一个不断被新的应用调高胃口的客户的角度去考虑你的测试方向。更新更好更廉价,就是最好的产品。 所以一个好的测试人员,只需要去掌握趋势,不需要去深入到过多的技术细节,我们要无招胜有招,把所有的招数都忘记了,测试必然大成。
  • 我们是谁?(测试人生系列之一)

    2012-07-10 21:40:51

    前几天跟朋友聊天,说你们测试人员现在不好混吧,技术含量低,人员过剩。呵呵,表面上敷衍过去,回来沉思,想到我们测试到底是什么一个状态呢。

    Who am I?

    一般来说,软件行业的测试人员主要是进行一些保障产品质量的活动。有的地方叫tester,和coder相对应。有的地方叫QE,意思是质量工程师(Quality Engineer)。 有的叫QA。 这个QA一般有两种说法,一个是Quality Assure, 意识是质量保障工程师。不但包含对软件产品质量的保障这层意思,很多公司还有专门的QA这个职位,用来对产品质量过程进行控制,例如CMMI体系,就有专门的人去审核测试团队在对某个产品进行质量保障的时候,其采用的流程,方法等等是否符合标准。 有的公司称QA为Quality Analyst,意为质量分析工程师。其实我个人更喜欢这个称呼,更加小资一些,像个文艺青年值得干的活。

    总而言之,测试人员的具体工作就是保障软件的质量。一般面试的时候,我也喜欢问这个问题,很多人都能说到这层意思。但是对于一个文艺青年来说,这点似乎有点太庸俗化。我们更喜欢说,我们是保障最终用户能够得到满足他们真实需求的软件。

    其实,很多开发人员看不起测试人员,就如同我们对中关村攒电脑的也自称自己是it人一样鄙视。实际上呢,测试和开发来说,都是软件工程中的一个角色而已。

    在软件工程这个词还没被发明前, 所谓的软件或者计算机行业,都是给数学专业大牛们打下手的。 我接触过最早的软件从业人员,任务就是帮助学校的老教授打孔,然后放到一个史前级别的科学计算器(也就是一般意义的电脑的前辈),去计算。 就是高级的计算器。

    后来,真正引导软件行业走向工程化的,应该是Nasa的功劳。每个入行的人应该都学过,当年为了保障火箭能顺利升空,很多计算结果都需要反复的验证。这个验证的过程,其实就是一个测试的过程。当软件开发变成了软件工程的时候,测试就作为开发的一分子存在于世了。

    那个时候,开发一个软件,很多时候都是为了自己的某个需求。所以,那个年代的开发,从实际意义来说充当了如下多个角色:用户,需求分析人员,设计人员,开发人员,测试人员,管理人员和维护人员。

    在中国的这个文化沙漠中,测试人员单独出现,也是由外企带来的。那个时候的测试人员,大部分时间就是玩自己公司的软件。然后,发现了问题,就写封邮件,说这个地方为什么是这样啊,我觉得不对劲啊。然后开发大拿们也许会斥责:不懂装懂,滚。也许会鄙视:这是我们的产品特性啊。 也许会悻悻然:哦,一个小问题,回头我改了就行了。

    当年2001年,找工作的时候,突然发现有公司招测试人员,就应聘了。基本上工作就是玩一个软件,熟悉了以后,就是每个版本从头到尾把自己能玩的玩一遍,看看有没有问题。所以,记忆尤甚的是当时很多bug都是一个大妈发现的,她连开机都不会,更别提装什么操作系统了。她的方式就是逮住一个页面,不停的点点点。

    哈哈,那个时候换煞有其事的参与了好多测试论坛的研讨会,很多著名的论坛都是那个时候各起山头的。 不过当时就觉得,大家其实都抱着我来学robot怎么用来的,其实没什么意思。感觉那个时候的测试人员,都是为了能有一个一技之长,好跳槽涨薪。 记得当时有个深圳的哥们说,他是测试人员,一个月12k,当时在北京一个月3k的我,只能恨之厌之不服之。哈哈。

    总之,行业在发展,后来就有很多像模像样的测试理论方法流程过程纷纷韶绕了一段。 那个时候,测试和开发,似乎成为了冤家对头。测试就是挑刺的,被开发鄙视,去恶心开发。 很多开发觉得,你丫就是个棒槌,根本用不到你们。 测试呢,普遍想法是,哥就喜欢干这个挑刺的活,舒坦,你丫牛逼,别搞这么多bug出来啊。所以,很多时候,开发人员终于如愿以偿的混上PM了,会对手下的测试人员极为苛刻。

    慢慢的,很多公司觉得把每个项目都搞几个QA有点得不偿失,就把人都集中起来,搞个测试经理,然后每个测试人员都参与多个产品的测试。貌似,有点独立权了,开始张口闭口我们测试部门怎么怎么样。 很多公司现在的模式还是如此。

    其实,测试人员如果只是单纯的会测试,确实局限性很大。 一个好的测试人员,哪怕最底层的,他至少对他要测试的部分了如指掌,知道跟那些模块的相互影响是什么。毕竟80%的bug都是出现在模块之间的交集地带。 而一个开发,更多的是对开发工具的熟悉,实现功能。他们注重的正向的测试,对于交叉测试很少能够全面的衡量。 所以,这就是一个好的底层测试人员的作用。

    对于一个3年以上的测试人员来说,其实他对一个产品的周期,要比很多开发人员熟悉的多。他更熟悉开发的计划,时间表等等。 能更好的从产品层次去组织和管理测试活动。

    对一个好的测试人员来说,测试经理不是最好的,其实他们更加适合当一个项目经理。一个产品开发过程,需要一个开发经理,一个测试经理和一个好的项目经理。这个项目经理,很多情况下都是高级开发经理担任的。其实这样有利有弊。 对于现在越来越清晰的测试驱动开发的模式,更需要一个高级测试经理来担任这个角色。

    因为一个好高级测试经理,不但是对产品开发周期,风险规避,人员安排更加熟悉。而且能够更加有效的组织测试活动。而且,高级测试经理往往已经能够胜任一个需求分析经理的职位。对测试管理,团队管理更加得心应手。原因就是:一个开发看到另一个开发的能力,往往是他的经验,就是他能不能解决一个复杂的开发问题。更多的是经验的积累。 而测试人员看开发人员,往往都是他的短处,谁更容易在什么地方出错等等。 而且,测试往往比开发更加熟悉一个产品的真实需求。而且,测试用例的设计,除了对已有知识经验的必需外,更加需要的是一个有很强的创新能力的人去设计。一个创新,一个积累,在中国这种纯粹靠密集劳动力拿项目的现实中,是多么的可贵,是多么的心痛,被那么多无量的开发经理直接忽略。

    所以测试人员,想做的更好,就是要把自己搞的既是BA,又是QA,process manager,而且还是最终用户。 这才是一个真正的测试人员需要自我。

  • 性能测试的研究(4)

    2012-02-03 14:47:51

    性能测试数据模型
    设计性能测试数据模型是一个设计数据负载分布配置文件的建模过程,也是对一个真实的用户的环境进行模拟的过程。每个配置文件一般包含了如下属性:
    •	关键场景
    •	并发用户数
    •	请求率
    •	请求模式
    
    对于请求模式和请求率,一般是根据真实的用户环境和用户习惯进行预测。如果已经有实际的应用环境,那么分析服务器日志文件是一个更加精确的方法。通用的方法如下述各条:
    
    那些是关键的场景?
    
    通过分析那些会对程序性能产生影响的场景,并结合用户需求来衡量那些是关键场景。也就是说,经历程序的核心模块的那些场景
    
    预期的最大在线用户数和并发用户数是多少?
    
    预期的最大现在用户数一般就是预期设计的程序最大运行能力所能承受的用户数。而活跃用户数一般是分布在程序的不同场景中。而并发用户数,是指一个单一的场景所能允许的极限用户数。一般来说并发用户数占在线用户数的比例不超过五分之一。同过分析已部署的实际用户环境的服务器日志,很容易得出这些数值。
    
    普通用户一般会执行的场景路线图是什么?
    
    从用户角度分析,正常的用户在使用程序时都有什么样的习惯也是很重要的。通过分析用户的习惯,从而知道用户体验的关键场景在什么地方。从而有针对性的测试。例如,一个电子商务网站的最常用的场景路线图是:
    •	打开主页
    •	登录
    •	浏览商品目录
    •	选定商品加入购物车
    •	提供付费,送货地址等信息。
    •	提交订单
    
    
    如何制定用户配置文件?
    
    用户配置文件是为了区分不同类型的用户。每个配置文件里都包含了一种特定用户类型,以及该类型用户的特定操作组。例如,可以设计一个用户配置文件,使用该用户配置文件的用户都是属于某个特定权限组,唯一操作是浏览目录。利用这种方式就可以把各个场景的用户进行组织。
    
    例如:
    •	浏览配置文件(给只浏览的用户群使用)
    •	搜索配置文件(给直接搜索的用户群使用)
    •	订单配置文件(给需要完成订单的用户群使用)
    
    
    每一个用户配置文件中,单一用户的操作分布是?
    
    我们可以根据用户需求分心或者实际的用户体验(利用服务器的日志文件分析得出)来判断每个单一用户的操作分布是什么。例如对于电子商务网站来说,一个实际的订单配置文件中的用户体验如下:
    
    
    对于无法从日志文件中得出分布的时候,我们可以根据用户需求分析和通常的市场分析报告来获取。例如,通过需求和市场报告我们获知,每个人在购买产品时,通常会浏览该类产品总目录一次,需要搜索指同类产品两次以做比较后进行购买。并且用户购买产品时绝大多数不少于三件产品。那么 我们的配置文件就如:
    每个请求之间的平均思考时间是多少? 思考时间是指用户在两个连续的请求之间的等待时间。在次期间,用户一般在浏览上一个请求返回的信息。例如,该产品的详细信息,图片啊等等。 思考时间完全依赖于数据的复杂性。比如,登录页面的思考时间就远远小于浏览产品信息的思考时间。一般来说,思考时间都是取的所有请求的思考时间的平均值。这个时间一般都可以从通常的读速或者日志文件中获得。 用户配置的文件是如何组织的? 一般来说用户配置文件的组织结构,都是在一个给定的时间点,各个用户群体的分布来决定的。例如:
    如何判断每个测试用例需要的执行时间? 测试的持续时间取决于设计的场景,数据和使用模式。以下是会经常考虑的: 用户的规模。对于一个电子商务网站来说,场景很简单,数据压力也不大,所以主要是考虑用户的使用模式。这样在考虑持续时间时,只需要做一个2-4小时即可。对于电信收费系统来说,就需要至少持续48个小时。 用户的行为。对于一个电子商务网站来说,压力最大的时候是在特定的假日期间会产生大量的订单。所以,对具体的瓶颈模块,需要更长时间的测试。比如银行付款模块,就需要能有足够大的能力来承受瞬间的强大压力,并要在最大承受能力下持续7X24小时来测试。 特殊的需求。对于一些特殊的客户需求,我们需要执行相应的测试时间。例如,电信收费系统会在每月底不断的接受强大的数据压力。为了模拟这种测试,我们就需要有个模拟的环境。例如,有一套单独的系统,独立运行中,每次压力只持续10分钟即可

    -fo


  • 性能测试的研究(3)

    2012-02-02 14:54:42

    压力测试
    
    压力测试是使用高于系统承受能力的数据压力对程序进行测试。其手段是快速消耗资源从而使得程序在“零”资源情况下运转。例如,超负载的用户登录数,大量消耗处理器和内存,剥夺了其他模块获得资源的机会,使得这些模块处于“暂停”状态。
    
    压力测试的目的是为了在高负荷条件下挖掘那些潜在的程序问题。
    
    常见的问题有:
    •	同步问题
    •	资源竞争
    •	内存泄漏
    •	网络拥塞导致的数据丢失
    
    和负载测试不同,压力测试是有明确针对性的测试。具有明确的性能指标,明确的测试场景,明确的数据量。负载测试往往是单一的场景测试,而压力测试往往是多个场景的复合测试。负载测试往往没有特殊的先决条件,而压力测试都是在特殊的指定测试环境下进行的。负载测试一般都是用来发现一个问题,而压力测试往往是用来复现一个问题。负载测试一般都是针对业务逻辑进行测试,而压力测试可以是一个简单的对象,例如一个指定的存储过程。
    
    进入文档
    
    执行压力测试的进入文档一般有如下几个:
    •	程序的特性(特殊的场景)
    •	潜在的问题(隐含的场景)
    •	需要的压力数据的特性
    •	瓶颈峰值(由负载测试得到的阀值)
    
    步骤
    
    进行压力测试需要的六步流程如下所示:
    
    
    流程包含的步骤如下: 1. 选择测试场景。根据要测试的缺陷,选择相关的测试场景。 2. 设计测试数据。依照测试场景,和由负载测试获得的阀值,来设计所需的测试数据。 3. 指定性能指标。针对测试的缺陷,来指定在压力测试中要监察的性能指标。 4. 创建测试用例。基于测试场景,数据集和缺陷来创建针对性的测试用例。 5. 执行测试用例。在特定的测试环境中执行测试用例。 6. 分析测试结果。 对得到的结果进行分析。 步骤一 选择测试场景 进行压力测试要确定多个测试方案。每个方案都依赖于一个单一的测试场景。一般来说,只有一对一的场景测试,才能更好的发现潜在的性能问题。如下是常用选择场景的原则: • 选择那些对整体性能有影响的场景。 • 选择那些最有可能影响性能的操作。例如,频繁的锁定操作,同步操作,长事务操作和那些磁盘密集型操作。 • 基于负载测试的结果。通过负载测试,可以探知一些系统的瓶颈。而一般围绕这些瓶颈进行压力测试是一个很好的选择。通过对瓶颈进行更大的压力测试,从而使得程序部分功能阻塞,从而揭显出那些隐藏的问题。 对一个电子商务应用来说,典型压力测试如下: • 订单处理场景中,程序需要实时的更新产品的库存。所以,会出现数据库数据同步和假死锁的可能。 • 用户在搜索的场景中,使用了一个会返回大量值的关键词。这种搜索会占用大量的内存而使得利用率降至极低。并且很大程度上是一次无效的搜索,浪费了资源。 步骤二 设计测试数据 用于压力测试的数据负载量,首先必须超过阀值。然后,不断调整负载来观察程序的行为。 其中一个设计理念就是对负载测试的反向设计。负载测试是要保证所有影响程序性能的性能指标是处于正常运行的状态下。所以压力测试只要破坏其中任意一个性能指标就可以压垮程序。通过不断的压垮程序的压力数据集,你也可以获得对抗这种潜在的高峰压力的方法。 负载测试的持续时间一般都是有个明确的值。而压力测试的持续时间测很难判断,不但会跟测试环境相关,也跟具体的场景有关。所以,不断的更换测试环境的配置是很有必要的补充,而在负载测试中,测试环境都是要求稳定的一致。 步骤三 指定性能指标 在压力测试前,要明确每个场景存在的隐患所可能涉及到的性能指标。这些性能指标一般都是预设的性能要求或者是根据明确的用户需求推导出来的潜在需求。一般来说,这些性能指标都是和负载测试的指标相同。可以共用同一种方法来获得。例如,在代码中加入的计时器,就可以被二者共享。但是,压力测试的性能指标获得都要比负载测试的过程复杂。 例如,在提交订单这个场景中,最主要的性能指标是资源竞争。除了负载测试需要关心的基本信息,需要获得一些额外的信息:
    步骤四 创建测试用例 基于以上步骤,创建所需要的压力测试用例。例如一个提交订单的测试用例如下: 触发条件: • 十万个模拟用户 • 每秒随机两次操作 • 用户异步触发 • 持续两天 性能参数(期望值): • 死锁(无硬死锁) • 接受请求数(不小于25次/秒) • 驳回请求数(不高于50次/秒) • 死锁率(不高于35%) • 解除死锁率(长度不超过100个/秒) 步骤五 执行测试 可以使用手工或者自动化工具对测试用例进行执行。一般执行的时间可以分为两种: 第一种,固定时间。例如,每个模块完成集成测试后,开始执行功能测试前。 第二种,固定阶段。例如,在功能测试完成后进行。 步骤六 分析测试结果 通过分析测试结果,与负载测试的数据进行对比,从而发现那些隐藏的瓶颈的成因。为了更好的修复问题,还需要做如下的额外工作: • 重新审读设计文档 • 重新审核源代码 • 修改架构并测试来验证结论

  • 性能测试的研究(2)

    2012-02-01 16:14:49

    负载测试流程
    
    使用负载测试来研究系统在通常数据压力下和峰值数据压力下的行为。一般是采用逐级增加数据量的方法来研究。从一个初始化环境的数据量逐级增加直到性能阀值数据量,一般是倍增的原则。例如,你设定了CPU的最高阀值是75%。那么逐级增加数据量,直到CPU的占用率接近75%。通过负载测试,你能够识别系统的瓶颈和程序的最大稳定负载能力。
    
    进入文档
    
    进入文档一般包含如下:
    •	由性能架构决定的性能目标
    •	程序的特性(测试用例)
    •	工作数据流的特性
    •	每个程序特性的性能指标
    •	测试计划
    
    
    测试步骤
    如下表中描述了进行负载测试的流程:
      
    
    负载测试流程包含了如下步骤: 1. 设定主要测试场景。从程序所包含的所有应用场景中,挑选出那些对性能影响最大的场景作为需要测试的场景。 2. 设计测试数据。根据设定好的测试场景设计相应的测试数据。 3. 审定性能指标。对每个需要测试的场景,设定具体要检测的性能指标。 4. 创建测试用例。针对每个测试场景,设计具体的测试用例,用于获得需要的性能指标。 5. 执行测试。使用设计好的测试数据执行测试用例,并搜集设定的性能指标的具体数据。 6. 分析测试结果。根据具体的性能指标的数据分析结果,对程序性能进行评估。 步骤一 设定主要测试场景 万始之初是挑选关键的测试场景。一般一条业务路径中,包含了多个场景。而关键场景,就是对你的测试目标有着直接影响的场景。一般来说关键场景就是经常被使用的场景或者是需要使用大量资源来执行的场景。 例如,对一个购物网站来说,常见的关键场景如下: • 登录网站 • 浏览产品目录 • 搜索特定产品 • 购物车 • 信用卡验证 • 订单提交 步骤二设计测试数据 根据挑选出来的测试场景,需要有针对性的设计所需的测试数据。一般来说测试数据应该考虑到如下几个因素: • 用户数。需要明确在线用户数和活跃用户数的需求。 • 请求频率。需要明确在单位时间内可能发生的请求数。 • 请求的模式。同样的用户集合在不同的模式下使用程序会带来不同的数据流。所以要明确用户会以何种模式来使用程序。 一般来说,我们采用数据模型的方法来创建测试数据集。 在创建了数据模型后,根据用户分布配置文件,来使用测试数据进行逐渐加压测试。在加压过程中,记录程序的行为,直到获得足够典型的性能目标数据,即可将当前的数据量作为一个数据集标准。然后逐渐加压,直到获得程序的阀值,然后就可以在数据模型中明确标识。这样,就可以勾勒出来一个明确的数据级别分布图。 步骤三审定性能指标 拥有明确的性能指标,才能在测试中获得有效的测试数据。通过这些指标,你才知道在哪里能找到用来对程序的性能进行评估的对象。只有通过这些指标,才能识别出真正的瓶颈。 而且,通过不断迭代的测试方式,你可以在任何一轮测试前根据上次的结果来修改下一轮测试需要关注的性能指标。例如在上轮测试中发现某个未监控的服务进程实际上是真正的资源消耗源头。那么在下轮测试中,就可以根据这个服务进程修改测试方法,数据和要关注的性能指标来跟踪。 如下所列的指标类型,都是用于评估程序性能的常用类型: • 网络类指标。这类指标一般提供了网络健康指数。例如交换机,路由器和网关等的状态。 • 系统类指标。这类指标一般用于了解服务器的资源利用率情况。例如处理器,内存,磁盘的输入/输出和网络端口的输入输出状态。 • 平台类指标。这类指标一般用于监察程序相关软件的性能情况。例如,使用的公用语言运行库和私有语言运行库的性能情况。 • 程序类指标。这类指标一般使用在程序中添加获得额外的代码来获得的。例如,在登录程序中,添加一个计时器,来获得用户登录的消耗时间。 • 服务类指标。这类指标一般用于衡量整个程序的数据吞吐量和服务延迟时间。一般都会跟一些特定的业务场景相结合。例如下表所列:
    在审定好性能指标后,我们需要给每个指标设定一个我们期望的基准线。这个基准线可能有多条,分别对应于不同的数据量。通过分析这些基准值和实际值,能够更加清晰的得出在不同的负载水平下的性能。举例如下:
    步骤四 创建测试用例 基于步骤二设定的数据模型和步骤三设定的性能指标来制定测试用例。 例如:在数据集A的测试场景中,使用测试用例1,2,3对多个性能指标进行检测。

    数据模型的数据集A为:

    场景

    占总用户的比例

    用户数

    浏览目录

    50%

    250

    搜索产品

    30%

    150

    提交订单

    20%

    100

    总计

    100%

    500

    审定性能指标和预设值为: • 单位时间浏览目录数(100/秒) • 单位时间成功提交订单数(10/秒) • 返回查询结果平均时耗(2.5秒) • 处理器占用率(不大于50%) • 内存占用量(不大于320MB) 测试用例为: • 测试用例1:每秒发送200个浏览请求。检测性能指标:单位时间浏览目录数,处理器占用率,内存占用量。 • 测试用例2:每秒发送100个查询请求。检测性能指标:返回查询结果时耗,处理器占用率,内存占用量。 • 测试用例3:每秒发送20个订单提交请求。检测性能指标:单位时间成功提交订单数,处理器占用率,内存占用量。 步骤五 执行测试 可以使用手工或者自动化工具对测试用例进行执行。一般执行的周期可以分为两种: • 第一种,固定周期。例如,每周对测试用例执行一次。 • 第二种,固定版本数。例如,每十个版本执行一次测试用例。 步骤六 分析测试结果 根据测试获得的数据和预设值进行比较,就可以对程序的性能有一个明确的评价结果。从而明确了性能调优的目标。同时,这些数据也能帮助你得出产品的瓶颈和潜在的固有缺陷和风险。以及获得如何进行扩容的方式和方法。同时,连续的测试结果报告,有助于控制产品的性能指标,从而降低开发成本。根据测试结果,还可以帮助用户在使用程序是如何部署更加优化的运行环境。 输出文档 通过负载测试获得的常用输出文档如下: • 更新的测试计划文档 • 在不同的负载水平下,程序的行为描述文档 • 程序的最大稳定负载能力描述文档 • 潜在的瓶颈,固有缺陷和风险的描述文档 • 推荐的部署和配置文档
  • 性能测试的研究(1)

    2012-01-31 18:38:21

     简述
    
    性能测试用于确定应用程序在指定的输入输出条件下的响应状况。一般要使用多个独立的性能测试场景/测试用例来覆盖所有的可能性。测试时,尽可能使测试环境贴近真实环境。通过研究应用程序的模拟负载下的行为,来确定其性能指标是否满足设计目标。
    
    性能测试是用于研究应用程序在预期数据量和最高峰值数据量下运行状态的测试方法。以便确认程序在不断增加的数据量下的具备的处理能力。如下的三种性能测试方法都可以殊途同归的实现以上的目标:
    
    •	负载测试。使用负载测试来研究基于不同可接受的数据集合下的产品的行为。 可以很明确的获知产品是否达到了设计要求。一般通过监控响应时间,数据吞吐率,资源使用率来进行测试。而且通过这种测试可以探知应用程序在什么样的数据峰值下达到崩溃点。
    
    •	压力测试。压力测试用于评估应用程序在数据量过载后的行为。目的是在高负荷状态下,挖掘更多的系统隐藏的内在问题。例如数据同步,资源竞争和内存泄漏这些常见的问题。通过压力测试,我们可以探知应用程序的内在缺陷,以及其会带来的风险。
    
    •	能力测试。能力测试和负载测试相辅相成。通过其能够获知应用程序的预设的失败阀值点。这个阀值点是通过研究负载测试在各个数据量的程序行为获得的,即在崩溃点前最后一个能够维持程序稳定运行的数据量为预设的失败阀值点。通过能力测试,可以制定扩容计划。通过扩容计划,我们可以稳定的提高用户集和数据集。例如,如果想将用户集和数据集提高一倍,那么根据现有的资源。(例如处理器个数,内存容量,硬盘空间,网络带宽等等)我们就可以知道最小的扩容资源需求值。
    
    性能测试的目标
    
    性能测试的最大目的是来比照应用程序的实际性能和预期性能。同时还有一些其他的目的:
    •	确认系统中存在的瓶颈和成因。
    •	调整和优化平台的硬件配置和软件配置来达到性能最大化。
    •	验证程序在压力下运行的可靠性。
    
    只通过一种性能测试的方法是不可能获得所有的性能指标的。但是了解这些性能指标,对你进行性能测试会有很大的帮助:
    •	响应时间。
    •	吞吐率。
    •	最大并发用户数。
    •	资源利用率。
    •	不同数据量对应的系统行为。
    •	程序崩溃点。崩溃点一般是指程序停止响应,返回典型的503错误时的数据量值。
    •	程序崩溃的原因和崩溃后的行为。
    •	程序的固有缺陷。
    •	负载的主要成因。例如,是用户数的增加导致负载量翻倍,还是某个操作导致数据流翻倍。
    
    性能测试的指标
    
    绝大多数的性能测试依赖于一组预定好的,文档化的和达成共识的性能目标。明确的目标可以提高性能测试的效率。通过测量程序的真实数据和目标进行对比从而判断程序性能的优劣。
    当然你也可用通过探索的方式对产品进行性能测试来了解程序的真实情况而无需任何明确的目标。这些测试的结果也可以作为对产品性能评价的指标。
    
    性能指标一般包含如下:
    •	响应时间/延迟时间。
    •	数据吞吐率。
    •	资源利用率。
    •	工作负载。
    
    响应时间/延迟时间
    
    响应时间是指发出请求后到得到相应所需的时间量。在服务器端和客户端都可以测量相应时间:
    
    服务器端获得响应时间。这个时间段是指服务器从获得请求到完成的执行时间段。不包含客户端到服务器端的传输时间段,因为其含有网络传输消耗的时间。
    
    客户端获得响应时间。这个时间段包含了加入请求队列的时间段,服务器处理的时间段和来回传输的网络消耗时间段。在多种测试方法中,最常用的两种方法是:TTFB,第一个字节到达客户端为终点。TTLB,最后一个字节到达客户端为终点。而且一般来说,测试时还要使用不同的网络带宽来测试从而得到更加真实的数据。
    
    通过测试时间延迟,从而可以判断是否存在对客户端的请求响应度过低的性能问题。
    
    数据吞吐率
    
    数据吞吐率是指单位时间内可以被程序响应的请求数。不同的用户数和用户活动类型会产生较大的差异。例如下载的数据吞吐率就要比浏览页面的低。通常,数据吞吐率是以每秒可以响应的请求数来记录。
    
    资源利用率
    
    资源利用率用于确认在服务器和网络资源方面需要的资源成本。主要的资源为:
    •	处理器
    •	内存
    •	硬盘输入/输出
    •	网络输入/输出
    通过性能测试,可以明确每一个流程和步骤需要的资源情况。通过优化资源利用率,降低成本。
    
    工作负载
    
    对于一个程序,活跃用户和并发用户往往有着巨大的差别。一般来说在活跃用户中,一般只有10%-20%的并发用户存在。
    
    所以在性能测试中,要区别两者。在压力测试时,工作负载一般指的就是并发用户产生的数据量。
    

  • Test Case Design

    2012-01-11 11:01:05


    包含如下内容

    Test Case Component
    Test Case Object
    Test Case Organization
    Test Case Design Methodology
    Test Case Design Process
    Test Case Common Risk
  • CS架构的性能测试

    2012-01-11 10:51:08

    简述了如何在CS架构下进行性能测试
  • 1467/8<12345678>