在生前一定要做完想做的事!

发布新日志

  • ruby 杀进程方法

    2009-10-26 14:08:07

    是从朋友那里知道这个方法的 收藏啦
    这个只是watir封装的方法
    实际处理是通过调用ie的方法处理的
        #功能说明:
        #- 根据系统进程名,杀掉对应的系统进程
        #
        #参数说明:
        #- name:进程名称
        #
        #调用示例:
        #- kill_process('EXCEL.EXE')
        #
        #返回值说明:
        #-  成功:返回true
        #-  失败:返回出错信息
        def kill_process(name)
          begin
            wmi = WIN32OLE.connect("winmgmts://")
            processes = wmi.ExecQuery("select * from win32_process where name='#{name}'")
            
            for process in processes
              process.terminate()
              sleep 0.2
            end

            return true
          rescue => err
            $LOG.fatal(err)
            raise err
          end
        end
    用这个方法可以杀进程
  • 做性能测试需要知道的知识

    2009-09-28 23:43:59

     

    今天听了同事的分享 关于性能测试经验的分享 比较有收获 把收获的东东记录下来

    性能测试要做好 必须要对被测系统的架构了解很清楚  对操作系统知识要比较了解

    做性能测试前你需要知道的东东

    长连接 和短连接的区别?对性能有何影响

    通俗的讲 长连接就是发送一次请求之后不会断开 继续下一个请求

    短连接是发一次请求建立一次连接

    一般apahce服务都是短连接,所以只需要几个用户 只要不断的发送请求就可以压力上去

    而长连接 比如c/s结构的 就是长连接 所以需要多个用户才能达到压力上去

    是否会话保持

  • 接上篇单元测试

    2008-10-20 13:58:12


    l
    待测试对象及辅助对象在@Before方法中初始化。
    l全局资源可以在@BeforeClass方法中初始化。
    l全局资源通常启动缓慢,如数据库,Web服务器,放入@BeforeClass使之仅初始化一次加快测试速度。
    l要测试一个方法应当编写多个测试方法,每个测试方法各有侧重。
    l测试方法要覆盖所有可能抛出异常的情况
    当遇到错误,最好的分析步骤是
    l检查环境。
    数据库链接,数据库中的数据是否正常?配置是否正常?网络是否正常?
    l检查测试代码。
    参数是否传错误?断言的预期值是否错误?
    l检查程序。
    debug
    接口:
    public interface ICalculatorService{
    /**
     * 计算器中加法功能的计算
     * @return 参数 a,b的和
     */
    public double add(double a,double b);
    }
    实现:
    public class CalculatorService implements ICalculatorService{
    public double add(double a, double b){
    return a+b;
    }
    }
    基类:
    Public class BaseCase{
    ICalculatorService calculotorService;
    Public BaseCase(){
    calculatorService = new CalculatorService();
    }
    }
    public class AddTest extends BaseCase{
    @BeforeClass
     public static void beforeClass() {}
    @AfterClass
     public static void afterClass(){}
    @Before
    public void before() {}
    @After
     public void after(){}
    /**
     * 测试输入为0的情况
     * 预期值为0
     */
    @Test
     public void testZero(){
    double result = calculatorService.add(0,0); Assert.assertEquals(0,result);
    }
    }
    例如组合测试计算器中的加减乘除的测试方法
    import org.junit.runner.RunWith;
     import org.junit.runners.Suite;
     import org.junit.runners.Suite.SuiteClasses;
     @RunWith(Suite.class)
     @SuiteClasses(value = { AddTest.class })
     @SuiteClasses(value = { MinusTest.class })
     @SuiteClasses(value = { MultiplyTest.class })
     @SuiteClasses(value = { divideTest.class })
     public class AllTests {
     }
    lpublic class BaseCase {
    // 获取日志对象,并提供给它该类的日志信息
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
    //初始化要测试的接口
     protected static RefundCommonAO refundCommonAO;
    //初始化要测试的接口
    protected static RefundFlowAO refundFlowAO;
    //声明数据库链接文件
    protected static String DB_PROPERITY = "db.properties";
    //声明JdbcTemplate以便对数据库进行操作
    protected static JdbcTemplate jdbcTemplate;
    l//获取spring类路径相关上下文的引用
    lstatic{
    lApplicationContext context = new ClassPathXmlApplicationContext(new String[]{
    l"biz-manager.xml",
    l"spring-persistence.xml",
    l"spring-refund-dao.xml",
    l"spring-refund-payway.xml",
    l"spring-refund-process.xml",
    l"spring-refund-service.xml",
    l"tc-client.xml",
    l"config_currect.xml",
    l"spring-refund-ao.xml"
    l});
    l//从上下文中获取被测试接口的引用。
    lrefundCommonAO = (RefundCommonAO)context.getBean("refundCommonAO");
    l
    l//从上下文中获取被测试接口的引用。
    lrefundFlowAO = (RefundFlowAO)context.getBean("refundFlowAO");
    l
    l//从上下文中获取jdbcTemplete的引用,以便对数据库进行操作
    ljdbcTemplate = (JdbcTemplate)context.getBean("jdbcTemplate");}
    l}
    l//如果测试的接口需要有数据源,那么需要调用此方法,把在excel里准备的测试数据添加到DB_PROPERITY中所定义的数据库中。
    public static void createTestData(String fileName) throws Exception{
    URL excelUrl = BaseCase.class.getClassLoader().getResource(fileName);
    URL dbUrl = BaseCase.class.getClassLoader().getResource(DB_PROPERITY);
    DataGenerator.tearDown(new String[]{excelUrl.getFile()}, dbUrl.getFile());
    DataGenerator.setUp(new String[]{excelUrl.getFile()}, dbUrl.getFile());
    l}
    l//调用此方法,删除调用createTestData添加的数据。以清理测试产生的垃圾数据。
    public static void deleteTestData(String fileName) throws Exception{
    URL excelUrl = BaseCase.class.getClassLoader().getResource(fileName);
    URL dbUrl = BaseCase.class.getClassLoader().getResource(DB_PROPERITY);
    DataGenerator.tearDown(new String[]{excelUrl.getFile()}, dbUrl.getFile());
    }
    l
    l//在测试类中可以调用此方法对数据库进行操作
    public void operaterData(String sql){
    jdbcTemplate.execute(sql);
    }
    public class QueryInfoByActionTest extends BaseCase{
    RefundInfoQuery query;
     //退款id 6000002
    private final static long PARAM = InstanceClass.REFUND_ID_6000002;
    /**
     * 调用BaseCasecreateTestData在数据库中添加excel中已准备好的测试数据。
           * instanceClass.INIT_DATA_SOURCE =  excel文件名
     */
    @BeforeClass
    public static void createTestData() throws Exception{
    createTestData(InstanceClass.INIT_DATA_SOURCE);
    }
    //在所有的测试方法都执行之后,清理createTestData保存进数据库中的数据
    @AfterClass
    public static void deleteTestData() throws Exception{
    deleteTestData(InstanceClass.INIT_DATA_SOURCE);
    }
    //在每个测试方法运行之前,执行此方法。这里是用来准备测试参数的。
    @Before
    public void before(){
    query = new RefundInfoQuery();
    query.setAction(RefundConstants.VIEW_REFUND_DETAIL); //查看退款详情
    query.setBizOrderId(PARAM);
    query.setRefundId(PARAM);
    query.setUserNumId(1234);
    l
    }
    /**
     * 查看输入参数在数据库中不存在时的返回值
     * 预期success = false; resultCode = NO_REFUND_RECORD
    *  说明:InstanceClass.DELETE_REFUND_BY_ID = "delete from tc_refund_trade t where t.REFUND_ID = ";
    *  说明:long InstanceClass.REFUND_ID_60159864 =  60159864 (REFUND_ID的值)
     */
    @Test
    public void  testRefundIsNotExit(){
      long param = InstanceClass.REFUND_ID_60159864;
      super.operaterData(InstanceClass.DELETE_REFUND_BY_ID + param ); //删除退款表中refundID60159864的数据
    query.setRefundId(param);  //把已删除掉的refundId传到参数中进行查询
    ResultSupport result = refundCommonAO.queryInfoByAction(query); //调用被测方法把参数传进去
    //以下为断言:检查返回值与预期值是否相等
    Assert.assertFalse(result.isSuccess());
    Assert.assertEquals(RefundResultCode.NO_REFUND_RECORD, result.getResultCode());
    }
    }


  • 单元测试junit初学

    2008-10-20 11:50:08



    l
    一 实例
    目前
    junit测试为接口中的方法。根据javadoc中的文字说明编写junit测试方法。
    l接口:
    lpublic interface ICalculatorService{
    /**
     * 计算器中加法功能的计算
     * @return 参数 a,b的和
     */
    public double add(double a,double b);
    }
    l实现:
    lpublic class CalculatorService implements ICalculatorService{
    public double add(double a, double b){
    return a+b;
    }
    }
    二 步骤
    l第一步: 编写一个基类以创建测试环境(可选)。
    l第二步: 编写测试类。
    l第三步: 在该测试类中编写测试方法。
    l第四步: 在测试方法中调用被测方法。
    l第五步: 验证预期结果与返回的结果是否一致。
    l第六步: 执行测试 查看测试结果。
    lTestSuite来组合测试。
    三 各步骤详解
    l第一步: 编写一个基类以创建测试环境(可选)。
    l此类会调用系统启动时的配置文件,模拟系统启动。也可以获取目标接口实现类的引用和编写测试代码时需要的公用方法。测试类的实现都需要继承此基类。
    l
    l例如如果计算机服务器有加减乘除等方法,我们可以把接口的引用放入基类,以方便各测试类调用。
    lPublic class BaseCase{
    ICalculatorService calculotorService;
    Public BaseCase(){
    calculatorService = new CalculatorService();
    }
    }
    l第二步:编写测试类。
    如果有基类要继承此基类完成测试环境的初始化。
    l通常情况下为接口中的每个方法编写一个测试类。
    l测试类的名字推荐为 被测方法名 + Test
    l例如,测试计算器中加法功能的测试类为:
    lpublic class AddTest  extends BaseCase{…}
    l第三步:在该测试类中编写测试方法。
    l(可选)编写初始化和清理方法,并标注为:@Before@After
    l@Before
         public void before() {}
    l@After
         public void after(){}
    l(可选)编写全局化初始化和清理方法,并标注为:@BeforeClassAfterClass
    l@BeforeClass
         public static void beforeClass() {}
    l@AfterClass
         public static void afterClass() {}
    l编写一个或多个测试方法,标注为@Test
    l推荐测试方法名字为 test + 测试点,如以下方法为测试计算器加法功能中输入为0的情况。
    §@Test
         public void testZero(){...}
    l第四步:在测试方法中调用接口中要测试的方法。
    l可以在BaseCase中已经引用了目标接口的实现类。在测试方法中可直接调用。也可以在测试类中直接引用目标接口的实现类。
    l例如引用计算器类中实现加法功能的add()方法。参数为两个加数。
    l@Test
      public void testZero(){
         double result = calculatorService.add(0,0);
      }
    l第五步:使用Assert所提供的静态方法验证方法调用返回的结果。
    lAssert超类所提供的核心方法如下:
    lassertEquals
    §断言两个对象相等,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    §例如计算器加法功能的测试可以使用一下验证:
    §Assert.assertEquals(0,result);
    lassertSame
    §断言两个引用指向同一个对象,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lassertNotSame
    §断言两个引用指向不同对象,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lassertTrue
    §断言条件为真,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lassertFalse
    §断言条件为假,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lassertNull
    §断言对象为null,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lassertNotNull
    §断言对象不为null,若不满足,方法抛出带有相应信息的AssertionFailedError异常。
    lFail
    §让测试失败,并给出指定信息。
    l测试异常需要指定期待的异常类(expected=?)
    l@Test  expected=NullPointerException.class
    l测试超时需要指定超时时间(timeOut=?)

    l第六步:执行测试 查看测试结果。
    leclipse 测试类中点右键run asjunit Test执行测试。
    l 测试结果分为一下三种。
    lPass:测试通过
    lFailure:测试失败。
    lError: 由异常引起的测试错误
    lTestSuite来组合测试。
    lTestSuite来把所有的测试类组合在一起执行。
    l如把计算器功能中的加减乘除的测试方法组合起来执行测试:
         import org.junit.runner.RunWith;
     import org.junit.runners.Suite;
     import org.junit.runners.Suite.SuiteClasses;
     @RunWith(Suite.class)
     @SuiteClasses(value = { AddTest.class })
     @SuiteClasses(value = { MinusTest.class })
     @SuiteClasses(value = { MultiplyTest.class })
          @SuiteClasses(value = { divideTest.class })
     public class AllTests {
     }
    幻灯片 15
    l确保开发人员编写的被测接口方法的javadoc详细完整。
    l必须包含的内容有:场景,输入参数,输入参数的返回结果,预期抛出的异常。
    lTC中要准备测试所需要的各种条件。
    l调用要测试的方法。
    l验证被测方法的返回值和所预期的是否一致。
    l完成后,使用@After@AfterClass方法中编写代码清理各种资源。

  • RandomNumber的用法 参数化(转)

    2008-07-27 20:35:09

     

    使用随机数来进行参数化
            对于选择航班这个测试步骤的参数化来说会有所不同,因为航班会跟随所选择的起点和终点而变化,因此,需要做特殊的处理。如下代码所示:
    ' 取得航班列表的行数
    ItemCount = Window("Flight Reservation").Dialog("Flights Table").WinList("From").GetItemsCount
    ' 随机选取其中一项
    SelectItem = RandomNumber(0, ItemCount)
    ' 选择航班
    Window("Flight Reservation").Dialog("Flights Table").WinList("From").Select SelectItem
            先通过访问GetItemsCount属性,获取航班列表的行数,然后使用RandomNumber随机选取其中一项,最后,再通过Select方法选择航班。参数化后的测试步骤如图8.9所示。

    图8.9  参数化后的测试步骤

            提示:使用随机数也是测试脚本参数化的一种重要方法,在QTP的测试代码中,可用RandomNumber来实现,在关键字视图编辑的界面如图8.10所示,其效果与在脚本中直接编辑是一样的。

    图8.10  选择参数化方式为“Random Number”
    8.2.4  参数化检查点
            测试脚本的最后一个测试步骤是检查订票记录中的航班终点是否正确,同样需要进行适当的参数化,方法如下:
    (1)单击检查点所在测试步骤的“Value”列中的单元格,如图8.11所示。

    图8.11  设置检查点参数
    (2)单击旁边的按钮,则出现如图8.12所示的界面。

     

  • 如何从页面url获取想要的信息

    2008-07-25 19:23:06

    在做脚本的过程中 要做相应的数据库检查 这时就要获得where条件

    比如脚本执行后进入到一个页面,该页面的url里含有我想要的数据 如:http://auction1.daily.taobao.net/auction/item_detail-0db1-c75a9b8f78914acd87dbd00f09096f7f.jhtml

    其中的 c75a9b8f78914acd87dbd00f09096f7f 是我想要的数据

    解决办法:1.首先获得该页面的url 用 id=browse("").page("").GetROProperty("url")

            2.然后截取想要的字符串 mid(id,59,32)

    mid的用法介绍

    Mid 函数
    从字符串中返回指定数目的字符。
    Mid(string, start[, length])
    参数
    string
    字符串表达式,从中返回字符。如果 string 包含 Null,则返回 Null。
    Start
    string 中被提取的字符部分的开始位置。如果 start 超过了 string 中字符的数目,Mid 将返回零长度字符串 ("")。

  • 创建数据源

    2008-04-27 20:43:24

    在控制面板的管理工具中 创建数据源

    选择system dsn tab

    点add 操作 选择microsoft odbc for oracle

    输入数据源的名字.这个要跟脚本里的参数名一致(下面例子里面的forum)

    topsql = "select count(*) from tbf_thread where forum_id = '85' and thread_type = '2'"
    topcount = getone1(forum,topsql)

    脚本里怎么连接数据库

    Function OpenConnection1 (dataSource)
     Set cnn = CreateObject("ADODB.Connection")
      cnn.ConnectionString = "Provider=MSDASQL.1;Persist Security Info=true;User ID=id;Password=pwd;Data Source=" &dataSource
        cnn.Open
     Set OpenConnection1 = cnn
    End Function

    从数据库中获取数据

    Function GetOne1(datasource,sql)
     cnn = OpenConnection1(dataSource)
     Set rs = CreateObject("ADODB.RecordSet")
     rs.open sql,cnn,1,1
     GetOne1 = null
     If Not rs.eof Then
      GetOne1 = rs.Fields(0).value
      'msgbox GetOne
     End If
    ' rs.close
     Set rs = nothing
    End Function

    脚本中引用这个函数

    sql = "select count(*) from 表 where 条件"
    topcount = getone1(跟数据源名字一样,topsql)

  • QTp脚本 把结果输出到测试报告的方法

    2008-04-27 18:46:12

    在调试脚本的过程中遇到了个问题...

    判断某个单选框是否被选中

    第一步先要找出你要判断哪个单选框,通过webradiogroup的value值来判断

    v=Browser("编辑个人资料").Page("编辑个人资料").WebRadioGroup("_fmf.edit._0.si").GetROProperty("value")
    If  v=3 Then
    a=Browser("编辑个人资料").Page("编辑个人资料").WebRadioGroup("_fmf.edit._0.si").GetROProperty("checked")
      'If a=1 Then
       Reporter.ReportEvent 0, "单选框被选中", "The user-defined step pass."
       end if '
    else if v<>3 then
       Reporter.ReportEvent 1, "单选框未被选中", "The user-defined step pass."
      End If
      End If

    如果取出来的value值不等于3 其实就是说这个单选框没被选中 就输出报告

    中间注释掉的语句其实可以不用写的 因为qtp只能找到被选中的那个单选框的value,如果这个单选框没被选中.qtp自然也是找不到的 (这个也是调试脚本发现的结论..)

    if这些个判断因为不能在测试报告中反应出来是成功了还是失败了.所以可以把这个结果输出到测试报告中.

    方法:

    在test result中报告测试结果。

    语法

    Reporter.ReportEvent EventStatus, ReportStepName, Details [, in]

     Argument  Type  Descrīption
     EventStatus  Number or pre-defined constant
    状态值:

    0 或 micPass:将本步骤的运行结果状态设置为“Pass”,并向Result中产生报告信息。

    如果想在报告中生成“通过”报告,用本状态值。

    1 或 micFail: 将本步骤的运行结果状态设置为“Fail”,并向Result中产生报告信息。当脚本中运行本语句时,整个测试的结果状态是“fails”。

    如果想在报告中生成“失败”报告,用本状态值。如果运行了本语句,则整个测试的状态为“Fail”。

    2 或 micDone:仅向Result中产生报告信息,但不影响整个测试的结果状态。

    如果想在报告中生成“完成”报告,用本状态值。

    3 或 micWarning: S向Result中产生报告信息,但是不会中断测试的运行,也不影响测试的 pass
    /fail status。

    如果想在报告中生成“警告”报告,用本状态值。运行这个语句后,整个测试结果状态为“Warning”。
     
     ReportStepName  String 将在报告中显示的步骤名称(object name). 
     Details  String 报告的详细信息。这些信息是本条报告的“Details”信息。
     in  N/A  Not in use


    举例: 下面的例子使用ReprotEvent方法来报告一个失败信息。

    Reporter.ReportEvent 1, "Custom Step", "The user-defined step failed."

  • 小知识汇总验证 验证点是否正确.

    2008-02-18 18:12:59

    验证检查点返回的内容是否正确可以这样写

    a = Browser("").Page("").Frame("reportFrame").Check (CheckPoint("列表"))
    如果你不了解a的值true还是个constant.你可以用msgbox a 语句得到结果

    因为a返回的是true or false的形式

    所以下面的判断就可直接写 if true then......

  • 登录界面密码输入动作无法录制下来

    2008-02-18 17:04:15

    利用mi提供的web定票功能来实践个问题.结果发现登录界面的密码输入动作录制不下来

    解决方法:

    打开object repositoris 添加密码输入框的webedit到对象库里

    虽然对象添加进去了,但是脚本里米有引用这个对象还是没用的

    所以添加这样一行:Browser("Sign-on: Mercury Tours").Page("Sign-on: Mercury Tours").WebEdit("password").Set "123"

    问题解决了...

Open Toolbar