qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

编写Linux定时处理程序

  本文要写的Linux定时处理程序,想必这是很多Linux开发人员需要处理的问题。例如编写一个每天数据入库程序,编写一个定时邮件通知程序等等。

  对于定时处理程序,主要有两种方法可以实现。一种是使用crontab来做程序的定时启动,实现定时处理功能,一种是通过守护进程,间隔一段时间处理一次。

  下面对这两种实现做一些分析。

  crontab 是用来设置被周期性执行的指令。可以设置每隔一段时间执行一次程序,执行的方法是新建一个进程来进行处理。通过编写一个cronfile定时处理文件即可,例如每隔20分钟,执行一个backup操作:

*/20 * * * * /usr/bin/backup

  程序会在0分,20分,40分的时候启动一个/usr/bin/backup进程。

   crontab的优点是可以指定确切的时间点启动程序,可以准确控制每次执行的间隔(两次开始执行程序的时间间隔)。但是由于crontab每次是通过 新建一个进程来进行处理,如果间隔时间太短以至于上一个进程还未处理完,却已启动第二次处理,这时两个同样的进程在运行,必定就有一些资源的竞争和冲突。 如果通过进程本身的程序区兼容这种竞争,会让程序变得过于复杂。如果是对执行时间点没有很高要求,可以在每次启动程序时先做进程检查,如果检查到上次程序 还未处理完,跳过本次处理或者延后本次处理时间。crontab的另一个缺点就是无法监控到定时程序的执行(有的程序处理时间只有零点几秒,难以进行定时 扫描)。如果由于crontab本身漏洞或是系统本身问题引起crontab失效(生产机器发生过这种问题),这对于排查问题是比较麻烦的。

  编写定时程序的另一个方式是通过守护进程来实现,守护进程是一种脱离终端并且在后台运行的进程。用守护方式来编写定时程序就如:

while(true)
{
    process.....
    sleep(SLEEP_TIME);
}

   原理就是一个死循环,每次处理完之后休眠一段时间,再进行下一次处理。这种实现方式的好处就是可以避开资源的竞争,因为处理都是顺序进行,处理完一次之 后才进行下一次处理。并且守护进程是比较好监控,它是一个常驻内存的程序,只需定时扫描进程就可很好监控程序的执行。拥有常驻内存的特性,这可以大大减少 数据的载入操作,一次载入,永久使用。

  当然,编写守护程序来实现定时也有一些缺点,它并不适用于需要在确切时间点启动的程序(例如需要每天8点钟定时运行的程序),只能适合周期性,但是对运行时间点没有要求的处理。并且守护进行处理不能准确控制每次处理的间隔,它只能控制上次处理结束到下次启动的间隔。

   总的来说,这两个处理方式都能实现定时处理的任务,但是对于定时意义,还是有所差别。crontab的定时,是确定每一次执行时间点,每次启动进程的间 隔一致;而守护进程的定时,是确定上一次处理结束到下一次处理结束的时间间隔。使用时需要根据具体使用场景选择。crontab在定时处理上,相对灵活一 些,但需要注意资源竞争以及对执行的监控。而守护进程,效率相对高一些,并且方便监控,但需确定程序对于执行时间点是否有较高的要求。

posted @ 2012-09-04 09:52 顺其自然EVO 阅读(251) | 评论 (0)编辑 收藏

Java 动态代理(Proxy)

  动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对象对客户隐藏了实际对象。动态代理可以对请求进行其他的一些处理,在不允许直接访问某些类,或需要对访问做一些特殊处理等,这时候可以考虑使用代理。目前 Java 开发包中提供了对动态代理的支持,但现在只支持对接口的实现。

  主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。 Proxy 类主要用来获取动态代理对象,InvocationHandler 接口用来约束调用者行为。

  “写一个 ArrayList 类的代理,其内部实现和 ArrayList 中完全相同的功能,并可以计算每个方法运行的时间。”这是一份考题上的题目,没有答案,来看下实现:

  1. package example;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.concurrent.TimeUnit;  
  8. /** 
  9.  * ----------------------------------------- 
  10.  * @描述  TODO 
  11.  * @作者  fancy 
  12.  * @邮箱  fancydeepin@yeah.net 
  13.  * @日期  2012-8-27 <p> 
  14.  * ----------------------------------------- 
  15.  */ 
  16. public class ProxyApp {  


  17.     public static void main(String[] args){  
  18.           
  19.         //ArrayList代理,通过代理计算每个方法调用所需时间 
  20.         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  21.             ArrayList.class.getClassLoader(),   /*定义代理类的类加载器,用于创建代理对象,不一定必须是ArrayList,也可以是其他的类加载器*/ 
  22.             ArrayList.class.getInterfaces(),     /*代理类要实现的接口列表*/ 
  23.             new InvocationHandler() {            /*指派方法调用的调用处理程序,这里用了匿名内部类*/ 
  24.                   
  25.                 private ArrayList<Integer> target = new ArrayList<Integer>(); //目标对象(真正操作的对象) 
  26.                 /** 
  27.                  * <B>方法描述:</B> 
  28.                  * <p style="margin-left:20px;color:#A52A2A;"> 
  29.                  * 在代理实例上处理方法调用并返回结果 
  30.                  * @param proxy     代理对象(注意不是目标对象) 
  31.                  * @param method  被代理的方法 
  32.                  * @param args         被代理的方法的参数集 
  33.                  * @return <span style="color: #008080;"> 返回方法调用结果 </span> 
  34.                  */ 
  35.                 @Override 
  36.                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  37.                       
  38.                     long beginTime = System.currentTimeMillis();  //开始时间 
  39.                     TimeUnit.MICROSECONDS.sleep(1);  
  40.                     Object obj = method.invoke(target, args);          //实际调用的方法,并接受方法的返回值 
  41.                     long endTime = System.currentTimeMillis();   //结束时间 
  42.                     System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  43.                     return obj;   //返回实际调用的方法的返回值 
  44.                       
  45.                 }  
  46.                   
  47.             }  
  48.         );  
  49.         arrayListProxy.add(2);  
  50.         arrayListProxy.add(4);  
  51.         System.out.println("--------- 迭代 ---------");  
  52.         for(int i : arrayListProxy){  
  53.             System.out.print(i + "\t");  
  54.         }  
  55.     }  
  56. }




  后台打印输出结果:

[add] spend 2 ms
[add] spend 1 ms
--------- 迭代 ---------
[iterator] spend 1 ms
2 4

  从代码上来看,用到了匿名内部类,这样一来,InvocationHandler 只能用一次,如果多个地方都需要用到这样一个相同的 InvocationHandler,可以将其抽象出来成为一个单独的类:

  1. package test;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.util.concurrent.TimeUnit;  
  5. public class MyInvocationHandler implements InvocationHandler{  
  6.     private Object target; //目标对象      
  7.     public MyInvocationHandler(Object target){  
  8.         this.target = target;  
  9.     }  
  10.     @Override 
  11.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {          
  12.         long beginTime = System.currentTimeMillis();  
  13.         TimeUnit.MICROSECONDS.sleep(1);  
  14.         Object obj = method.invoke(target, args);  
  15.         long endTime = System.currentTimeMillis();  
  16.         System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  17.         return obj;      
  18.     }  
  19. }

  客户端调用改成:

  1. package example;  
  2. import java.lang.reflect.Proxy;  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. /**  
  6.  * -----------------------------------------  
  7.  * @描述  TODO  
  8.  * @作者  fancy  
  9.  * @邮箱  fancydeepin@yeah.net  
  10.  * @日期  2012-8-27 <p>  
  11.  * -----------------------------------------  
  12.  */ 
  13. public class ProxyApp {  
  14.     public static void main(String[] args){          
  15.         //ArrayList代理,通过代理计算每个方法调用所需时间  
  16.         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  17.             ArrayList.class.getClassLoader(),     /*定义代理类的类加载器,用于创建代理对象,不一定必须是ArrayList,也可以是其他的类加载器*/ 
  18.             ArrayList.class.getInterfaces(),       /*代理类要实现的接口列表*/ 
  19.             new MyInvocationHandler(new ArrayList<Integer>())         /*指派方法调用的调用处理程序,这里用了匿名内部类*/ 
  20.         );  
  21.         arrayListProxy.add(2);  
  22.         arrayListProxy.add(4);  
  23.         System.out.println("--------- 迭代 ---------");  
  24.         for(int i : arrayListProxy){  
  25.             System.out.print(i + "\t");  
  26.         }  
  27.     }  
  28. }



