测试之路,与你同行!

发布新日志

  • java return作用

    2012-02-21 12:25:11

    return的常用作用有以下两种
    一种是返回参数所用的关键字,假如一个有返回值的方法执行完了之后需要返回一个参数,示例:public string functionTest(){
             String a = "abc";
             return a;
    }
    那么这个方法被调用之后就会返回一个值为abc的字符串,string result = functionTest();
    
    
    第二种用法是,代码执行到此处终止。
    比如当代码执行到某个地方会出现几种结果,然后其中一种结果就不能执行后续代码,这时候在那里加上一个return就可以终止后面的代码执行。
  • MVC

    2012-02-14 14:17:43

  • Spring3 MVC 深入研究

    2012-02-14 13:12:14

    原文地址: http://elf8848.iteye.com/blog/875830

    一、前言:

    大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了。Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀。

    官方的下载网址是:http://www.springsource.org/download   (本文使用是的Spring 3.0.5版本)

     

    Struts2也是比较优秀的MVC构架,优点非常多比如良好的结构。但这里想说的是缺点,Struts2由于采用了值栈、OGNL表达式、struts2标签库等,会导致应用的性能下降。Struts2的多层拦截器、多实例action性能都很好。可以参考我写的一篇关于Spring MVC与Struts2与Servlet比较的文章 http://elf8848.iteye.com/admin/blogs/698217

     

    Spring3 MVC的优点:

    1、Spring3 MVC的学习难度小于Struts2,Struts2用不上的多余功能太多。呵呵,当然这不是决定因素。

    2、Spring3 MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)

    3、Spring3 MVC的灵活是你无法想像的,Spring的扩展性有口皆碑,Spring3 MVC当然也不会落后,不会因使用了MVC框架而感到有任何的限制。

     

    Struts2的众多优点:略...   (呵呵,是不是不公平?)

     

    众多文章开篇时总要吹些牛,吸引一下读者的眼球,把读者的胃口调起来,这样大家才有兴趣接着往后看。本文也没能例外。不过保证你看了之后不会后悔定有收获。

     

     

    二、核心类与接口:

     

    先来了解一下,几个重要的接口与类。现在不知道他们是干什么的没关系,先混个脸熟,为以后认识他们打个基础。

     

    DispatcherServlet   -- 前置控制器

     

    HandlerMapping接口 -- 处理请求的映射

    HandlerMapping接口的实现类:

    SimpleUrlHandlerMapping  通过配置文件,把一个URL映射到Controller

    DefaultAnnotationHandlerMapping  通过注解,把一个URL映射到Controller类上

     

    HandlerAdapter接口 -- 处理请求的映射

    AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

     

    Controller接口 -- 控制器

    由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,

    所以我们并没有用到这个接口。

     

     

     

    HandlerInterceptor 接口--拦截器

    无图,我们自己实现这个接口,来完成拦截的器的工作。

     

     

    ViewResolver接口的实现类

    UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理

    InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

     

    View接口

    JstlView类

     

    LocalResolver接口

     

    HandlerExceptionResolver接口 --异常处理

    SimpleMappingExceptionResolver实现类

     

     

    ModelAndView类

    无图。

     

     

     

     

     

    三、核心流程图

     

    本图是我个人画的,有不严谨的地方,大家对付看吧。总比没的看强。

     

     

     


    四、DispatcherServlet说明

     

    使用Spring MVC,配置DispatcherServlet是第一步。

    DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。

    DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。

     

    “某某规则”:是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。

     

    先来看第一个例子:

    Xml代码  收藏代码
    1. <web-app>  
    2.     <servlet>  
    3.         <servlet-name>example</servlet-name>  
    4.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    5.         <load-on-startup>1</load-on-startup>  
    6.     </servlet>  
    7.     <servlet-mapping>  
    8.         <servlet-name>example</servlet-name>  
    9.         <url-pattern>*.form</url-pattern>  
    10.     </servlet-mapping>  
    11. </web-app>  

     <load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servletp容器一起启动。

     <url-pattern>*.form</url-pattern> 会拦截*.form结尾的请求。

     

     <servlet-name>example</servlet-name>这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中,关于key,以后说明。

     

    在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。

     

     

    第二个例子:

    Xml代码  收藏代码
    1. <servlet>  
    2.     <servlet-name>springMVC</servlet-name>  
    3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    4.     <init-param>  
    5.         <param-name>contextConfigLocation</param-name>  
    6.         <param-value>classpath*:/springMVC.xml</param-value>  
    7.     </init-param>  
    8.     <load-on-startup>1</load-on-startup>  
    9. </servlet>  
    10. <servlet-mapping>  
    11.     <servlet-name>springMVC</servlet-name>  
    12.     <url-pattern>/</url-pattern>  
    13. </servlet-mapping>  

    指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。

    其中<param-value>**.xml</param-value> 这里可以使用多种写法
    1、不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
    2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
    3、<param-value>classpath*:springMVC-mvc.xml</param-value>
    4、多个值用逗号分隔

     


    Servlet拦截匹配规则可以自已定义,Servlet拦截哪种URL合适? 

    当映射为@RequestMapping("/user/add")时:
    1、拦截*.do,例如:/user/add.do,弊端:所有的url都要以.do结尾。不会影响访问静态文件。
    2、拦截/app/*,例如:/app/user/add,弊端:请求的url都要包含/app,@RequestMapping("/user/add")中不须要包含/app。
    3、拦截/,例如:/user/add,弊端:对jpg,js,css静态文件的访问也被拦截不能正常显示。后面有解决办法。
    4、拦截/*,可以走到Action中,但转发到jsp时再次被拦截,不能访问到jsp。

     

     

    五、双亲上下文的说明

     

    如果你使用了listener监听器来加载配置,一般在Struts+Spring+Hibernate的项目中都是使用listener监听器的。如下

    Java代码  收藏代码
    1. <listener>   
    2.   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
    3. 查看(700) 评论(0) 收藏 分享 管理

    4. java回调

      2012-02-13 23:09:34

      回调的通俗理解:你有一个复杂的问题解决不了,打电话给你的同学,你的同学说可以解决这个问题,但是需要一些时间,那么你不可能一直拿着电话在那里等,你会把你的电话号码告诉他,让他解决之后打电话通知你。即回调就是体现在你的同学又反过来拨打你的号码。 拿这个例子类比Ajax中的回调机制以及Spring中HibernateTemplate用到的回调+模板机制,可以更容易地理解回调机制。 
      Spring中HibernateTemplate的回调机制与模板方法 

      HibernateTemplaet的源码很复杂,我们可以写一段简单的代码来模拟一下: 

      Java代码  收藏代码
      1. interface CallBack{   
      2.     public void doCRUD();   
      3. }  
      4.   
      5. public class HibernateTemplate {   
      6.       
      7.     public void execute(CallBack action){  
      8.         getConnection();  
      9.         action.doCRUD();  
      10.         releaseConnection();  
      11.     }  
      12.    
      13.     public void add(){  
      14.          execute(new CallBack(){  
      15.             public void doCRUD(){  
      16.                 System.out.println("执行add操作...");  
      17.             }  
      18.          });  
      19.     }  
      20.       
      21.     public void delete(){  
      22.          execute(new CallBack(){  
      23.             public void doCRUD(){  
      24.                 System.out.println("执行delete操作...");  
      25.             }  
      26.          });  
      27.     }   
      28.   
      29.     public void getConnection(){  
      30.         System.out.println("获得连接...");  
      31.     }  
      32.       
      33.     public void releaseConnection(){  
      34.         System.out.println("释放连接...");  
      35.     }  
      36.       
      37. }  



      类比:execute方法可以体现出模板模式。以add方法为例,调用execute方法就相当于你打电话给你的同学,但是你的同学说需要时间,就像execute方法需要首先获得连接一样,于是你把CallBack匿名类传递给它,在它获得连接之后会执行你的add操作,这就相当于你把电话号码告诉你的同学,他解决问题之后再打给你一样。当然这种通俗理解不能很好地体现出Spring中的Callback模式和Template模式合用的简单与灵活,这里只是利于理解一点

      一.回调是异步的一种表现形式

      二.什么时候使用回调?

           答:1.请求服务器的时候使用回调。

               2.创建查询窗口的时候

                  例如:某一需求:点击“属性查询”,弹出查询界面,输入查询条件,点击提交;根据查询条件请求服务;成功获得请求信息,失败提示。

                 分析:当点击属性查询的时候创建窗口,同时传入回调参数,用于在点击提交的时候执行回调,再在回调中执行查询方法

    5. Spring的queryForList

      2012-02-13 14:34:04

      对于一般的hibernate查询,返回的往往是一个我们熟悉的list,比如:gciLogs = criteria.list();那么这里返回的就是类型是某一个实体的list,get(i)就是这样一个实体,也就是一个记录,然后还可以取得字段值。

      而spring的jdbcTemplate.queryForList( sql );先返回一个object,这个object里面是一个map,对应的key就是数据库里面的字段名,value就是我们要取的值了!如:

      1. txnLogList = template.queryForList( sql2 );  
      2. Object jf=txnLogList .get(i);     
      3. Map txnLog=(Map)jf;   
      4.   
      5. txnLog.get("status").toString() //就是字段status的值了  

      不这样取的话,就会爆  <!-- google_ad_section_start -->java.lang.ClassCastException: org.apache.commons.collections.map.ListOrderedMap

      <!-- google_ad_section_end -->


    6. java的StringBuffer类

      2012-02-13 13:41:52

      StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。

               所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。

               StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。

      但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。

               另外由于StringBuffer是线程安全的,关于线程的概念后续有专门的章节进行介绍,所以在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。

               1StringBuffer对象的初始化

      StringBuffer对象的初始化不像String类的初始化一样,Java提供的有特殊的语法,而通常情况下一般使用构造方法进行初始化。

      例如:

               StringBuffer s = new StringBuffer();

      这样初始化出的StringBuffer对象是一个空的对象。

      如果需要创建带有内容的StringBuffer对象,则可以使用:

               StringBuffer s = new StringBuffer(“abc”);

      这样初始化出的StringBuffer对象的内容就是字符串”abc”

      需要注意的是,StringBufferString属于不同的类型,也不能直接进行强制类型转换,下面的代码都是错误的:

               StringBuffer s = “abc”;               //赋值类型不匹配

               StringBuffer s = (StringBuffer)”abc”;    //不存在继承关系,无法进行强转

      StringBuffer对象和String对象之间的互转的代码如下:

               String s = “abc”;

               StringBuffer sb1 = new StringBuffer(“123”);

               StringBuffer sb2 = new StringBuffer(s);   //String转换为StringBuffer

               String s1 = sb1.toString();              //StringBuffer转换为String

               2StringBuffer的常用方法

      StringBuffer类中的方法主要偏重于对于字符串的变化,例如追加、插入和删除等,这个也是StringBufferString类的主要区别。

      aappend方法

               public StringBuffer append(boolean b)

      该方法的作用是追加内容到当前StringBuffer对象的末尾,类似于字符串的连接。调用该方法以后,StringBuffer对象的内容也发生改变,例如:

                        StringBuffer sb = new StringBuffer(“abc”);

                         sb.append(true);

               则对象sb的值将变成”abctrue”

      使用该方法进行字符串的连接,将比String更加节约内容,例如应用于数据库SQL语句的连接,例如:

                         StringBuffer sb = new StringBuffer();

                         String user = “test”;

                         String pwd = “123”;

                         sb.append(“select * from userInfo where username=“)

                          .append(user)

                          .append(“ and pwd=”)

                          .append(pwd);

               这样对象sb的值就是字符串“select * from userInfo where username=test and pwd=123”。

      bdeleteCharAt方法

               public StringBuffer deleteCharAt(int index)

      该方法的作用是删除指定位置的字符,然后将剩余的内容形成新的字符串。例如:

               StringBuffer sb = new StringBuffer(“Test”);

               sb. deleteCharAt(1);

      该代码的作用删除字符串对象sb中索引值为1的字符,也就是删除第二个字符,剩余的内容组成一个新的字符串。所以对象sb的值变为”Tst”

      还存在一个功能类似的delete方法:

               public StringBuffer delete(int start,int end)

      该方法的作用是删除指定区间以内的所有字符,包含start,不包含end索引值的区间。例如:

               StringBuffer sb = new StringBuffer(“TestString”);

               sb. delete (1,4);

      该代码的作用是删除索引值1(包括)到索引值4(不包括)之间的所有字符,剩余的字符形成新的字符串。则对象sb的值是”TString”

                         cinsert方法

                                  public StringBuffer insert(int offset, boolean b)

                                  该方法的作用是在StringBuffer对象中插入内容,然后形成新的字符串。例如:

                                           StringBuffer sb = new StringBuffer(“TestString”);

                                           sb.insert(4,false);

      该示例代码的作用是在对象sb的索引值4的位置插入false值,形成新的字符串,则执行以后对象sb的值是”TestfalseString”

                         dreverse方法

                                  public StringBuffer reverse()

      该方法的作用是将StringBuffer对象中的内容反转,然后形成新的字符串。例如:

               StringBuffer sb = new StringBuffer(“abc”);

               sb.reverse();

      经过反转以后,对象sb中的内容将变为”cba”

                         esetCharAt方法

                                  public void setCharAt(int index, char ch)

                                  该方法的作用是修改对象中索引值为index位置的字符为新的字符ch。例如:

                                           StringBuffer sb = new StringBuffer(“abc”);

                                           sb.setCharAt(1,’D’);

                                  则对象sb的值将变成”aDc”

                         ftrimToSize方法

                                  public void trimToSize()

      该方法的作用是将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费。

               总之,在实际使用时,StringStringBuffer各有优势和不足,可以根据具体的使用环境,选择对应的类型进行使用。

    7. junit中的assert方法

      2012-02-09 18:32:55

      JUnit中的assert方法全部放在Assert类中,现在总结一下经常用到的junit类中assert方法。 
      1.assertTrue/False([String message],boolean condition) 判断一个条件是true还是false。 
      2.fail([String message,]); 失败,可以有消息,也可以没有消息。 
      3.assertEquals([String message],Object expected,Object actual); 判断是否相等,可以指定输出错误信息。 

      4.assertNotNull/Null([String message],Object obj); 判读一个对象是否非空(非空)。 
      5.assertSame/NotSame([String message],Object expected,Object actual); 判断两个对象是否指向同一个对象。看内存地址。 
      另外还有其他的几个Annotation: 
      @Before: 
      使用了该元数据的方法在每个测试方法执行之前都要执行一次。 

      @After: 
      使用了该元数据的方法在每个测试方法执行之后要执行一次。 

      注意:@Before和@After标示的方法只能各有一个。这个相当于取代了JUnit以前版本中的setUp和tearDown方法。 

      @Test(expected=*.class) 
      在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,通过@Test元数据中的expected属性。expected属性的值是一个异常的类型 

      @Test(timeout=xxx): 
      该元数据传入了一个时间(毫秒)给测试方法, 
      如果测试方法在制定的时间之内没有运行完,则测试也失败。 

      @ignore: 
      该元数据标记的测试方法在测试中会被忽略。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法. 
    8. java对象序列化

      2012-02-08 14:05:15

      所谓对象序列化,就是将对象的状态转换成字节流,以后可以通过这些值再生成相同状态的对象。
      这个过程也可以通过网络实现,可以先在windows机器上创建一个对象,对其序列化,然后通过网络发给一台unix机器,然后在那里准确无误地重新“装配”。
      java对象序列化,可以通过让类实现java.io.Serializable接口可以将类序列化。
      序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。
      序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。
    9. oracle的sequence自增

      2012-02-08 13:28:44

      在Oracle数据库中,sequence等同于序列号,每次取的时候sequence会自动增加,一般会作用于需要按序列号排序的地方。

      1、Create Sequence

      (注释:你需要有CREATE SEQUENCE或CREATE ANY SEQUENCE权限)

      CREATE SEQUENCE emp_sequence

      INCREMENT BY 1 -- 每次加几个

      START WITH 1 -- 从1开始计数

      NOMAXVALUE -- 不设置最大值

      NOCYCLE -- 一直累加,不循环

      CACHE 10;

      只要定义了emp_sequence,你就可以用使CURRVAL,NEXTVAL

      CURRVAL=返回 sequence的当前值

      NEXTVAL=增加sequence的值,然后返回 sequence 值

      例如:

      emp_sequence.CURRVAL  emp_sequence.NEXTVAL  

      可以使用sequence的地方:

      · 不包含子查询、snapshot、VIEW的 SELECT 语句

      ·INSERT语句的子查询中

      ·NSERT语句的VALUES中

      ·UPDATE 的 SET中

    10. do yourself

      2012-02-07 13:49:09

      不要太敏感,做好自己就好了。
      不要在意别人的看法。
      你遇到的问题别人也会遇到。
      迷茫的时候,多做,实践。做了之后再看结果,然后反思

      岁寒,然后知松柏之后凋也!
      真正的做到全力以赴,尽力的投入。
      蘑菇定律。
      静候你的成功之门。
    11. contribution

      2012-01-19 12:43:03

      作为测试人员,要想成为优秀的测试人员,要具备硬实力和软实力。这些实力如何体现给我们的上司,从而获得加薪and升值呢?个人思考了以下几个方面:
      1、主管如何获知你的工作业绩
         平时做的都是繁琐的测试工作,怎样提炼出来说明自己的成长和成绩呢?
         业务的分享,比如新的需求,解决的需求问题,任何时候都不能脱离了业务,在适时的时候可以将新的业务分享给大家。
         测试报告,包括需求的探讨、疑惑,项目的风险,开发团队或其他团队对本项目的影响,目前缺陷的情况、测试执行情况等,这些都可以谈。总之涵盖的面不仅要多,而且要有深度。这个可以体现测试人员对全局的把控,从全方位的看问题,发现对质量的影响因素,有点像过程改进。深入一步的想,测试报告也是开发同学非常关注的,他们关注你的测试手段,关注他们的代码质量,关注缺陷是否明确,测试报告写的好也能获得开发同学的认可,有助于提升自己在团队中的影响力。
      2、测试技术提升的体现
         发现隐藏的bug。如何体现测试人员的价值,说白了就是发现有价值的bug。
         白盒测试的能力。这里就包括自动化测试了,熟练运用各种自动化测试工具,写自动化测试脚本来持续集成,保障产品的质量。
         解决问题的能力,运用其他测试技能,比如性能测试、探索测试发现问题,如果再具有追根究底,能发现问题的根因,协助开发同学一起改进那么就最好了。
      3、态度
          态度决定一切,这句话你一定要相信。自信、乐观、微笑的面对这个让人曾让你哭过、痛苦过的世界。
        

        
    12. interface testing design

      2012-01-18 14:31:44

      接口测试是项目测试的一部分 ,它测试的主要对象是接口 ,是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与所测系统之间以及内部各系统之间的交互点。测试的重点是检查数据交互、传递、和控制管理过程以及系统间的相互依赖关系等。
      如何设计接口测试用例?首先,明确出发点,和所有的测试一样 ,接口测试出发点是你要证明所测的程序是错误的。以这个出发点为导向 ,你的设计行为就会尽量朝这个方向,更易发现问题
      其次,选择好测试对象。对于一个系统做接口测试选择好的测试对象是接口测试关键。一个系统有无数的接口 ,每个接口如果分别测试 ,那将是很痛苦的一件事情,而且任何一个内部接口的变动 ,都将导致我们用例的不可用。

      可将这些最外层的接口分为两类:一类是数据进入系统的接口;一类是数据流出系统的接口。进入系统的接口实际是我们用例的执行调用的接口。可通过变化 参数对这些接口进行调用 ,模拟外部的使用;而流出的接口则是我们用例真正该验证的点。数据从哪里流出,流出时的状态如何 ,此时系统又是什么状态都是我们所应该验证的。  

      然后,确认完整的测试对象的功能:确认外部接口提供给使用这些接口的外部用户什么样的功能,外部用户真正需要什么样的功能。此两个功能一定要准确详细,用例的设计要严格按照测试对象功能设计才是正确的用例。

      最后当出发点、对象、功能都确定了,就可以真正设计用例了。下面详细介绍下如何去设计一个结构好、可读性高、渗透性强的接口测试用例。

       接口测试用例设计和测试用例设计一样,用例设计的内容应该包括:主要测试功能点、测试环境、测试数据、执行操作以及预期结果。

      1)接口测试环境分为两种:一种是程序内部的环境;一种是程序的所调用外部接口的环境。

      2)接口测试测试数据分为接口参数数据和用例执行所需系统数据。数据的设计、准备测试用例的数据上需要花费更多的心思。要通过好的测试数据使用例查 找问题。接口参数数据需对每个参数根据测试接口的实际的功能进行分析,在符合业务逻辑的情况下进行逻辑组合排列 ,不要遗漏了某些边界值和错误点的数据。每个用例执行所需系统数据和接口参数数据尽可能的采用不一样的数据 ,使用例更容易发现问题。    

      3)测试功能点,如果一个接口功能复杂时推荐对接口用例进行结构划分 ,这样子用例具有更好的可读性和维护性。接口划分原则为以接口提供的功能点的不同进行合适粒度的划分。同一功能点的用例又可根据测试环境的不同、数据的不同进行用例的填充。  

      4)接口测试用例执行操作非常简单,就是所测接口的调用。  

      5)预期结果验证,这也是接口用例设计的很关键的一步 ,应该细而不冗余。每个用例均需验证 ,避免一个用例中重复做相同的验证 ,提高测试用例的效率。    

      如何设计接口测试用例小例子:  

      简单划分可以按照2个基本组成要素进行划分:1. 参数 2. 业务

      以下为最简单的一种划分用例的方法,可能涵盖不全,但只为说明一种划分接口用例的方法方式以及需要考虑的测试用例的测试点


      为何要如此设计,是为了更好的将用例分类为程序规定型以及业务限制型,尽量的保证覆盖,尽量细化到点的划分形式来保证工作时间的预估和计划

      所有的自动化接口的测试用例  都基本围绕三部曲进行,传数据,执行,校验返回的数据和期望数据是否一致来构成每个简单的测试用例

      有清晰的线路和清晰的思维,才能做好整体测试的掌控。


    13. ======================

      2012-01-18 13:10:14

         集成测试,本文说的是对service层暴露的供外部系统调用的接口做的接口测试,因为涉及到外部系统,所以要通过接口的输入,调用接口,验证输出;即验证模块接口间的传参,所以统称为集成测试。
         集成测试,重点在集成测试设计,分两个维度:
         1、从业务角度
         从业务场景考虑,比如在网上买东西这个场景,下单、付款、卖家发货、买家确认收货这是一个业务场景,小范围的可以只覆盖创建订单这一个接口,验证订单创建成功就可;大范围一点的测试整个场景,包括:调创建订单接口创建订单,然后调付款接口付款,然后调发货接口发货,最后调确认收货接口确认收货。调完每个接口,要注意对接口返回值进行校验,这个相当于功能测试的执行测试用例时验证实际结果是否符合预期,集成测试的接口返回值的预期结果根据具体的业务校验返回值,通常对应数据库字段的更改,比如调完创建订单的接口,要验证订单的状态,订单的金额等等。写集成测试用例的时候,从小范围开始集成,逐步的扩大最后覆盖整个业务场景,这样一个集成测试用例就覆盖了多个接口。当然这样写有个问题,就是当脚本中的某个接口有问题调不通时,会导致整个脚本hold住。比如如果付款接口调不通,那么后续的发货、确认收货接口将不能执行。
         2、从接口角度
         从接口角度考虑,要考虑一些异常输入对接口的影响。通常在client端会做些参数合法性的校验,比如参数是否为空,不为负;然后service实现里也会做些校验,但是具体的参数之间的逻辑可能没有做校验,这时候就要写这些异常情况的传参,通过调接口查看返回值是否给出相应的异常信息。所以这时候脚本的预期结果就是有异常输出,具体的异常信息要看内部代码是如何判断的。从业务角度考虑哪些异常的传参会导致异常的输出,预期的期望结果可能不确定(只确定是异常,但是具体异常信息未知),调用接口会返回异常信息,这时候判断异常信息是否是合理的。
         以上,是做集成测试时需要考虑的。

       
    14. 关于QPS和TPS

      2012-01-12 10:16:16

      TPS:Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出,加上一次用户数据库访问。(业务TPS = CAPS × 每个呼叫平均TPS)

      TPS是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。

      一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量。系统整体处理能力取决于处理能力最低模块的TPS值。

      QPS:每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。

      对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。

       

      在DBA界,TPS和QPS是衡量数据库性能的2个重要参数。计算方法如下:

      TPS(每秒事务处理量)  INNODB 引擎

      (com_commit+com_rollback)/uptime

      QPS(每秒查询处理量)MyISAM 引擎

      Questions/uptime

    15. 数据库相关

      2012-01-12 10:01:22

      一、读写分离:(主库、备库)
          数据库挂了,查询原因发现是数据库读取压力太大了,此时就到了读写分离的时候。这个时候我们会配置一个servermaster节 点,然后配几个salve节 点,这样以来通过读写分离,使得读取数据的压力分摊到了不同的salve节点上面
           读写分离简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力。主数据库提供写操作,从数据库提供读操作,其实在很多系统中,主要是读的操作。当主数据库进行写操作时,数据要同步到从的数据库,这样才能有效保证数据库完整性。 
          Quest SharePlex就是比较牛的同步数据工具,听说比oracle本身的流复制还好,mysql也有自己的同步数据技术。mysql只要是通过二进制日志来复制数据。通过日志在从数据库重复主数据库的操作达到复制数据目的。这个复制比较好的就是通过异步方法,把数据同步到从数据库。

            主数据库同步到从数据库后,从数据库一般由多台数据库组成这样才能达到减轻压力的目的。读的操作怎么样分配到从数据库上?应该根据服务器的压力把读的操作分配到服务器,而不是简单的随机分配。mysql提供了MySQL-Proxy实现读写分离操作。不过MySQL-Proxy好像很久不更新了。oracle可以通过F5有效分配读从数据库的压力。

            上面说的数据库同步复制,都是在从同一种数据库中,如果我要把oracle的数据同步到mysql中,其实要实现这种方案的理由很简单,mysql免费,oracle太贵。好像Quest SharePlex也实现不了改功能吧。好像现在市面还没有这个工具吧。那样应该怎么实现数据同步?其实我们可以考虑自己开发一套同步数据组件,通过消息,实现异步复制数据。其实这个实现起来要考虑很多方面问题,高并发的问题,失败记录等。其实这种方法也可以同步数据到memcache中。听说oracle的Stream也能实现,不过没有试过。

      二、分库分表

          有一天,发现master撑不住了,负载很高,这时就要垂直分区了。

          也就是所谓的分库),比如将商品信息,用户信息,交易信息分别存储到不同的数据库中,同时还 可以针对商品信息的库采用mastersalve模式,OK, 通过分库以后,各个按照功能拆分的数据库写压力被分担到了不同的server上面,这样数据库的压力终于有恢复 到正常状态。但是是不是这样,我们就可以高枕无忧了呢?NO,这个NO, 不是我说的,是前辈们通过经验总结出来的,随着用户量的不断增加,你会发现系统中的某些表会变的异常庞大,比如好友关系表,店铺的参数配置表等,这个时候 无论是写入还是读取这些表的数据,对数据库来说都是一个很耗费精力的事情,因此此时就需要我们进行水平分区了(这就是俗话说的分表,或者说sharding.

      OK,上 面说了一大堆,无非就是告诉大家一个事实数据库是系统中最不容易scale out的一层,一个大型的互联网 应用必然会经过一个从单一DB server,Master/salve,再到垂直分区(分 库),然后再到水平分区(分表,sharding)的过程,而在这个过程中,Master/salve 以 及垂直分区相对比较容易,对应用的影响也不是很大,但是分表会引起一些棘手的问题,比如不能跨越多个分区join查 询数据,如何平衡各个shards的 负载等等,这个时候就需要一个通用的DAL框架来屏蔽底层数据存储对应用逻辑的影响,使得底层数据的访问对应用透明化。

      目前的情况来说,好多公司也正在从昂贵的高端存储(小型机+ORACLE)切换到MYSQL,切 换到MYSQL以 后,势必会遇到垂直分区(分库)以及水平分区(Sharding)的问题,因此目前根据自 己的业务特点也开发了自己的TDDL框架,此框架主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制。


    16. $$$$$$$$$$$$

      2012-01-11 16:58:29

      1、系统架构熟悉:(6达到)
      2、白盒测试,代码熟悉
      3、性能测试,让性能同学参与性能测试设计,进行性能调优,性能结果引起的代码改动,我们帮助评估影响范围:功能被影响了哪些范围。
      4、由代码改动正确识别影响点,风险。
      5、前端代码了解

      系统新需求不再增多,重要的是保证系统的稳定性、健壮性。

    17. ~~~~~~~~~~

      2011-12-26 17:06:21

          做了一段时间集成测试了,今天系统的回归了下集成测试。思考的问题如下:
          从产品角度考虑,现有的集成测试用例是否满足?
          从目前来看,是满足的。只是个人写的用例粒度比较粗的,按照业务流程去覆盖,考虑到了场景复杂情况下的异常流。每个用例都是一个业务流,而不是针对单个接口传参是否合法,校验值返回是否正确。本想再细化下粒度补写些用例,但从业务角度考虑,目前的脚本已经能满足对各接口的校验。再写的话从投入产出比考虑,不会很大。
          系统容灾、缓存方面的测试是否需要?
          对于系统容灾、缓存这块,目前测试还未涉及。系统容灾方面,这块可以在后续中考虑,缓存主要是查看要查询的信息是否在缓存中,如果缓存失效,是否可从数据库中读取等。缓存和数据库数据的交换。
          怎样从头搭建一个集成测试工程?
          这个目前还在思考,自己动手搭建,spring配置、bean的装配、数据库连接等设置,都需要学习下。
    18. 。。。。。。。,

      2011-12-17 15:17:26

          这两天在思考一个问题:人的成长。
          一样的起点进公司,为什么有的人成长得很快,甚有后来者为何别人可以超越自己,驾轻就熟。
          再待下去的结果是什么,自己的提升空间还有多大。
          决定一个人的成长有很多因素,内在的靠自身的专业技能、业内知识的积累,外在的有公司的上层是否支持、是否给予机会。这两者都很重要。有再多的技术能力,没有施展的空间,是件很悲哀的事。这种情况是否应该考虑跳槽呢,可是想想自身的能力还未成熟,也许跳槽只会从一个围城进入另一个围城,于是彷徨着。但待久了会越来害怕改变,害怕进入陌生的环境,害怕失败。
          有这种想法是很可怕的,因为当你犹豫彷徨的时候,你的竞争者仍在默默的努力着,唯有静下心来认真的分析自己的优势略施,看清自己和他人的差距,迎头赶上,才是正道。与其迷茫,不如奋力前行,越过这个坎你也许会觉得前边的风景更美。
         我的缺点:不够耐心、不够坚持、不善于表达、缺乏分析问题总结问题的能力、遇事不够沉着冷静。
         该怎么克服这些缺点那?我得好好想想。
    19. 。。。。。。。。。。。。。。。。

      2011-12-16 13:36:06

         回想想从毕业后进公司也有2年半了。从事测试工作已经这么长时间了,写测试方面的文章还比较少的。
         偶尔也看测试技术、逛测试论坛,但从没有静下心来总结总结属于自己的测试经验。
         目前软件测试领域大家都在说持续集成、敏捷。如果有人说我只做功能测试,可能会被别人取笑,自动化测试的时代如日中天了,单纯靠手工测试的时代终将被淘汰。
         那么怎么才能做好自动化测试呢?
         1、选用好的自动化框架,ruby也好,接口也好。成本、效率以及结果是关键。
         2、选择哪些用例适合自动化。将优先级高的用例优先实现自动化,ruby可以选择P0级别用例实现自动化,接口可以根据业务选择主流程来进行编写。这里,用例的设计思路很关键,用例设计得好就能发现隐藏的bug。
         3、自动化用例的维护。写用例只要熟悉语言、按照规则都可以写,但是要考虑用例的维护成本。接口方面,在接口更改(虽然发生可能性不大)、接口传参变化、返回值变化等问题时,需要修改脚本。ruby方面,在页面元素发生变化时,需要修改脚本。
         4、什么时候开始介入自动化测试?项目期间做,测试时间紧张,项目周期不允许,这是普遍面临的问题。如果能在流程上指定代码测试阶段,那么自动化测试在此时就可以介入,可以及早发现问题,尽早的持续集成起来。
         5、自动化测试做到什么程度算是终点。换句话说,什么时候我们认为自动化测试已经做足了,不需要再做了。这个目前考虑可能有点早,毕竟自动化还做得不是很完善,还是有很多不足需要改进的地方。
          自动化测试目前就想到以上几点,先讨论到此。
          接下来想想测试人员追求的是什么,还需要掌握哪些方面的技能。
          测试的核心价值是保障产品质量,产品质量有很多维度。功能、性能、安全、兼容性、可维护性、易用性等等。每一方面都是一个延伸到无限的空间。作为测试人员是把这些技能身兼一身还是选定一个深度去挖,我想这两个方向上都要抓,广度和深度。以上说的是测试技术方面的,还有测试管理方面的,我们日常接触的测试工作无时无刻不存在管理的因素,基于风险的测试、基于失效模式的测试、敏捷测试、和开发团队、其他团队间的合作,这些都需要测试人员有很高的把控能力。在现阶段测试人员已经成为全能型人才了。
         
    20. 厚积薄发

      2010-05-21 14:45:06

          


           昨天有同学打电话告诉我,他已经在公司实习了,将来的工资可以拿到月薪1万,做网络维护的。
      我说,真的吗? 他说,这样算一般了,待国企待遇好,很轻松。。。。。。
           我,脑袋闪过一个一个念头:跳槽。但马上打消了,觉得自己资本还远远不够,现在出去也是干苦力的。
      呵呵,先在这里坚持下来,扎扎实实的打好基础,还有很多东西要学。努力不放弃,厚积而薄发。
742/4<1234>
Open Toolbar