从上面代码看来,客户端知道代理的实际目标对象,还知道怎么样去创建这样一个代理对象,如果想把这些信息全部对客户端隐藏起来,可以将这些代码挪到一个类中,将它们封装起来:

  1. package example;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.concurrent.TimeUnit;  
  8. /**  
  9.  * -----------------------------------------  
  10.  * @描述  TODO  
  11.  * @作者  fancy  
  12.  * @邮箱  fancydeepin@yeah.net  
  13.  * @日期  2012-8-27 <p>  
  14.  * -----------------------------------------  
  15.  */ 
  16. public class ProxyUtil {  
  17.     public enum ArrayListProxy {  
  18.         PROXY;       
  19.         private Object target;    
  20.         ArrayListProxy(){  
  21.             this.target = new ArrayList<Object>();  
  22.         }  
  23.         public List getInstance(){  
  24.               
  25.             return (List)Proxy.newProxyInstance(ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces(),  
  26.                     new InvocationHandler() {     
  27.                         @Override 
  28.                         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  29.                               
  30.                             long beginTime = System.currentTimeMillis();  
  31.                             TimeUnit.MICROSECONDS.sleep(1);  
  32.                             Object obj = method.invoke(target, args);  
  33.                             long endTime = System.currentTimeMillis();  
  34.                             System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  35.                             return obj;   
  36.                         }  
  37.                     });  
  38.         }  
  39.     }  
  40. }

  客户端调用改成:

  1. package example;  
  2. import java.util.List;  
  3. import example.ProxyUtil.ArrayListProxy;  
  4. /**  
  5.  * -----------------------------------------  
  6.  * @描述  TODO  
  7.  * @作者  fancy  
  8.  * @邮箱  fancydeepin@yeah.net  
  9.  * @日期  2012-8-27 <p>  
  10.  * -----------------------------------------  
  11.  */ 
  12. public class ProxyApp {  
  13.     public static void main(String[] args){  
  14.         List<Integer> arrayListProxy = ArrayListProxy.PROXY.getInstance();  
  15.         arrayListProxy.add(2);  
  16.         arrayListProxy.add(4);  
  17.         System.out.println("--------- 迭代 ---------");  
  18.         for(int i : arrayListProxy){  
  19.             System.out.print(i + "\t");  
  20.         }  
  21.     }  
  22. }

  上面代码中用到了枚举 enum,如果不想用枚举,就改用普通类来实现就行了。

posted @ 2012-09-03 11:51 顺其自然EVO 阅读(170) | 评论 (0)编辑 收藏

性能测试知多少---性能需求分析

  需求分析是个繁杂过程,它并非我们想象的那么简单,而性能测试需求除了要对系统的业务非常了解,还需要有深厚性能测试知识。才能够挖掘分析出真正的性能需求。

  如何获得有效的需求

  1、客户方提出

  客户方能提出明确的性能需求,说明对方很重视性能测试,这样的企业一般是金融、电信、银行、医疗器械等;他们一般对系统的性能要求非常高,对性能也非常了解。提出需求也比较明确。

  曾经有一个银行项目,已经到最后的性能测试极端,因为数据库设计不合理,导致性能出现很大的问题,最终不得不把整合项目作废,对于这样的项目,其实从分析设计阶段就应该考虑系统的性能问题。性能测试也一样,对于某些项目来说越早进行越好。当然,前期的性能测试为单元性能测试、接口性能测试,有别系统性能测试。

  有时候也会碰到不懂装懂的客户,提出一些无理的需求,比如只能2000人使用的OA系统,客户要求并发用户2000,这显然是不合理的需求。这个就要看你怎么给客户沟通了。但是,千万别伪造数据欺骗客户。

  2、根据历史数据分析

  对于一些面向用户的独特产品,比较难定位市场的大小,可以先上一运营一段时间,通过运营可以搜集客户资料,比如,每月、每星期、每天的峰值业务量是多少。用户以 什么样的速度在递增中。用户对系统的哪些功能模块使用的最多,他们所点的比例等等。

  收集到这些数据之后,我们就可评估系统的系统需求指标,从而进行性能测试。

  3、需求分析与定位

  这里根据前期的需求分析与定位,来分析确定系统性能指标。例如某省幼儿园管理系统。统计全省有多少家幼儿园,系统的使用时间为幼儿到校之后,管理人员对幼儿的到校情况进行录入,以及幼儿的午饭,放学情况的录入时间。经过与需求人员交流分析也能得到比较明确的性能指标。

  4、参考历史项目或其它同行业的项目

  如果公司之前有类似的项目经验,根据项目大小及上次性能测试的一些指标。从根据项目的规模可以制定出相应的性能指标。

  即使本公司没有类似的项目,但其它公司有类似的项目,例如做IPTV或者DVB计费系统的测试,可以参考电信计费系统的需求——虽然不能完全照搬数据,但是可以通过其他行业成熟的需求来了解需要测试的项目有哪些,应该考虑到的情况有哪些种。

  5、参考其它资料数据

  如果你做的是非常独特的产品,市场上没有此类型的产品,而且需求及市场也难以估计,那么只能从与产品相关的资料中寻找痕迹了。不过,相信这样不确定性的产品,老板要承担的风险也是挺大的。^_^

  需要说明的是,我上面介绍的方面并非是独立的,可以综合的使用,你可以根据客户提出的指标,再根据历史数据以及参考同类型项目来进行。这样可以更确定你的性能指标是客户(或自己)真正需要的、最符合项目需求的。

  性能测试点的选取

  * 发生频率非常高的(例如:某邮箱核心业务系统中的登录、收发邮件等业务,它们在每天的业务总量中占到90%以上)

  * 关键程度非常高的(产品经理认为绝对不能出现问题的,如登录等)

  * 资源占用非常严重的(导致磁盘I/O非常大的,例如某个业务进行结果提交时需要向数十个表存取数据,或者一个查询提交请求时会检索出大量的数据记录)





  对性能需求点的描述

  准确

  如**系统必须在不超过 10 秒的响应时间内,处理 20 起登录任务。再如发邮件时间最大不超过5秒以及平均时间在2秒以内。

  一致

  用户和性能测试工程师对有关术语的理解要一致,如:并发用户数、在线用户数、注册用户数:

  特定

  性能测试的需求一定是有条件的。

  检查系统后台关键业务数据10G、操作数据量为20K, 1500 个用户、500 个并发用户运行的负载下,连续运行12小时过程中,业务操作是否满足性能需求。

  常见性能需求

  1、WEB首页打开速度5s以下,web登陆速度 15s以下。

  2、邮件服务支持50万个在线用户

  3、计费话单成功率达到99.999%以上。

  4、在100个并发用户的高峰期,邮箱的基本功能,处理能力至少达到10TPS

  5、系统能在高于实际系统运行压力1倍的情况下,稳定的运行12小时

  6、这个系统能否支撑200万的vu(每天登录系统的人次)          vu----Virtual user(虚拟用户)

  如何把需求转换成性能指标

  我们把200万vu转换成一系列的指标

  ™响应时间:根据国外的一些资料,一般操作的响应时间为2,5,10秒,2秒内优秀,5秒内良好,10秒内可接受,其它一些特殊的操作,如上传,下载可以依据用户体验的情况,延长响应时间。

  ™吞吐量:可以根据已经上线的类似产品进行估计。或者,采用80/20原则进行估计。我们经常使用的是80/20原则。

  80/20原则:又称帕累托效应,比如,80%的社会财富掌握在20%的人手里。

  应用于测试:从vu计算吞吐量?根据80/20原则,80%的用户会在20%的繁忙时间内登陆。则繁忙时间每秒大概会有(2000000*80%)/(24*3600*20%)=100个用户登陆 ,也就是说,登陆操作的吞吐量是100TPS

  如何根据性能需求进行测试

  其实我们上面得到的需求指标仍然是不明确的:

  是验证当前硬件和软件配置能否支撑200万vu?

  是测试当前的硬件和软件配置最多能支撑多少vu?

  是帮助开发寻找性能瓶颈?

  根据需求进行性能测试的过程:



  首先,请你们当前软件和硬件配置下验证能否支撑200万vu。如果可以支撑200万,再增加到300万看是否可以支撑。如果不能达到200万, 那么就需要寻找一下是否有性能瓶颈,将主要的性能瓶颈解决后,再看一下是否可以支撑200万,如果可以支撑,输出测试结果。仍然不能,请评估需要添加多少 硬件设备。

  通过上面流程的分析,那么我们对于需求实施过程就非常明确了。

  下面看来分析某邮箱系统的需求:

  按照 某某 邮箱20000万注册用户,其中日活跃用户数为1.5%的规模计算:

  日活跃用户=20000*1.5%=300万

  日活跃用户人均每天发6封邮件,用户使用客户端收发邮件比例20%,则:

  每天发邮件投递量=300万*6*20%=360万封

  如何得到每秒的邮件数?

  方式一: 严格的根据2/8原则  ,80%的邮件集中在20%的时间发送。
  集中发邮件数:  3600000*80%=28800000封
  集中发送的时间:24*20%=4.8小时=17280秒
  每秒发送邮件数:2880000/17280=166.7封/秒

  方式二,根据 某某邮箱业务模型表,每天忙时集中邮件系数0.15,邮件平均峰值系数2,则:
  峰值邮件量=3600000*0.15*2/3600=300封/秒
  注:忙时集中系数=忙时业务量/全天业务量

  在两种方式的分析中,方法二得出的结果是方法一的将近一倍,我们不要根据经验理所当然的去分析,要深入的了解系统,我们要对行业指标及计算方 式。如果按照第一种方式,性能测试达标了,但系统真正上线后可能远远超出了我们的评估。2008年北京奥运运门票系统就是一个典型的案例。

  再来分析系统的登录:

  去年全年处理“WEB登录”交易约 100 万笔,考虑到 3 年后交易量递增到每年 200万笔。

  假设每年交易量集中在 8 个月,每个月 20 个工作日,每个工作日 8 小时,试采用 80~20 原理估算系统服务器高峰期“WEB登录”的交易吞吐量应达到怎样的一个处理能力

  200万/8=25万/月
  25万/20=1.25万/日
  1.25万*80%/(8*20%*3600)=1.74TPS

  ----------------------

  上面的小案例算是抛出的一块砖,需求开发难度要远远大于需求管理,在实际工作中常常需要我们为客户开发这部分性能需求。所以,在追求技术的基础上,请更多的了解分析你的项目及行业指标。

相关链接:

性能测试知多少----性能测试分类之我见

性能测试知多少---并发用户

性能测试知多少---吞吐量

性能测试知多少---响应时间

性能测试知多少---了解前端性能

性能测试知多少---性能测试工具原理与架构

性能测试知多少---性能测试流程


posted @ 2012-09-03 11:38 顺其自然EVO 阅读(255) | 评论 (0)编辑 收藏

敏捷实践的误区和陷阱的七个方面

 我们认为敏捷实践经历的误区和陷阱大致可以分成如下七个方面:特性团队、人、浪费、局部优化、软件质量、测试自动化、流程。

  特性团队(Feature Team)

  在组织中想要达到真正的Feature Team是一个很漫长的过程,当在组织中实现局部的端到端的组的时候,更大的端到端的组的演变要求就会出现,因为这时组织中新的瓶颈会展现出来,这也是为什么敏捷虽不能解决问题,但却使问题更显现地表现出来的原因之一。

  在组织的转型中,产品有非常庞大的老代码:

  1、通常早期的Feature Team所包括的功能性测试不完全,外部的测试对于这些Feature Team所起到的保护作用还是相当重要的;

  随着时间的推移,Feature Team对于自己feature自动化测试加强以及测试能力的提高,发布给外部的产品质量会大大提高;

  2、对于外部其他组的依赖接口会很多,特别是组在不同国家的时候,沟通、交接和等待的浪费会很大;

  3、当产品中开发部门和开发部门的依赖减少后,开发和测试的瓶颈会更突出;

  4、当产品中各个功能部门的依赖减少的时候,产品和产品间的瓶颈会凸显。

   想象一下从客户提需求到最终提交功能需要经过多少个过程,特别是大型组织中的产品,端到端意味着几十个过程甚至更多,Feature Team中能容纳多少个这样的过程就意味着这个Feature Team的灵活度有多高,本质上敏捷就是为了减少相互的依赖、等待和传递所带来的消耗。

  一个组织是一个庞大的系统,Feature Team的转变过程意味着减少整个系统中的Limitation。

  在向Feature Team演变的过程,在相对比较短的时间把原先十几或者几十Component Team打破组成新的Feature Team,这中间的风险在于:

  1、组的成熟度:成熟度需要时间,也需要一些错误的代价;

  2、组的长期成长和短期项目计划:由于为了项目的进度而把对某领域很熟悉的组移出去做不熟悉的领域;

  3、组织的产出效率:怎样合理的利用现有的有经验人员和新人,建立新结构所需要的基础会使组织整体的产出效率减低;

  4、不可控和无序:怎样让这些组高质量的发布产品在转变过程变的不可控。

  理想和现实中的平衡是Feature Team所面对一个问题,剧烈的变动意味着剧烈的阵痛。

  人

  我们的转变是基于Scrum+XP的方式,转变的影响巨大,之前存在的许多职位、头衔都会面临变化甚至消失的可能。例如将不再会有项目经理来集中处理项目管理工作,对于产品需求研发顺序的管理也由以往的项目经理手中转为产品负责人来负责。就算是最基层的开发人员和测试人员,他们的日常工作方式以及职责范围也面临着极大变化。这也意味着转变可能会遇到非常大的阻力,人天性会抗拒未知的变化。

   某平台部门的转变尤其特殊,研发的老大意志坚定,在初期Pilot成功后,就大刀阔斧地进行组织架构改革,仿佛一夜之间所有的项目经理全部消失。而以往 围绕功能模块所组建的分散的测试团队以及开发团队也被重组,每一个Scrum团队都拥有好几名来自不同功能模块领域的开发和测试人员,从某种角度来看,这 是我们所倡导的跨功能特性团队的雏形。

  各种形式的人员流失造成很大的困难,有人因为个人或家庭的原因离开公司,也有人在新成立的产品线 谋得职位,也有人被提升。但这一切都造成原来位置上的熟手损失殆尽,尤其是测试相关人员的流动,曾是很大的隐患。在以往的研发模式中,测试被严格划分为多 个层级,由不同的测试部门执行,彼此之间通过高级别工程师以及文档和流程体系来沟通,确保各个层级的测试得到执行。新的组织架构中,除了Scrum团队 后,就是系统测试团队,而Scrum团队测试和系统测试之间的衔接则出现了灰色地带,原因就是彼此对对方的职责各有不同假设,却未能发现及解决。


  当时拥护及反对“敏捷”的各有人在。很有意思的是,在内部论坛上,我们属于敏捷的坚定支持者,又喜欢说话或者说辩论,所以可谓是当时论坛里的焦 点,矛头所向。和大家进行了很多很多的辩论,当然多数都是无疾而终。我认为这些讨论,以及发生在工作场合里的许多讨论,同事间私下的交流都非常好,在变革 之际,能够帮助大家去理解这场变革(就算是纯粹的抱怨也并非一无是处)。

  组织变革的关键还是在于充分沟通,以及切实执行。有不同的声音不要紧,关键是要去澄清和解决他们的疑问,因为没有大家的理解和认同,变革也很难取得实际的效果。

  浪费

  加班加点赶进度的情形相信大家并不少见,但如果这么辛苦做出来的东西并没有真正地或是及时地派上用场,恐怕就更加可惜了。该平台部门曾经很辛苦 地去兑现某一个重要发布的最后期限,而根据客户提交的缺陷报告来看,其中有一些功能客户并没有在拿到这个重要发布后就去使用,而是在拿到后续的发布后才有 使用到这些特定的功能。

  该平台部门并非是直接面向终端客户,还需要结合上层的网元应用才能真正地产生效果。常规的模式都是网元有一系列客户需求(具有非常大的粒度)中 分割出对系统平台的需求后,传递到平台部门的项目进行管理。出现过的情形是,平台部门赶出来递交的功能特性,由于网元应用没能及时开发出来,而无法递交给 客户使用。

  对此,大家有很多疑惑,我们是否在做该做的事情(功能特性),其中到底有多少浪费。Scrum的主张就是对用户需求进行优先级排序,但其中有一 些关键的点必须要重视,否则很容易流于形式而无法从中获益,第一,要将需求分割到合适的细粒度,团队才有可能持续地递交高优先级的功能特性,需求粒度不够 小,假设Product Backlog里就只有一个条目,那么不管是PO还是销售还是客户都没有办法取舍;第二,要逐渐达到以真正端到端级别的需求为单位进行开发、管理;第三, 开发团队和PO(能够和终端客户、用户交流更好)之间有频繁地交流、功能成品展示,从而可以利用反馈来改进、提高后续功能的开发。

  局部优化

  有话说“不怕神一样的敌人,就怕猪一样的队友”,其实做软件也是,怕的就是劲不往一处使。但说回来还真不是大家不努力,而是对这个“一处”的看 法各有不同。关注于各自目标的达成,并不能保证这些努力叠加起来能够实现那个 “共同的”目标,对局部进行的优化可能会反过来扯集体的后腿。这样的现象,组织各个层面都有。团队内、团队之间、产品线之间,都存在着这样的情况。

  例如团队内部,由于不习惯转型过程中新的特性团队的工作方式,团队内部也还是颇有些泾渭分明的开发、测试各一拨人,自个选自个的工作,迭代开始 的时候,各自就把自己的任务选走,然后整个迭代就盯着自己的一亩三分地拼命干。但问题是,团队需要负责、承诺的是最终可以运作的软件增量,而这样的模式无 法保证迭代结束时的交付。

  团队之间也是如此,为了让自己的团队工作预期更稳定、工作中能更专心,团队也都要求确定他们的工作领域,迭代中则有些简单粗暴的拒绝许多协助进行缺陷分析的请求。结果就是导致缺陷分析、修复的工作变得非常难以开展,而且有很多尚未查明的潜在缺陷被放弃追踪和申报。

  更大范围内来看,我们完成了传输平台的开发还不够,要能够产生客户价值,还少不了上层的应用软件系统。但我们的系统工程师团队、Scrum团 队、系统领域测试团队等,以及上层的开发团队、功能测试团队、版本测试团队、系统测试团队等一干团队,尽管都在努力改进自己的工作绩效,可问题是,这些局 部的、片面的优化,在组织层面观察,对终端客户产生的影响微乎其微,甚至是副作用。

  敏捷、精益的要点正在于此 —— 关注于产生的价值,移除不必要的浪费。不恰当的局部优化也是一种浪费,我们要具备系统思考的能力,从整体上看问题,然后改进绩效。组建特性团队就是开始。

  软件质量

  软件质量是很多组织都有的一些共性问题,任何变化都意味着质量降低然后恢复到当初,然后再变得比以前好的循环,在我们组织中还是不可避免经历这样的循环。

  在敏捷的转型中,如果没有很好的考虑这些质量的风险,那么最终它所带给组织的将是未来很长一段时间的“痛”,背负的“债”需要很大的代价来偿还,所导致的结果将对客户的满意度和信任都会产生很大的影响。


  质量问题中,通常我们认为会有三种类型的问题:老代码的问题,新功能开发的问题和改问题引入的新问题

  老代码的遗留质量问题所占的比重通常是比较大。庞大的系统,任何的改动都有可能影响老代码的问题,或者老代码不能满足当前的需求所需要做的调整,往往是这些改动或者新需求会影响那些地方通常是比较难界定出来,对于老代码的测试自动化保护是关键。

  新功能开发所带来的问题通常会由于对于进度压力的妥协,在匆忙完成当前迭代周期的内容或者需要延迟当前迭代周期去做更多的测试之间矛盾。敏捷的开发模式使得原先长周期的项目进度和项目质量矛盾会在更短的周期里(4周)显现出来。

  在敏捷实践中,最大的一个优势就在于快速的质量反馈。由于持续集成,持续回归测试,质量的反馈就会在2~3天甚至3~4小时之内反馈到代码提交的软件人员。

  当然这样的快速反馈是基于持续集成所达到的层次,最完美的情况肯定是整个产品所有的测试都被放入到持续集成,那么对于整体软件将会有一个非常全面的质量考量。

  自动化测试

  测试自动化被许多人看做是敏捷的基石之一,众多的敏捷实践依赖于自动化的程度,例如持续集成。而能够实现增量式开发也需要能够快速、全面地进行 回归测试,确认已存在的功能特性没有受到新特性开发的影响。在大张旗鼓地进行敏捷转变之前,我们的产品线就已经开始尝试过测试自动化。一个专门的测试自动 化小组在半年多时间内,操作芬兰专家开发的自动化测试工具,将那些执行频率很高的回归测试用例集实现自动化执行。基于由此项目得来的成功经验,测试自动化 的概念被广为传播,而且这个实践也开始作为一个基本要求附加给测试团队,自动化测试用例占所有测试用例的比例作为一个指标被上层主管密切关注。

  开始进行敏捷转变时,围绕着测试自动化有很多的争论,主要的焦点在于是否要追求100%的测试自动化。反对方和支持方都各有理由,难分高下,不 同理念都有追随者在实践。支持者认为自动化测试可以节省执行时间,而且可以在夜间及周末进行测试执行。反对者认为实现自动化用例耗用了测试人员的绝大部分 时间,来自于基层的部分意见反映他们都没有时间去真正的测试系统,而且还有一些用例非常难实现自动化,或者说成本非常高。而最新的一个情况是,在一个新的 版本发布计划中,测试自动化的开销总计以万小时计算,那么是否有必要一定要实现100%测试自动化?

  我个人认为,其中很重要的一点就是测试自动化以及其比例被作为硬性指标施压给团队,导致团队无暇顾及测试自动化的质量高低。而测试自动化的质量 恰恰会影响到:执行时间的长短、维护自动化脚本的开销、实现测试目的的准确性等。另一个原因就是,了解、专长于测试自动化,具备大范围应用测试自动化经验 的专家太少,还常常疲于应付实现具体的测试自动化用例,无暇去传授、辅导及培养其他同事的测试自动化技能。

  流程

  敏捷的转型过程中,如果认为流程可以被抛弃,可以按照自己的想法去做开发测试,这样的观念将是很大的一个误区。

  流程之所以为流程是因为它所承载的是一个组织长时间积累的经验与教训,它被实践所证明有效的方式,怎样使做某件事情的效果与效率达到最优,并在多年的实践中被不断的补充。

  比如同行评审,我们的误区在于认为人们会自动自发的组织好同行评审,可以使用开发组所自己的方式。老的同行评审的传统并没有很好的沿袭,特别在组织大规模扩招的时候。导致的结果是我们的需求,设计代码的问题比以往任何时候都要多。

  比如测试,组织大规模的调整,但是相对应的测试在新组织里的怎样的计划,新开发组里测试以怎样的方式进行,怎样是最有效率的进行测试,开发组的 测试和外部测试之间的区别和协调,测试在端到端的整个开发过程中的布局与充分性。我们的误区是对这些问题在相当长的时间以后才逐渐意识到这方面的缺乏,然 后逐渐提出改进。



posted @ 2012-09-03 11:35 顺其自然EVO 阅读(232) | 评论 (0)编辑 收藏

推动开发做自动化的解决方案

 1、为什么推动开发做自动化?

  测试将自动化做起来不难,做出效果来不难,但只能做好与业务相关紧密的黑盒级自动化。

  黑盒自动化虽能带来很好的效益,但它的问题也随之而来,慢,开发成本高,环境依赖大,可覆盖面有限。不能给项目带来质的改变。

  开发做自动化,可以从代码上入手,从一开始就减少bug,其价值,就非常大。

  但是,推动开发好做么?如何去做?接下来,就这个问题我们来讨论一下。

  2、如何推动开发做自动化?

  首先,要弄明白一个事情,开发是什么样的人。

  1)聪明但懒惰的人。

   聪明不必说,我们测试同样十分聪明,不是么?呵呵,放松一下。懒是程序员的天生本性。君不见,K.I.S.S 是他们开发的基本原则。可能有些测试兄弟没听过,没关系,我解析下,将项目做的够简单,够愚蠢。这样,他们才能懒下去。没有任何重复,任何事情不应该干两 次,这也是他们的准则。而且他们还美其名曰:“懒是人类进步的动力”,我吐槽,这群程序猿们有些意思嘛。。。

  他们宁可用着老掉牙的vim也不喜欢微软的大型IDE,宁可在命令行输入天书般的命令,也不愿做一个UI点一点,宁可用Linux这复杂至极的系统,整天用着 wget,linker,curl也不愿切换鼠标。

  那他才懒着用你提供的关键字驱动框架呢,一会用中文编程,一会切换到这门语言,一会切换到他的“母语”,一会切换在人家的IDE里,一会又用脚本,再写的过程出个错,错杀自己心爱的代码。谁受得鸟呢。不用了。

  2)何况,他们还是不多管任何事的人。

  君不知,不是他的事就不应该知道就是他们的信条,否则,便犯了软件界的大忌了。你想让他们做一些测试的事情?门都没有。

  还好,他们还是聪明人,知道bug本质上都是自己的过错,知道线上的问题自己承担至少一半的责任。知道自己应该测测再提交测试人员。知道最好可以自动化测测。。。

  说到这里,我有一个很久远的故事先分享下,古时候,有一个孩子,很懒很懒,懒到饭都要老妈喂到嘴边才肯吃,有一天,老妈要去婆婆家几天,于是,做了一张大饼,挂在儿子脖子,然而,儿子竟被饿死了。。

  还好,我们开发人员只需要喂喂就可以了,我的方法是,做一个足够简单,方便的“大饼”,给开发 “喂” 起来。则此事可成。

  那么,这个大饼应该是什么样呢?

  * 足够简单,让他一张“嘴” 就可以“吃”起来,所以最好只写业务代码就成了。

  * 美味,符合他的味口,所以最好可以使用他的母语进行自动化,符合K.I.S.S

  * 可扩展性好,想改变下口味也是可以的

  * 还要好看,实用。通知机制,失败分析,一个都不能少。

  如果,有如此一张“饼”,大事可成矣。但如何去做出这张大 “饼” 呢?这需要你的高深的厨艺了。且听接下来的分解。

  3、具体的做法

  我有两种方法

  第一种高端方法是采用深入敌方深处

  * 控制开发框架,掌握开发的框架,正所谓,知之知彼,百战不怠。

  * 通过某一次新产品需求,提出框架的可测试性需求,让产品经理或老板采纳。

  * 开始完成我们的大饼,一步步来,让开发看到进度,一旦成型,则可以无数开发使用。

  第一种难度大,我们需要成为他们的架构师才行的通。

  方法二

  * 参与前期需求,提出可测试性需求,并能够有效拥有开发的意识,

  * 跟他们开发经理谈谈,找出内部有兴趣做这个框架的”叛将“, 谈谈。

  * 让他负责做核心,你借机熟悉周边技术,比如,我们用Ruby,因为它的开发效率,我们可以学学 swing, thrift 这些 ”透明胶“,将他们的母语粘在一起,这样即拥有了高效的开发效益,又符合他的味口。

  * 形成框架,让少数人用起来,改进再改进,直到”大饼“ 成型。

  大饼的特点,我上面说到了,你一定要留心,缺一不可。

  那能做成么?有实例吗?你肯定会如此问,我可以信心十足的回答,有的。实际上,正是段念分享的一段话,在懒惰的开发面前,如何做成 Google Map 这样的自动化测试工作的。

  所以,我们团队很可能去落实了,你呢?

版权声明:本文出自 lyfi2003 的51Testing软件测试博客:http://www.51testing.com/?312752

原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。

posted @ 2012-09-03 11:31 顺其自然EVO 阅读(205) | 评论 (0)编辑 收藏

如何写软件测试人员的周报(或日报)

 众所周知,在职场,总有各式各样的报告要看,要写,而最常规的莫过于周报(或者日报)了。这类报告通常是关于个人的工作情况或者项目的进展情况等。那么作为一名测试人员,该如何写周报呢(若有日报需要,以此类推)。

  通常在写一份报告之前考虑这么两个方面会让你的报告更具阅读性,那就是:报告要表达的主题是什么,报告的观众/听众是谁。对于同一个(或者相似的)主题,观众/听众不一样,报告所需要陈述的具体内容通常也是不一样的。

  下面我想从测试员和测试组长(负责人)的角度分别罗列一下测试周报的模式和内容。

  一、测试员(tester)

   测试员的周报一般来说是汇报给自己的组长,就我自己的工作经历来说,一般软件公司测试组长兼具项目以及行政两个方面,也就是说一方面主导分配到这个测试 小组的测试任务,另一方面也要关注组员的工作绩效以及团队发展等。所以汇报给测试组长的周报就要比较详细的从项目和团队合作方面同时阐述自己一周的工作情 况。大概可以包括这个几点:

  1、内容概要罗列以及花费时间列表

  阐述本周自己主要的工作情况,譬如参与了哪几个项目的哪些相关测试,出席了几个公司会议,参加了几个公司内(或外)的相关培训课,阅读了什么工作相关的资料/书籍等,同时(推荐以表格的形式)列出每一项工作(或相关)内容所花费的时间(work hour)

  2、执行的测试用例数目

   按照项目分别列出,本周执行了多少测试用例,其中pass多少,fail多少,有多少用例被block了不能执行(需要另外列出具体的被block原 因,如某个bug或者某项测试资源没有到位),还有多少已分配的测试用例没有完成。这些信息推荐以表格形式给出,参见下面的草图:


 Pass FailBlocked  Remaining
  Project A 25 3 2 16
 ......    

  如果执行了ad-hoc或者exploration测试,可以考虑以表格形式列出测试内容。

  3、提交的bug具体数目

   体现测试人员绩效一个重要的方面是提交的bug数量和质量。所有在这里列出本周里在每个测试项目中你提交的有效bug数,无效bug数(重复的bug, 不能复现的bug),验证的bug数(有效修复-fixed,无效修复-reject),这些信息同样推荐以表格形式给出,参见下面的草图:


 Submitted-Valid Submitted-Duplicated Submitted-Unreproduciable Verify-FixedVerify-Reject 
 Project A 5 2 0 8 3
 ......     

  4、其它

  任何工作相关的其余内容。譬如你希望多一个测试平台,你需要某本专业书籍等等等等。

  二、测试组长

   测试组长的周报通常来说覆盖两个方面,一是项目相关情况,这个内容的目标读者是所有和项目相关的人员(项目经理,产品经理,开发人员,测试人员,发布人 员等),另一个方面是关于团队管理方面(有时候会把这一项单独放在一份报告里发给测试经理,毕竟项目相关人员只关注项目的测试进展情况,基本不关心测试团 队成员的具体工作内容)

  1、严重问题

  任何阻止测试顺利进行的issue都要在这里醒目列出,同时要注明希望问题得到解决的最后期限,如果知道报告接受者中的谁可以帮助推动解决这个问题,要明确指到该人姓名。

  2、各个项目测试用例完成情况

  可以用类似于下面的柱状图来表示

  (如有必要,可以给出具体的链接指向测试用例管理库中本轮测试的详细内容和结果)

  3、各个项目的bug以固定时间为单位(通常周报中就按周来统计)的增减情况

  (统计的bug数量可以是所有优先级/严重程度的bug总和,也可以只取第一第二优先级/严重程度的bug进行统计,因为很多时候,这类bug的数量直接影响产品发布与否,而这个,正是项目相关人员最关心的)

  例见下图

  (如有必要,给出具体链接指向bug管理库中该项目所有bug的详细内容)

  4、各个项目的bug按照一定类别的百分比统计

  (这个图可以让看报告的人一目了然当前项目中的主要问题存在哪里,是功能上的,还是界面上的,还是通讯上的,还是其它等等等等)

  例见下图(具体分类根据不同产品不同项目而不同)

  5、(如有必要)测试小组成员的大概工作情况

  可以包括:有多少测试人员参与,每个人在各个项目中花费的时间,有时候也可以列出每个测试员执行了多少测试用例,提交了多少bug,验证了多少bug等信息

  可以参见如下表格:

  6、任何项目相关的其它杂事

  暂时就想到这么多了,欢迎大家指点意见。

版权声明:本文出自小丫头的51Testing软件测试博客:http://www.51testing.com/?18819

原创作品,转载时请务必以超链接形式标明文章原始出处 、作者信息和本声明,否则将追究法律责任。

posted @ 2012-09-03 11:16 顺其自然EVO 阅读(463) | 评论 (0)编辑 收藏

MySQL锁的用法之表级锁

 锁机制是数据库有别于文件系统的一个重要的特点,也是用来管理并发访问的一个有效的方式。MySQL的锁分为表级锁、页级锁与行级锁。表级锁是MySQL中粒度最大的一种锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。

  表级锁定分为两类,读锁与写锁。读锁是预期将对数据表进行读取操作,锁定期间保证表不能被修改。写锁是预期会对数据表更新操作,锁定期间保证表不能被其他线程更新或读取。

  读锁:

  用法:LOCK TABLE table_name [ AS alias_name ] READ

  指定数据表,LOCK类型为READ即可,AS别名是可选参数,如果指定别名,使用时也要指定别名才可

  申请读锁前提:当前没有线程对该数据表使用写锁,否则申请会阻塞。

  操作限制:其他线程可以对锁定表使用读锁;其他线程不可以对锁定表使用写锁


写操作读操作
使用读锁线程否(报错)
不使用读锁线程否(阻塞)

   对于使用读锁的MySQL线程,由于读锁不允许任何线程对锁定表进行修改,在释放锁资源前,该线程对表操作只能进行读操作,写操作时会提示非法操作。而 对于其他没使用锁的MySQL线程,对锁定表进行读操作可以正常进行,但是进行写操作时,线程会等待读锁的释放,当锁定表的所有读锁都释放时,线程才会响 应写操作。

  写锁:

  用法:LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE

  别名用法与读锁一样,写锁增加了指定优先级的功能,加入LOW_PRIORITY可以指定写锁为低优先级。

  申请写锁前提:当没有线程对该数据表使用写锁与读锁,否则申请回阻塞。

  操作限制:其他MySQL线程不可以对锁表使用写锁、读锁


写操作读操作
使用写锁线程
不使用写锁线程否(阻塞)能(阻塞)

  对于使用写锁的MySQL线程,其可以对锁定表进行读写操作。但是对于其他线程,对指定表读写操作都是非法的,需要等待直到写锁释放。

  锁分配优先级:

  对于锁分配的优先级,是: LOW_PRIORITY WRITE < READ < WRITE

  1、当多个线程申请锁,会优先分配给WRITE锁,不存在WRITE锁时,才分配READ锁,LOW_PRIORITY WRITE需要等到WRITE锁与READ都释放后,才有机会分配到资源。

  2、对于相同优先级的锁申请,分配原则为谁先申请,谁先分配。

  注意事项:

  1、不能操作(查询或更新)没有被锁定的表。

  例如当只申请table1的读锁,SQL语句中包含对table2的操作是非法的。例如:

mysql> LOCK TABLE test READ;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM test_myisam;
ERROR 1100 (HY000): Table 'test_myisam' was not locked with LOCK TABLES

  2、不能在一个SQL中使用两次表(除非使用别名)

  当SQL语句中多次使用一张表时,系统会报错。例如:

mysql> LOCK TABLE test READ;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM test WHERE id IN (SELECT id FROM test );
ERROR 1100 (HY000): Table 'test' was not locked with LOCK TABLES

  解决这个问题的方法是使用别名,如果多次使用到一个表,需要声明多个别名。

mysql> LOCK TABLE test AS t1 READ, test AS t2 READ;
Query OK, 0 rows affected (0.00 sec)

mysql>  SELECT * FROM test AS t1 WHERE id IN (SELECT id FROM test AS t2);
+----+-----------+
| id | content   |
+----+-----------+
|  1 | tt_1      |
|  3 | new_3     |
|  4 | new_4     |
|  5 | content_5 |
+----+-----------+
4 rows in set (0.00 sec)

  3、申请锁时使用别名,使用锁定表时必须加上别名。

posted @ 2012-09-03 11:15 顺其自然EVO 阅读(2369) | 评论 (0)编辑 收藏

多浏览器行为同步的手工兼容性测试方法

  背景:

  在浏览器的手工兼容性测试中,为了测试兼容性,需要测试人员手工在各个浏览器中分别、重复的进行相同操作,既效率低下,又让测试人员感到枯燥。

  问题:

  自动化测试可以让测试人员脱离枯燥的测试行为,提升测试效率,但自动化测试更关注业务功能的验证,对于页面兼容性不如手工测试直观、有效。

  解决方案:

   将测试人员在某一浏览器的操作行为,即时同步到其它浏览器中,这样测试人员只需要在一种浏览器中进行操作,就能同时看到其它浏览器中进行相同操作的效 果。这样既避免了测试人员在不同浏览器中分别进行相同操作的枯燥,同时有效地提升测试效率,并且能够直观、有效的监控到各浏览器页面的兼容性。

  原理分析:

  用到的技术:Javascript、鼠标/键盘事件、套接字Socket、XMLHttpRequest、Selenium-WebDriver

  1)整体框架

  整体框架分为Server端和Client端,如下图所示:

  注:图中的XHR为XMLHttpRequest对象。

   上图中,首先对document注入js,绑定鼠标事件和键盘事件,对当前被操作浏览器的行为进行捕获;通过XHR实现Server端和Client端 (即当前被操作浏览器)一对一的消息交互;各个浏览器进行通信之前,为每个请求创建socket实例,接收当前被操作浏览器发送过来的消息,并运用 Selenuim-WebDriver扩展开发将该行为同步到其他浏览器,达到在不同浏览器上的兼容性测试。

  2)流程

  流程分为两大部分:浏览器行为捕获和各个浏览器间的行为同步,其中行为捕获有捕获和记录两个动作,行为同步是通过Socket通信机制和Selenuim-WebDriver扩展开发来实现的,具体如下:

   捕获:通过对document注册mousedown和keydown事件,当监听到事件发生时,获取当前对象的path或者keycode。同时绑定 blur事件,当鼠标点击的元素为input时触发,获取input对象的value值,即输入框中输入的内容。 path/keycode和value通过XMLHttpRequest传给Server端,供各个浏览器通信用。当前被操作浏览器的每一次操作,都会通 过创建XMLHttpRequest实例,向指定的服务器端口发送。

  行为同步:在各个浏览器开始通信之前, 要建立当前被操作浏览器和其他浏览器之间的连接。需要服务端在监听到请求之后,为每个请求创建socket实例,将当前被操作浏览器发送过来的消息 (path/keycode和value)接收,通过Selenuim-WebDriver扩展开发反馈给其他浏览器进行同步操作。

  后续规划:

  目前一期产品已经发布,可以同时同步的浏览器有IE/ForeFox/Chrome/Safari/360/Sougou/World

  1)网络版,支持本机同步到虚拟机,用于IE6/7/8/9的兼容性测试

  2)提升用户体验,添加其他常用功能

  3)截图对比,减少人肉工作量,提高效率

  4)录制功能

posted @ 2012-09-03 11:01 顺其自然EVO 阅读(1478) | 评论 (1)编辑 收藏

SQL Server数据库程序设计知识总结

  SQL Server是由Microsoft开发和推广的关系数据库管理系统(DBMS),它最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的,并于1988年推出了第一个OS/2版本。它只是众多关系数据库管理系统的一种,其它的关系数据库管理系统还有Server,Oracle,DB/2,Sybase,Informix;关系数据库:Access,FoxPro,Dbase等。如今,数据库已经变成学习软件开发的核心课程之一,几乎绝大部分软件都涉及到数据库,很多数据必须存在数据库中。所以为了更好的掌握和操作数据库,对数据库知识的封装就显得尤为重要。

  ● 关系和非关系数据库

   关系数据库是创建在关系模型基础上的数据库,由一个或多个二维关系数据表组成,通过建立表之间的关系来定义数据库的结构。在关系数据库中最重要的是数据 表,数据表把相关联的数据按行和列排列到一起来描述一个实物。一个二维表称为一个关系,每一个关系又可以包含多个属性。

  和关系型数据库相比,非关系型数据库特别适合以SNS为代表web 2.0应用,这些应用需要极高速的并发读写操作,而对数值一致性要求却不甚高。关系数据库为了维护事务的一致性付出了重大代价导致了其读写能力下降,随着 现在网络SNS的应用对并发读写能力要求极高,关系型数据库已经无法应付,因此,必须用新的一种数据结构化存储来来代替关系数据库。关系数据库的另一个特 点就是其具有固定的表结构,因此,其扩展性极差,而在SNS中,系统的升级,功能的增加,往往意味着数据结构巨大改动,这一点关系型数据库也难以应付,需 要新的结构化数据存储。于是,非关系数据库(NoSQL)应运而生。非关系数据库通常没有固定的表结构,严格上说不是一种数据库,应该是一种数据结构化存 储方法的集合。

  ● SQL Server数据库基础

  首先我们从图中看他们之间的联系。

  一、T-SQL和SQL的比较

  SQL全称为Structured Query Language,是关系数据库的标准语言,它主要包括三种语言:  数据定义语言、数据操纵语言、数据控制语言。T-SQL是SQL语言的增强版。

   也就是说,SQL三种语言适用于所有关系型数据库,但是它本身具有局限性,因为它只提供了对数据库数据基本的增删改查等命令,在开发拥有复杂结构的数据 库程序时,只有SQL语言是远远不够的,于是各大公司在SQL基础上对它进行了增强。T-SQL是MS和Sybase在 SQL的DDL和 DML基础上,增加了延伸的函数、系统预存程序以及程式设计结构(例如 IF和 WHILE)让程式设计更有弹性。和T-SQL类似的增强版的SQL语言还有Oracle对SQL的扩展PL/SQL。

  二、数据库对象

  数据库对象定义了数据库内容的结构。它们包含在数据库项目中,数据库项目还可以包含数据生成计划和脚本。 在学习SQL Server时,最快的方法是先学习数据库对象。在研究了它们之间的异同点后,我把数据库对象分为三类。





 这三类数据库对象在功能上可能有重叠。

  1、基于表的对象

  表,数据保存在表中。

  基于表的对象我把它分为三类:

  视图,用来筛选出用户想要的信息,它是虚拟表,只封装语句,一定程度上保证表中数据的安全;

  索引,对数据库表中一个或多个列的值进行排序的结构,提供指针以指向存储在表中指定列的数据值,然后根据指定的排序次序排列这些指针。数据库使用索引的方式与使用书的目录很相似;

  约束、默认值、规则、触发器确保了数据完整性。

  2、数据库安全性:用户、角色、权限与数据库安全性中的登陆联合应用可以限制登陆者可进行的操作来保证数据库的安全性。

  3、块:存储过程和函数有点相似,但是存储过程可以返回Recordset;触发器是一种特殊的存储过程。

  三、DTS数据转换服务

  DTS的主要作用:1、导入与导出数据

  2、转换数据(检验、净化、重整数据)

  3、转换数据库对象

  四、管理和维护

  在这部分中主要是对数据库文件的保护和管理。

  1、数据库文件

  数据库文件是存放数据库数据和数据库对象的文件。一个数据库可以有一个或多个数据库文件,一个数据库文件只属于一个 数据库。当有多个数据库文件时,有一个文件被定义为主数据库文件,扩展名为.mdf,它用来存储数据库的启动信息和部分或全部数据。一个数据库只能有一个 主数据库文件,其它数据库文件被称为次要数据库文件,扩展名为.ndf,用来存储主文件没存储的其它数据。

  多个数据库文件组合到一块就成为文件组。主文件组是由主文件组合成,此文件组是由此文件组合成,但是事务日志文件不属于任何一个文件组。

  2、事务和锁

  事务

  事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性。

  事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。

  COMMIT表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束。

  ROLLBACK表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有以完成的操作全部撤消,回滚到事务开始的状态。

  锁

  数据库就是通过锁机制来解决并发问题的。。主要就是两种锁,共享锁和排他锁(也叫独占锁)。

  从程序员的角度看锁分为以下两种类型:

  乐观锁(Optimistic Lock):乐观锁假定在处理数据时,不需要在应用程序的代码中做任何事情就可以直接在记录上加锁、即完全依靠数据库来管理锁的工作。一般情况下,当执行事务处理时SQL Server会自动对事务处理范围内更新到的表做锁定。

  悲观锁(Pessimistic Lock):悲观锁对数据库系统的自动管理不感冒,需要程序员直接管理数据或对象上的加锁处理,并负责获取、共享和放弃正在使用的数据上的任何锁。


  ● 应用实例

/*--下面我们新建一个名为company的数据库,创建三个表priduct、project、tblsales,并在其中创建默认值、规则、触发器、存储过程,并利用用户、角色、权限等确保数据库安全。*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_priduct_project]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[priduct] DROP CONSTRAINT FK_priduct_project
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[getavgpbiaodi]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[getavgpbiaodi]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pinfo5000]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[pinfo5000]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pro]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[pro]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sysconstraints]') and OBJECTPROPERTY(id, N'IsView') = 1)
drop view [dbo].[sysconstraints]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[priduct]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[priduct]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[project]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[project]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tblsales]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tblsales]
GO

if exists (select * from dbo.systypes where name = N'tele')
exec sp_droptype N'tele'
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rule_position]') and OBJECTPROPERTY(id, N'IsRule') = 1)
drop rule [dbo].[rule_position]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[@position]') and OBJECTPROPERTY(id, N'IsDefault') = 1)
drop default [dbo].[@position]
GO

create default [@position] as '其它'
GO
create rule [rule_position] as @postion in('项目经理','秘书','会计','职员','其它')
GO
setuser
GO

EXEC sp_addtype N'tele', N'smallint', N'not null'
GO

setuser
GO

CREATE TABLE [dbo].[priduct] (
 [产品ID] [int] NULL ,
 [产品名称] [char] (20) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[project] (
 [项目编号] [int] NOT NULL ,
 [项目名称] [char] (10) COLLATE Chinese_PRC_CI_AS NOT NULL ,
 [开始日期] [datetime] NULL ,
 [预计日期] [int] NULL ,
 [客户编号] [int] NULL ,
 [负责人编号] [int] NULL ,
 [项目标的] [int] NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[tblsales] (
 [number] [int] NOT NULL ,
 [name] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
 [sex] [char] (2) COLLATE Chinese_PRC_CI_AS NULL ,
 [birthday] [datetime] NULL ,
 [salary] [money] NULL
) ON [PRIMARY]
GO

setuser
GO

EXEC sp_bindefault N'[dbo].[@position]', N'[project].[项目标的]'
GO

EXEC sp_bindrule N'[dbo].[rule_position]', N'[project].[项目名称]'
GO

setuser
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

--/****** Encrypted object is not transferable, and script can not be generated. ******/

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

create procedure getavgpbiaodi
@name varchar(10),@avgpbiaodi int output
as
declare @errorsave int
set @errorsave=0
select @avgpbiaodi=avg(项目标的)
from project as p inner join pmanager as pm on p.负责人ID=pm.负责人ID
where pm.姓名=@name
if(@@error<>0)
 set @errorsave=@@error
 return @errorsave

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

create procedure pinfo5000
as select * from project where 项目标的>=5000
order by 项目标的 desc

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

create procedure pro
@n1 int,@n2 int,@n3 int,@avreage int output
as select
@avreage=(@n1+@n2+@n3)/3
declare @avgscore int
exec pro1 1,2,3,@avgscore output
select 'The score is:',@avgscore

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

  SQL Server的基础框架知识,我现在只能总结这么多,更多的总结还是在以后一点一滴的学习中。


posted @ 2012-09-03 10:12 顺其自然EVO 阅读(275) | 评论 (0)编辑 收藏

六年软件测试感悟

 软件测试人员应该居安思危

  每当经济不好,公司业绩不好的时候,公司都可能进行裁员。首先裁的就是测试人员。因为测试人员的技术水平相对来说比较低,容易被替代,招起来也比较容易。公司往往先拿测试人员开刀。

  身为测试人员,虽然我们平常的工作大部分都比较安逸。但是千万不能温水煮青蛙。应该自强不息,要像开发人员一样,不断学习,提高自己的编程水平。这样就算被裁也能很快找到新的工作。

  测试人员应该比开发人员更熟悉业务需求

  测试人员的水平主要体现在测试用例的设计上。要设计出全面,覆盖广的测试用例,需要测试人员对自己所测试的项目的业务需求非常熟悉,甚至要比开发人员还要熟悉。

  如果是测试银行系统,通信行业,或者ERP软件。这些业务知识非常有用的,学习起来比较有激情。

  要做到精通业务需求谈何容易。

  1、要熟读功能需求文档,任何有疑问的地方都要去和PM确认。

  2、把自己当成最终用户,经常使用自己所测试的软件。模拟用户的行为。

  3、熟记软件的每个功能。

  假如倒霉碰到一些又没用,又繁琐的软件,真的是不想去学习它的业务(出了这个公司就再也用不到的业务)

  学会如何跟开发人员相处

  测试人员必须跟开发人员密切合作,所以跟开发人员搞好关系是相当重要的。

  1、和开发人员成为朋友。

  熟悉了干啥都方便

  2、不要打扰开发人员

  看到开发在聚精会神写代码的时候,千万不要去打扰人家。写代码需要集中精力,如果被打扰,就会中断思考。

  3、集中问问题。

  把需要问的问题都总结起来,集中起来问开发,这样能节省大量的时间。

  4、写好Bug,不被开发人员烦。

  如果开发人员看到一个Bug描述不清楚,还无法重现,他肯定会骂测试人员。所以测试人员一定要写好Bug,描述精确,简洁,没有歧义,详细简洁的重现步骤,加截图。

  测试人员应该懂一些基本的编程

  你的产品是用C#开发的,那测试人员应该有C#的入门知识。你测试web程序,你起码要了解HTML,CSS,Javascript,Jquery吧,否则你测了一两年web程序,都不知道这东西是怎么做的,悲剧了吧。

  只有懂代码你才能和开发人员交流,不被开发鄙视。

  测试人员搭建开发环境

   产品的代码是最好的学习资料了,我们不能总跟在开发屁股后面做测试,不能老是等开发build一个版本后,我们就测试这个版本,开发checkin了什 么代码,测试人员一点都不知道。偶尔我们应该了解下产品代码是怎么设计的,了解下开发人员是如何修复bug的。说不定编程水平高了,还能帮开发做 codereview。

  使用源代码工具把产品代码checkout到本机。经常看看代码,经常看看开发修复bug时候提交的代码。


  写文档是测试人员的核心能力

  我记得我以前的testlead说,之所以她能当lead,是因为她很会写文档发邮件。写文档需要总结归纳的能力,还要逻辑清晰。她非常擅长分 析几十页的Spec,写出几十页的测试计划。她还非常擅长汇总测试报告。每天将完整,清晰,漂亮的测试报告发给各个组,让公司所有的人都能清晰的看到测试 组的工作。

  在她的带领下,我们总结出很多文档,比如,“New hire checklist”,“on boarding traning”,测试工具使用的文档,等等。

  写多了博客后我发现我写文档能力提高了很多。

  测试后期应该做两天交叉测试

  交叉测试,就是指两个测试工程师,互相交换下测试的项目。这样做有很多好处。

  1、有利于找出bug,测试工程师测久了自己的项目,容易形成眼盲。会对一些Bug熟视无睹。

  2、有利于知识和业务共享,避免人员离职,请假,造成无人测试的情况。

  3、测试思想不一样,可以互相找出很多问题

  测试人员的瓶颈

  手动测试工作做个两三年,基本上就能掌握测试需要的大部分知识,如果没有爬到test lead的位置,很多人就感觉到发展瓶颈了,每天重复测试,学不到东西,很快就会对测试工作失去激情。

  学不到东西,技术水平低下,是测试这个行业最大的毛病。

  如何突破瓶颈?我也不知道。

  尽量实现自动化

  一点要抽时间尽量把自己的测试工作实现自动化,可以节省测试的时间,提高自己的技术水平,也可以避免老是重复测试。

  自动化测试VS手动测试

  现在很多公司招测试的要求越来越高,很多好公司招senior QA,都要求5年工作经验以上,掌握一门编程语言,有丰富的自动化测试经验。当然自动化测试的待遇也会比手动测试好很多。

  自动化是趋势,只会做手动测试的人,以后肯定会失去竞争力。

  自动化测试的技术和开发用到的技术相差太远

  以前很多同事想由测试转开发,现在几年过去了,还是没转成,他们原先想利用自动化测试的技术积累,转去做开发。哪知道自动化测试用到的技术跟开发用到的技术相比,实在是相差太远。

  测试转开发?难

  努力学习编码,然后用于测试,才是正道

  做测试最郁闷的是无法听懂开发人员讨论技术

  有时候跟开发人员一起开会,会议上开发人员都热烈讨论。而我做为测试人员基本上听不懂这群开发在说什么,根本插不上话。很多会议我甚至都没说过一句话。

  优秀的测试人员非常稀少

  想把测试做好非常不容易,优秀的测试人员需要很广的知识面,良好的沟通能力(不但要和开发人员和项目经理打交道,还要跟其他组的人交流)。丰富的测试经验,对测试工作有极大的热情,耐心。还需要测试人员有丰富的业务知识,还要会写代码。

  代码写得好的人,肯定就不会做测试,而是做开发去了。

  大部分的测试经理都是有开发背景的

  我发现我的几任上司都是由开发转来做测试的。 他们都是有几年的开发经验,然后不知道什么原因转行做测试经理了。他们既能开发又能测试,啥都会,能给手下的测试人员提供技术支持。

  假如一个测试经理啥技术都不懂,对内hold不住手下的人,对外其他组的人不鸟你。

  软件测试的确非常枯燥,需要花费大量精力

  不可否认测试工作需要耗费大量的精力,所以欧美才会把大量的测试职位外包给中国,一遍又一遍的重复测试,不停地执行测试用例, 测得天昏地暗,头发晕。

  我还记得我以前测试过一个程序的各个版本在Windows update中的升级,先安装老版本的程序,然后Windows update 重启后看看有没有升级,最后卸载。 然后又安装,又卸载。最后测的差点吐血。

  英语是测试人员的救命稻草

  技术上已经不如开发了。在英语上一定占有一些优势。

  同等的技术水平下,英语好的测试人员可以进外企,比一个英语不好的测试人员的待遇要高不少。

  尽量少用UI自动化测试,多使用单元测试,接口测试

  能找到bug的自动化测试,才是有用的,否则就是个噱头

  UI自动化测试比较不稳定,对于测试结果的分析也困难。而且UI改动也大。所以应该尽量多做一些底层的的自动化测试,比如ASP.NET MVC 中UI和逻辑分开了,针对逻辑的自动化测试就比较好做了。

  出自:http://www.cnblogs.com/TankXiao/archive/2012/08/27/2576962.html


posted @ 2012-09-03 10:10 顺其自然EVO 阅读(200) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 294 295 296 297 298 299 300 301 302 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