qileilove

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

Java和.NET使用DES对称加密的区别

 Java和.NET的系统类库里都有封装DES对称加密的实现方式,但是对外暴露的接口却各不相同,甚至有时会让自己难以解决其中的问题,比如Java加密后的结果在.NET中解密不出来等,由于最近项目有跨Java和.NET的加解密,经过我的分析调试,终于让它们可以互相加密解密了。

  DES加密

  DES是一种对称加密(Data Encryption Standard)算法,以前我写过一篇文章:.NET中加密解密相关知识,有过简单描述。

  DES算法一般有两个关键点,第一个是加密算法,第二个是数据补位。

  加密算法常见的有ECB模式和CBC模式:

  ECB模式:电子密本方式,这是JAVA封装的DES算法的默认模式,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,则补足8个字节(注意:这里就涉及到数据补位了)进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。

  CBC模式:密文分组链接方式,这是.NET封装的DES算法的默认模式,它比较麻烦,加密步骤如下:

  1、首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,就涉及到数据补位了)

  2、第一组数据D1与向量I异或后的结果进行DES加密得到第一组密文C1(注意:这里有向量I的说法,ECB模式下没有使用向量I)

  3、第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2

  4、之后的数据以此类推,得到Cn

  5、按顺序连为C1C2C3......Cn即为加密结果。

  数据补位一般有NoPadding和PKCS7Padding(JAVA中是PKCS5Padding)填充方式,PKCS7Padding和PKCS5Padding实际只是协议不一样,根据相关资料说明:PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。但是封装的DES算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。

  NoPadding填充方式:算法本身不填充,比如.NET的padding提供了有None,Zeros方式,分别为不填充和填充0的方式。

  PKCS7Padding(PKCS5Padding)填充方式:为.NET和JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:

  加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。

  .NET中的DES加密

  对于.NET,框架在System.Security.Cryptography命名空间下提供了DESCryptoServiceProvider作为System.Security.Cryptography.DES加密解密的包装接口,它提供了如下的4个方法:

  1. public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)  
  2. public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)  
  3. public override void GenerateIV()  
  4. public override void GenerateKey()

  从.NET类库封装情况,加解密需要传入一个Key和IV向量。而且Key必须为8字节的数据,否则会直接抛异常出来,当使用ECB模式下,不管传入什么IV向量,加密结果都一样。示例代码如下:

  1. public static string EncryptWithJava(string key, string str)  
  2. {  
  3.     if (key.Length < 8 || string.IsNullOrEmpty(str))  
  4.     {  
  5.         throw new Exception("加密key小于8或者加密字符串为空!");  
  6.     }  
  7.     byte[] bKey = Encoding.UTF8.GetBytes(key.Substring(08));  
  8.     byte[] bIV = IV;  
  9.     byte[] bStr = Encoding.UTF8.GetBytes(str);  
  10.     try 
  11.     {  
  12.         DESCryptoServiceProvider desc = new DESCryptoServiceProvider();  
  13.         desc.Padding = PaddingMode.PKCS7;//补位 
  14.         desc.Mode = CipherMode.ECB;//CipherMode.CBC 
  15.         using (MemoryStream mStream = new MemoryStream())  
  16.         {  
  17.             using (CryptoStream cStream = new CryptoStream(mStream, desc.CreateEncryptor(bKey, bIV), CryptoStreamMode.Write))  
  18.             {  
  19.                 cStream.Write(bStr, 0, bStr.Length);  
  20.                 cStream.FlushFinalBlock();  
  21.                 StringBuilder ret = new StringBuilder();  
  22.                 byte[] res = mStream.ToArray();  
  23.                 foreach (byte b in res)  
  24.                 {  
  25.                     ret.AppendFormat("{0:x2}", b);  
  26.                 }  
  27.                 return ret.ToString();  
  28.             }  
  29.         }  
  30.     }  
  31.     catch 
  32.     {  
  33.         return string.Empty;  
  34.     }  
  35. }




 由于为ECB模式,因此IV这里设置什么值都是可以的,当为CBC模式下,则需要设置为其他值,比如:public static byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },才能正常加密解密。

  JAVA中的DES加密

  JAVA的javax.crypto.Cipher包下,提供了加密解密的功能,它的静态getInstance方法,可以返回一个Cipher对象,一般有public static final Cipher getInstance(String transformation)方法,transformation为:algorithm/mode/padding,分别表示算法名称,比如DES,也可以在后面包含算法模式和填充方式,但也可以只是算法名称,如为:"DES/CBC/PKCS5Padding","DES"等。JAVA中默认的算法为ECB,默认填充方式为PKCS5Padding。Cipher的Init方法用来初始化加密对象,常见的有:

  1. public final void init(int opmode, Key key, AlgorithmParameterSpec params)  
  2. public final void init(int opmode,Key key, SecureRandom random)

  用SecureRandom时,一般用于不需要IV的算法模式,示例代码如下:

  1. public static String encrypt2(String src) throws Exception {  
  2.        SecureRandom sr = new SecureRandom();  
  3.        DESKeySpec ks = new DESKeySpec(KEY.getBytes("UTF-8"));  
  4.        SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");  
  5.        SecretKey sk = skf.generateSecret(ks);  
  6.        Cipher cip = Cipher.getInstance("DES/CBC/PKCS5Padding");//Cipher.getInstance("DES");  
  7.        IvParameterSpec iv2 = new IvParameterSpec(IV);  
  8.        cip.init(Cipher.ENCRYPT_MODE, sk, iv2);//IV的方式  
  9.        //cip.init(Cipher.ENCRYPT_MODE, sk, sr);//没有传递IV  
  10.        String dest = byteToHex(cip.doFinal(src.getBytes("UTF-8")));  
  11.        return dest;  
  12.     }

  当默认用DES,JAVA会用ECB模式,因此这里IV向量没有作用,这里,但当用CBC模式下,如果还是用SecureRandom,则每次加密的结果都会不一样,因为JAVA内部会用随机的IV来初始化Cipher对象,如示例代码,由于Cipher.getInstance("DES/CBC/PKCS5Padding")使用了CBC,因此我这里用的javax.crypto.spec.IvParameterSpec包下的IvParameterSpec来初始化向量IV:

Private final static byte[] IV = new byte[] {0x010x010x010x010x010x010x010x01};

  总结

  对于.NET和JAVA在使用DES对称加密时,需要大家指定一样的算法和填充模式,并且JAVA在写DES加解密算法时,还需要根据创建Cipher对象的不同,正确使用IV向量。在不同系统需要互相数据时,必须要明确的是加密算法,Key和算法模式,再根据不同模式是否需要IV向量,最后是填充模式。

  本文是经过自己翻阅资料和反复调试代码而出来的,如有问题,请指正。

posted @ 2012-05-23 09:24 顺其自然EVO 阅读(883) | 评论 (0)编辑 收藏

性能测试新手误区(三):用户数与压力

同样的项目、同样的性能需求,让不同的测试人员来测,会是相同的结果么?

  假设有这样一个小论坛,性能测试人员得到的需求是“支持并发50人,响应时间要在3秒以内”,性能测试人员A和B同时开始进行性能测试(各做各的)。

  只考虑发帖这个操作,A设计的测试场景是50人并发发帖,得到的测试结果是平均完成时间是5秒。于是他提出了这个问题,认为系统没有达到性能期望,需要开发人员进行优化。

  B设计的测试场景是,50个人在线,并且在5分钟内每人发一个帖子,也就是1分钟内有10个人发帖子,最后得到的测试结果是平均完成时间2秒。于是他的结论是系统通过性能测试,可以满足上线的压力。

  两个人得到了不同的测试结果,完全相反的测试结论,谁做错了?

  或许这个例子太极端,绝对并发和平均分布的访问压力当然是截然不同的,那我们再来看个更真实的例子。

  还是一个小论坛,需求是“100人在线时,页面响应时间要小于3秒”。A和B又同时开工了,这时他们都成长了,经验更加丰富了,也知道了要设计 出更符合实际的测试场景。假设他们都确认了用户的操作流程为“登录-进入子论坛-(浏览列表-浏览帖子)×10-发帖”,即每个用户看10个帖子、发一个 帖子。于是他们都录制出了同样的测试脚本。

  A认为,每个用户的操作,一般间隔30s比较合适,于是他在脚本中的每两个事务之间加上了30秒的等待(思考时间)。

  B想了想自己看论坛时的情景,好像平均每次鼠标点击要间隔1分钟,于是他在脚本中的每两个事务之间加上了1分钟的等待。

  他们都认为自己的测试场景比较接近实际情况,可惜测试结果又是不同的,很显然A场景的压力是B的两倍。那谁错了呢?或者有人说是需求不明确导致的,那么你需要什么样的需求呢?

  看看我随手在网上(51testing)找的提问吧,和上面的内容如出一辙。一定有很多的性能测试人员每天接到的就是这种需求,又这样就开展了测试,结果可想而知。

  这里我想问几个问题,希望各位看完了上面的小例子后想一想:

  如果有另一个人和你测同样的系统,你们的测试结果会一致么?
  如果不一致,那么谁是正确的?
  如何证明测试结果是有效的?

  如果你有了一些疑惑,对之前的测试结果少了一些自信,那么请继续。

服务器视角 vs. 用户视角

  性能测试中非常重要的一块内容就是模拟预期的压力,测试系统运行在此压力下,用户的体验是什么样的。

  那么压力是什么?压力是服务器在不断的处理事情、甚至是同时处理很多事情。压力是服务器直接处理的“事情”,而不是远在网络另一端的用户。

  下图中,每一个颜色的线段代表一种操作。在任意一个时刻,服务器都知道它有10个事务需要处理,这10个事务也是有10个用户产生的。但它不知道的是,整个时间段内的所有事务,是由多少个用户与系统交互而产生的。

  这句话好像有点绕,我再试着更形象的解释一下。时刻1,10个当前事务是由10个用户发起的。时刻2,依然是10个正在进行的事务,但可能是完 全不同的10个人发起的。在这段时间内,服务器每一个时刻都在处理10个事务,但是参与了这个交互过程(对服务器产生压力)的人可能会达到上百个,也可能 只有最开始的10个。

  那么,对于服务器来说,压力是什么呢?显然只是每时刻这10个同时处理的事务,而到底是有10个人还是1000个人,区别不大(暂不考虑session等问题)。

  下面再从用户的视角来看看。实际的情况中,不可能出现很多用户同一时刻开始进行操作的场景,而是有一定的时间顺序的。正如下图所示,在这个时间段内,一共有23个用户进行了操作。

  但是服务器能看到这些用户么?它知道的只是某一个时间点上,有多少个正在执行的事务。大家可以数一下,此图中任意时刻的并发事务依然是10个。

  其实这两个图描述的本来就是同一个场景,只不过观察者的视角不同罢了。

  那么大家想想,在性能需求中最常见到的“并发用户”到底是指的什么呢?

并发用户

  很多使用“并发用户”这个词的人,并没有从服务器视角进行考虑。他们想的是坐在电脑前使用这个系统、对系统产生压力的人的个数。基于这个原因, 我很少使用这个容易让人误解的词汇,而是进行了更细的划分。主要有这么几个:系统用户数(注册用户数)、在线用户数(相对并发用户数)、绝对并发用户数。

  上面几个例子中所说的“并发用户”,实际就是在线用户数。其实我更喜欢叫做相对并发用户数,因为这个词更容易让人感受到“压力”。相对并发用户 数指的是,在一个时间段内,与服务器进行了交互、对服务器产生了压力的用户的数量。这个时间段,可以是一天,也可以是一个小时。而需求人员必须要描述的, 也正是这个内容。

  而绝对并发用户,主要是针对某一个操作进行测试,即多个用户同一时刻发起相同请求。可以用来验证是否存在并发逻辑上的处理问题,如线程不安全、 死锁等问题;也可提供一些性能上的参考信息,比如1个用户需要1秒,而10个用户并发却需要30秒,那很可能就会有问题,需要进行关注,因为10个用户请 求排队处理也应该只需要10秒啊。但这种绝对并发的测试,同实际压力下的用户体验关系不大。

  再回到相对并发这个概念上来,它与服务器的压力到底是什么关系呢?如果你理解了前面的所有内容,那么就会知道这两者其实没有直接联系(当然了,同一个测试用例中,肯定是用户数越多压力越大)。也就是说,你得到的这种性能需求,是无法知道服务器到底要承受多大压力的。

  那么如何开展性能测试?

如何模拟压力

  既然我们知道了所谓的压力其实是从服务器视角来讲的,服务器要处理的事务才是压力,那么我们就从这出发,来探寻一下性能测试需要的信息。依然用之前的小论坛为例,我们需要测试活跃用户为500人时,系统的性能是否能还能提供良好的用户感受。

  假设现在的活跃用户有50个人(或者通过另一个类似的系统来推算也行),平均每天总的发帖量是50条、浏览帖子500次,也就是每人每天发一个 帖子、浏览十个帖子(为了方便讲解,假设论坛只有这两个基本功能)。那么我们就可以推算,活跃用户达到500时,每天的业务量也会成比例的增长,也就是平 均每天会产生500个新帖子、浏览帖子5000次。

  进一步分析数据,又发现。用户使用论坛的时间段非常集中,基本集中在中午11点到1点和晚上18点到20点。也就是说每天的这些业务,实际是分布在4个小时中完成的,如下图(随便找了个图意思一下,数不一致)。

  那我们的测试场景,就是要用500个用户在4小时内完成“每人发一个帖子、浏览十个帖子”的工作量。

  注意上面的两处,“平均每天……”、“分布在4个小时……”。敏感的测试人员应该能发现,这个场景测的是平均压力,也就是一个系统最平常一天的使用压力,我喜欢称之为日常压力。

  显然,除了日常压力,系统还会有压力更大的使用场景,比如某天发生了一件重要的事情,那么用户就会更加热烈的进行讨论。这个压力,我习惯叫做高峰期压力,需要专门设计一个测试场景。

  这个场景,需要哪些数据呢,我们依然可以从现有的数据进行分析。比如上面提到的是“平均每天总的发帖量……”,那么这次我们就要查到过去最高一 日的业务量。“分布在4个小时”也需要进行相应的修改,比如查查历史分布图是否有更为集中的分布,或者用更简单通用的80-20原则,80%的工作在 20%的时间内完成。根据这些数据可以再做适当的调整,设计出高峰期的测试场景。

  实际工作中可能还需要更多的测试场景,比如峰值压力场景。什么是峰值压力呢,比如一个银行网站,可能会由于发布一条重磅消息使访问量骤增,这个突发的压力也是性能测试人员需要考虑的。

  需要注意高峰期压力和峰值压力的区别,高峰期压力是指系统正常的、预期内压力的一个高峰。而峰值压力是指那些不在正常预期内的压力,可能几年才出现一次。

  这里只是举了个最简单的例子,实际工作远比这复杂的多。需要哪些数据、如何获取,很可能要取得这些数据就要花费很大的功夫。这其实就涉及到了一个很重要的内容,用户模型和压力模型的建立,以后会有专门的文章进行讲述。

  为什么要花这么大的精力来收集这些信息呢?是因为只有通过这些有效的数据,才能准确的去模拟用户场景,准确的模拟压力,获取到更加真实的用户体验。只有这样,“不同的测试人员,测出相同的结果”才会有可能实现,而且结果都是准确有效的。

要点回顾

  最后通过几个小问题来总结回顾一下:

  你真的理解“并发用户”的意义么?
  什么是用户视角和服务器视角?
  什么是压力?
  如何模拟预期压力?

posted @ 2012-05-21 12:06 顺其自然EVO 阅读(253) | 评论 (0)编辑 收藏

性能测试新手误区(二):为什么我模拟的百万测试数据是无效的?

 

  测试环境的重要性无需多说,大家都知道测试环境要尽量的模拟生产环境,当然也包括数据。这样测试的结果才会更加准确的反应真实的性能。就连开发过程,都已经开始在大数据量下加压开发了。那么,关于测试数据,你了解多少呢?

  通常说的测试数据可以分为两类:

  一是为了测试性能而准备的数据,这是用来模拟“压力”的数据。也就是常说的数据量、历史数据等。一般都会根据需求或者经验很容易估算出来,比如案件年增长量为5%,去年数据量为100W,测试需要保证3年后系统仍可正常运行,那么就需要计算并模拟出3年后的总数据量,在这个基础上进行测试。

  二是用来辅助测试使用的数据。比如有一个对案件进行打分的功能,只有符合一定条件的案件才会出现在打分列表 中。那么我们要测这个打分的操作,首先就要保证有可用的案件,这就需要去生成测试数据,该数据可能一经使用就失效了(已经打过分就不能再打了)。这样,每 次测试这个功能,就需要准备这样一批数据。这里的测试数据,更多的是和测试流程有关,是为了能够正常的进行测试,而不是涉及到性能的。

  我们这里要说的是第一类,对性能测试结果产生直接影响的数据。

  先看两个小案例,涉及到了案件表(T_AJ)和法院编号列(N_FY)、立案日期列(D_LARQ)。案件表中模拟了一百万测试数据,测试简单的查询操作,根据经验,预期响应时间在2秒之内。

  案例1. 查询本院案件列表,相应的SQL如下:

select * from T_AJ
where N_FY=10
order by D_LARQ desc
  执行这个操作耗时近10s,显然达不到正常预期。

  经排查,生成的100W测试数据中,所有的N_FY列值都为10。这样,最明显的问题就是,查询的结果集数量完全偏离了正常范围。如果实际有 100家法院,正常分布下,每家法院只有1W的案件,但测试数据的FY只有一个值,通过这个查询,查出了原来100家法院的数据。无论是在数据库处理中 (如本例的排序),还是在程序的处理中(如展现或者是对数据做进一步处理),两者的性能差异都是很显著的。所以这个测试结果是无效的。

  有人说,这个例子太弱了,结果集差了100倍,性能当然不一样了。那是不是数据总量和结果集大小都一致,测试结果就是有效了呢?

  案例2. 查询本院一个月内收的案件,相应SQL如下:

select * from T_AJ
where N_FY=10 and D_LARQ between '20110101' and '20110201'

  这个操作,查出来的结果只有一千条数据,属于正常范围。但查询的时间还是超过5秒,依然超出了我们的预期。

  查看数据发现,N_FY=10的数据有近50万,占了总数据量的一半,D_LARQ在一月份的数据也占了差不多一半。但是同时符合两个条件的数据还是一千条左右。那么这里的问题就不在于结果集了,而是是否能利用索引进行查询,看如下两个图就能很好理解了。

  在正常数据中,每家法院的数据可能占总数据量的1%,一个月时间段内的数据可能占总数据量更少,假设是0.5%。那么这时我们通过N_FY和 D_LARQ两个条件进行查询,数据库会进行估算:符合D_LARQ查询条件的数据大概有5000条,符合N_FY查询条件的数据大概有1万条,那么用 D_LARQ上的索引进行查询是最快的,可以迅速的将查询范围缩小到5000条,然后在这5000条中去检查N_FY是否也符合条件。

  过程如图一所示(手绘草图^_^)。

  

图一

  注:数据按行存储,小方块表示符合该列查询条件的数据,阴影表示符合所有查询条件,也就是最终的结果集。箭头线段表示为了完成查询,需要扫描的数据量,本图中即符合LARQ查询条件的数据。下同。

  但在本例中不正常的数据条件下,数据库会知道:符合N_FY查询条件的数据有50万条,符合D_LARQ的也有近50万条,如果使用其中一列的 索引将一百万的范围缩减到50万,比从头到尾扫描整个表做的工作还要多(为什么呢?需要了解索引的结构和原理),那还是不要用索引了吧。于是数据库会依次 检查每一条数据,判断N_FY和D_LARQ是否符合条件。

  如图二所示。

图二

注:本图中实际扫描的数据量就是整张表的数据,但结果集和图一是一样大的。

  这样,就可以知道,总数据量一样,结果集大小一样,为什么性能差了很多了。就是因为数据分布不合理,导致数据库无法正常使用索引,从而进行了全 表扫描。当然,这个数据分布,我们依然可以归类到结果集中去,那就是要保证每一个查询条件“单独的结果集”都要符合真实情况,而不仅仅是整个查询最终的 “总结果集”。

  看个这两个简单的小例子,我们再来总结一下关于测试数据,需要注意的内容:

  1. 最根本、也是大家都知道的就是数据量,性能测试必须保证能在预期的数据量下进行测试。在一万条记录中查询,和在一百万数据中查询,显然是大大不同的,可以把数据量看做一种“压力”,这个就不用再解释了。

    但是在比较大型的系统中,这一点可能也不是很容易做好,因为这类系统往往有着复杂的数据库,上百张的数据表。对每张表都进行数据模拟显然是不现实 的,也是没有意义的,因为不是每张表都涉及到大数据量。那么如何选取不容易遗漏呢?通常通过两种方式:从设计和业务角度分析表间关系、从现有实际数据量进 行分析推测。

  2. 确保结果集在正常范围内。结果集的大小直接影响后续很多工作的性能,如数据排序分组、分页、程序中的逻辑校验或者是展现。

  3. 数据分布必须合理,尽量接近真实。数据的分布,其实也就是数据的真实性,它直接决定了数据库是否使用索引、选用哪个索引,也就是常说的查询计划。不同的查询计划也就是不同的数据访问路径,性能差别可能会很大。

    这里主要涉及到的是索引的问题,需要大家对索引的原理有一定的了解,索引如何工作、数据库如何选择索引、和索引有关的一写重要概念如区分度(selectivity)等等。

  4. 最好的数据来自生产环境。这是显而易见的,使用真实的数据测出来的结果才是最准确的。但是绝大多数情况下,我 们没有这样的好运,可能是客户禁止、也可能是生产环境数据量比较小。那就只好自己想办法来模拟了,需要注意的也就是上面说到的几点。这里再推荐一种方法, 数据翻倍。比如已经有了真实的数据十万条,但我们需要一百万条,那就可以通过写一些SQL或者存储过程,将现有的数据不断翻倍(简单的说,复制到临时表, 根据需要修改一些列,再插回到原表),这样的数据真实性还是比较高的。

  关于测试数据,我想说的就是以上几点了。另外再补充上一些相关内容,也是性能测试人员需要关注的。

  • 重点了解IO的概念,更准确的说应该是物理IO。一般来讲,数据库的瓶颈或者查询的主要耗时就是IO。所以,数据库优化的一个重要方向就是尽量减小IO。

    IO是不是只和数据量(行数)有关呢?举一个例子:

    select co1, col2, col3, col4, col5 from T_AJ 
    where condition...

    T_AJ数据量有100万,表中有近200列,此查询耗时大于10秒。而另一种实现方式,首先将col1-col5以及查询条件中的几个列的数据抽取到一张临时表(#T_AJ)中。然后,

    select co1, col2, col3, col4, col5 
    from #T_AJ where condition...

    临时表#T_AJ和原数据表有同样的数据量(行数),但是此查询却只需要1秒(暂不考虑抽取到临时表的耗时),这就是不同IO引起的差异。通常我们 使用的数据库都是行式存储的,可以简单的理解为,一行数据从头读到尾,才能进入到下一行。这样,不管一行中的200列,你只读取其中的一列还是几列,其余 的190多列仍然需要一定的IO。在大数据量下,这个性能差异就很明显了。所以上面的这个例子就是一种典型的优化手段,索引覆盖也是处理类似问题的典型方 法,各位自行了解吧。列式存储数据库(如Sybase IQ)之所以性能这么高,也是同样的道理。

  • 尽量深入了解这些概念,如执行计划,基于开销的估算,统计信息等等。我用一句话来简单描述:数据库通过统计信息来估计查询开销,统计信息不准时,开销估计就可能不准确,从而导致选择了错误的执行计划。

  • 测试过程中数据的清理。性能测试过程中可能又会生成大量的数据,积累到一定程度又会对性能结果造成影响,所以每一轮测试时都应该清理掉之前测试过程中产生的数据,保证每次测试是在相同的条件下进行的。

  • 性能测试过程中,如果定位到了某一个查询或SQL有问题,首先要确认的是数据是否合理。通过查询计划来判断是否按预期进行了查询,如果不是,查看数据的分布是否真实。一般数据库会提供很多种手段来进行验证。

posted @ 2012-05-21 12:04 顺其自然EVO 阅读(279) | 评论 (0)编辑 收藏

性能测试新手误区(一):找不到测试点,不知为何而测

 有过一些性能测试经验的人很容易进入此状态,他们已经熟悉了性能测试的基本流程,能够比较熟练的使用测试工具开展工作。我大概从事性能测试一年左 右时遇到了这个问题,那时我觉得性能测试的过程没有太多挑战,遇到的每一个系统,仿佛都可以用同样的流程完成。半天时间填写测试方案,一天时间来准备测试 环境,一天时间准备测试脚本,一到两天来完成各种测试用例(基准测试、日常压力测试、峰值压力测试、绝对并发测试、稳定性测试等),然后就是调优、问题复 测和完成测试报告。在我看来,性能测试好像变成了用一些工具去执行一个个固定的用例。

  这样的工作持续了一段时间后,我感到有些不对劲,一定是哪里出了问题。性能测试难道真的这么简单,简单到把任何一个系统套入标准的流程中就可以 了?于是我开始思考测试的意义,为什么要进行性能测试?是因为性能测试可以提供关于瓶颈、缺陷、效率等等我们认为有价值的信息。那仅仅通过一个工具,或者 是一个固定的流程,就可以发现不同系统的这些信息么?这显然是不可能的。

  我开始尝试尽量深入的去理解被测系统,这个系统的目的是什么,用户是如何使用系统的,用户对哪些业务的性能比较敏感,系统的一些关键业务实现逻 辑是怎么样的,从设计实现的角度来看哪些业务的性能可能存在隐患。这些很少是技术层面上的问题,需要做的只是思考,再深入思考。慢慢的我有了些收获,开始 了解为什么要测这个系统,针对这个特定的系统哪些内容是最重要的,为了获得需要的信息我需要从哪几个方面进行测试,为了实现我的想法又需要哪几种方法或者 工具。(现在我的性能测试过程中,用于理解被测系统、理解用户、整理测试思路的时间投入大大增加了。你呢,投入了多大比例?)

   要做好这些其实很难,每一个被测系统对我来说,仿佛就变成了一个新的挑战。但是逐渐的我发现自己思考问题更全面了、可以更快的抓住系统的重 点、找到更重要的BUG、对系统的实际性能有了更准确的评估。这里提一个简单的问题,如何确保你的测试结果和生产环境的性能表现是一致的,也就是说测试结 果能够真正的反应实际的性能,而不仅仅是代表了你选取的几个测试场景的性能。话说起来比较绕,但是请认真想一想,你有多大的把握呢?

   上面只是写了一些个人的感想,我觉得如果在“思想”上没有办法上到一个新的台阶,你的性能测试生涯可能也就达到“瓶颈”了。如何突破这个瓶 颈,那就需要努力改变自身,多思考多学习,最核心的能力恐怕不是能培训出来的。一定会有一些人认为性能测试的重点在于“技术”上,于是他们不断的记住各种 调优配置参数,以为自己掌握了性能的精髓,仿佛什么系统到了他们手上,只要改几个参数就会出现奇迹。我也经历了这个阶段,也有过几次自以为挺高明的调优经 历,也为自己会各种中间件数据库的配置调优而有些小得意。但现在想想,那还真是一个比较低的层次,思想上抓不住重点、看不全大局,技术上其实也只是一点皮 毛。面对这类人,只要问几个为什么就会让他们无法回答,为什么要调优?为什么要调这个参数?如何证明这次调整的效果?

   将上文简单的总结成几点,希望能给性能测试新手提供一丁点的帮助吧:

  1. 性能测试的难点在于对被测系统的理解,在于对测试点的分析。为了实现测试的思想,可以有多种方法,手段永远只是辅助的,只有思想才是根本的。工具 (如LR)更不等于性能测试,不要以为会用LR就懂了性能测试,那只是最低级的测试执行。也不要以为会调几个参数就懂了性能测试,那同样是个比较低的层 次。
  2. 调优等技术不是性能测试的主要目的,好的性能也不是调出来的。测试人员一定要明白自己存在的价值所在,所谓的“技术”只是为了达成自己测试目的的一些手段,同开发人员、DBA相比,你在这些技术上永远是外行。
  3. 不要照着文档模板,填入测试方案。每一个系统都是不同的,要真正的认识到这一点,为每个系统设计出有针对性的测试方案。思考你每一步工作的意义和目的。
  4. 如何证明测试结果的有效性,其实是个很难的问题,值得花费时间去认真思考。这个过程涉及到一些很重要的内容,如用户模型的建立,后续会有专门的文章。
  5. 性能测试是一个需要不断改进的过程,每一次只需尽量的做到更好,多做一点点以前没有想到的东西。经过不断的积累,你会发现自己对性能测试有了更深的认识。

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

性能测试浅谈

本文主要针对WEB系统的性能测试。不涉及具体的执行操作,只是本人对性能测试的一点理解和认识。

  性能测试的目的,简单说其实就是为了获取待测系统的响应时间、吞吐量、稳定性、容量等信息。而发现一些具体的性能相关的缺陷(如内存溢出、并发 处理等问题),我认为只是一种附加结果。从更高的层次来说,性能测试最想发现的,是瓶颈。如何能得到所需要的信息,就需要从多方面进行测试。

  性能测试的内容

  性能测试种类的划分与定义这里就不说了,各有各的说法,比如性能测试、负载测试、压力测试这三个词,在网上能找到N个版本的定义,大体理解就行 了,没必要在文字层面上较这个真。以下的内容也只是我个人的理解,一些名词的定义可能和其他资料有所不同,但在我的工作中,这样是比较形象和容易理解的。

  在实际工作,一般的应用系统会从这么几个方面进行性能测试。 

  1.基准测试
  Benchmark或者Baseline测试。一般为单用户测试,或者是零数据量环境下的测试。目的在于建立一个可度 量的参考标准,为其他测试场景或者调优过程提供对比参考。也可认为是最基础的性能测试,如果基准测试的结果都不能达到预期要求,那么后续场景也就没必要测 试了。

  2.日常压力测试
  在基准测试通过后,应该先进行较小压力下的测试,首先对系统在日常压力下的表现进行测试。此压力需要根据系统使用相关数据得出,如系统平均每天访问量、平均在线人数、每日完成事务数等。通过此测试,发现一些较表面的性能问题并进行处理。

  3.峰值压力测试
  在日常压力测试通过后,需要进行更大压力的测试。此处压力同样需要相关数据的支持,一般为未来几年后的预期压力。 可根据历史日均压力、日最高压力等信息,估算出未来几年的日均以及日最高压力。再通过一些通用估算方法、如二八原则(80%的工作在20%时间内完成,相 当于2小时完成一天8小时的工作量),将日压力转换成峰值压力。
  峰值压力为可预期到的最大负载压力,通过了此测试,则认为系统有能力满足未来增长的压力。

  4.容量测试
  验证了系统是否可满足预期的压力后,还需要知道系统能够承受的最大压力,也就是容量。一般通过“拐点法”进行测试,逐步增大系统的压力,直到性能指标不可接受或者出现了明显的拐点。如下图,拐点在哪?

  5.稳定性测试
  验证系统是否可长期稳定的运行,是否存在一些短时间内可能无法发现的缺陷(如内存溢出、数据库连接不释放等)。为了 缩短测试工期,一般可将预期一天的压力集中在2小时内完成(二八原则),这样持续加压10小时,便相当于系统运行5天。注意监控各种性能指标是否平稳,有 无下降。

  以上几种类型的测试,是性能测试过程中最多用到的。当然也也其他一些比较常用的类型,如绝对并发测试,测试多用户对某一功能的瞬时请求,主要用 于验证系统是否存在并发逻辑上的处理问题。此测试也可划分到不同的压力测试场景中去,根据不同的用户压力,测试相应的绝对并发,一般取在线用户数的10% 进行测试;突发压力测试,对一些不在预期内的突然压力进行测试(其实既然想到了,就应该是在预期内了)。以银行门户网站为例,可能会由于发布了一条重要消 息(政策调整)而导致访问量激增,这种压力是否会导致系统宕机或者暂时无法提供服务,就是突发压力测试需要考虑的了。也有人将此压力定义为峰值压力,这就 无所谓了,只要考虑到会有这么一个问题就够了。

  性能测试的阶段

  上面主要说的是测试内容的划分,也就是说做性能测试时要考虑到的几个方面。从实际执行层面来看,测试的过程一般分为这么几个阶段:

  1.测试确认
  理解被测系统、寻找测试点、确认测试范围、测试环境等。一些重要信息需要同PM、需求人员、设计人员讨论确认,如用户最常用哪些功能、最关注哪的性能,程序上哪可能是压力点,哪些数据需要模拟到真实的量级,大体上需要使用哪种测试方法。

  2.确定通过标准
  性能是好是坏、测试是否通过,必须有明确的标准。这个标准,主要从客户的期望和业务上的需求两方面来考虑,客户的 期望一般指页面上的响应时间,业务需求则是系统的处理能力,一般为吞吐量或TPS(每秒完成事务数)。标准制定的不合理,测试结果可能无法反映系统真实的 性能表现,或者会让客户无法接受我们认为通过的软件。
  至于具体如何去设定,是需要同业务负责人(一般为PM)和技术负责人(一般为设计人员)共同确认的,业务负责人了解用户的实际需求和期望,技术负责人了解具体的实现,可以判断哪些是不可达到的要求。
  一旦达成了共识,那么测试就要严格的按照标准去执行。

  3.测试设计
  主要从上面提到的几个方面进行分析,针对系统的特点设计出合理的测试场景。为了让测试结果更加准确,这里需要很细致的 工作。如建立用户模型,只有知道真实的用户是如何对系统产生压力,才可以设计出有代表性的压力测试场景。这就涉及到很多信息,如用户群的分布、各类型用户 用到的功能、用户的使用习惯、工作时间段、系统各模块压力分布等等。只有从多方面不断的积累这种数据,才会让压力场景更有意义。最后将设计场景转换成具体 的用例。
  测试数据的设计也是一个重点且容易出问题的地方。生成测试数据量达到未来预期数量只是最基础的一步,更需要考虑的是数据的分布是否合 理,需要仔细的确认程序中使用到的各种查询条件,这些重点列的数值要尽可能的模拟真实的数据分布(数据统计信息、执行计划相关的内容,此处就不细说了), 否则测试的结果可能是无效的。
  此外,性能测试执行过程中,需要监控收集的各种指标数据,也需要明确下来。

  4.测试环境准备
  部署测试环境,生成测试数据,环境预调优等等。预调优指根据系统的特点和自己的经验,提前对系统的各个方面做一些优化调整,避免测试执行过程中的无谓返工。比如一个高并发的系统,10000人在线,连接池和线程池的配置还用默认的,显然是会测出问题的。

  5.测试执行、监控
  准备测试脚本,执行之前设计好的各个用例,监控并收集需要的数据。出现问题时,切记要全面的保留事故现场、或者是能进行分析的数据。比如TOMCAT不再响应,不能只把这个现象记录下来,这对问题的排查定位是没有意义的,要保留所有相关的日志,导出线程转储和堆转储。

  6.问题分析定位、调优
  发现问题或者性能指标达不到预期,及时的分析定位,处理后重复测试过程。
  性能问题通常是相互关联相互影响的,表面上看到的现象很可能不是根本问题,而是另一处出现问题后引起的反应。这就要求监控收集数据时要全面,从多方面多个角度去判断定位。
  调优的过程其实也是一种平衡的过程,在系统的多个方面达到一个平衡即可。

  7.性能报告
  将测试过程中记录的各种数据汇总成报告,将各方面需要的结果清楚的展现出来。

  上面所有内容中,如果排除技术上的问题,性能测试中最难做好的,就是用户模型(或者叫系统使用模型)的分析。它直接决定了压力测试场景是否能够 有效的模拟真实世界压力,而正是这种对真实压力的模拟,才使性能测试有了更大的意义。可以说,性能测试做到一定程度,差距就体现在了模型建立上。

  至于性能问题的分析、定位或者调优,很大程度是一种技术问题,需要多方面的专业知识。数据库、操作系统、网络、开发都是一个合格的性能测试人员需要拥有的技能,只有这样,才能从多角度全方位的去考虑分析问题。

  当然,对于测试人员来说,技术能力只能排在第二号,测试思想才是最根本的。敏锐的嗅觉、严谨的逻辑、合理的推测、大胆的实践是一个合格测试工程师的必备要素。

  模拟演练

  写了一大堆,新手还是不知道如何去做。其实写本文的目的也不是讲具体操作,而是思想,思想。新手学性能测试,建议找一本从LOADRUNNER开讲的书比较好。如51TESTING上有连载的《性能测试从零开始》。

  不过还是尽量说点具体些的内容吧。

  普通BS架构的系统,一般都采用测试工具(如LR)直接录制手工操作的方式进行测试。这种方式简单有效,对测试人员要求不高。但在一些情况下, 这种基于录制的方法可能无法完成,比如页面上有特殊控件、系统是CS架构、或者通讯的协议无法捕获等。这时就需要更复杂的测试方法,如手动编写模拟客户端 的JAVA代码,而把测试工具当作一个调度控制台,去调度大量的虚拟用户线程执行编写好的代码。

  现在假设有一个简易版的12306网站,JAVA实现,中间件为TOMCAT,数据库为SYBASE,没有集群处理(一切从简,只有查询和订票功能)。如何对它进行性能测试呢?

  按照上面的几个步骤来想一想吧,这里只简单写几点。

  第一步,测试确认。海量并发,数据也应该是海量的,但基本都是简单查询,没有复杂的统计,所以主要困难还是在海量并发事务的处理上。中间件、数 据库上都会承受巨大压力。此类高并发系统还需要对一些功能特别注意,比如一个车次有10张票,5个人同时购票,如何处理?如果是12个人同时点购票,又是 如何处理?

  第二步,通过标准。无非是系统能够满足多少人同时在线,一分钟内能处理多少订单,用户最大等待时间是几分钟。注意这个标准一定要是经过各方面确认过实际可行的啊,定一个订单响应时间不超过5秒有意义么?确认了以后,就要按着这个目标来设计测试和执行。

  另一个需要注意的问题,按照预期的压力测试通过了以后,是不是就高枕无忧了?答案是否定的,因为很可能这个预期或者标准是不合理的,这个是非常 可能的,只有长期的数据积累,才会一点点走向精确。想想奥运订票系统,开通后短短五分钟,网站就瘫痪了,你们以为这种系统没有经过专业的性能测试么?据我 所知,奥运订票系统性能测试时制定的标准是每分钟处理四百万访问(具体数据记不住了,就假设是这个数吧),出事后的检查发现,每分钟的访问量超过了八百 万。这种事故责任在谁呢?测试机构敢拍胸脯保证,每分钟处理四百万就是没问题的。而奥组委自己设定的每分钟四百万目标,和实际出现偏差也是正常的,毕竟这 种系统是第一次上线。最后的处理方法就是,压力达到了预期最大值以后,再后来的访问就被排队了。好好体会这个案例吧,会有收获的。

  第三步,测试设计。设计用户模型,设计测试场景,设计测试用例。一个典型的用户是如何使用系统的?登录、查询车次余票、订票、付款,这是理想化 的情况。实际更可能是这样的,登录(一次登不进去,重复多次)、查询A车次(未到放票时间、不断重试,时间到无票)、查询B车次(无票)、查询C车次(有 票)、订票、付款、查询订单。两种交互方式对系统产生的压力,差别是很大的。

  将多个用户行动整合到一起,也就是用户模型,或者叫系统使用模型,是压力场景设计的依据。假设系统一天的访问量是一万个用户,这一万访问量是在 24小时内平均分布的,还是分布在8小时内,还是在某一时间点上集中访问?这些具体到用例中也就是虚拟用户的加载策略,直接决定了压力的大小。

  除了这个压力场景,针对此系统还需要进行绝对并发测试,参考第一步的分析。

  第四、五步就不细说了,准备环境、数据,针对大量用户的并发进行一些预调优。按照第三步设计好的各个测试用例准备脚本、执行测试。

  第六步,发现问题了怎么办?比如1000人的压力下,系统响应就比较慢了,查询车次需要1分钟,下订单需要2分钟,接下来要做什么?能把这些作 为一个性能缺陷提起么?显然是不可以的,这只是通过你的压力测试场景产生的一个现象,可能是测试脚本有问题、也可能是测试环境有问题。作为一个性能测试人 员,需要尽量深入的定位到问题产生的原因。就像这个响应慢,只是一个表面现象,慢在哪?是中间件还是数据库?一些简单的测试方法就可以进行判断,如在页面 上进行一些数据库无关的操作,如果依然比较慢,说明在中间件上压力就已经比较大了。还可以部署另一套中间件测试环境,连接之前相同的数据库,在压力测试出 现问题的同时,手动访问新部署的应用(只有一个用户),如果同样很慢,那说明慢在了数据库端的处理上。还可以通过日志的方式更准确的进行判断,如应用日志 和数据库SQL执行日志。总之方法是多种多样的,但目的只有一个,就是不断的排除无关部分、缩小问题范围。

  定位到了中间件和数据库之一,然后又该怎么办?此时恐怕就需要一些相关方面的专业知识了,但其实最常见的还是那些。中间件相关的一般是线程池、 JVM、数据库连接池等,数据库相关的有锁、缓存、IO(一般就是SQL语句的问题)等。要进行全面的监控和分析,再做一些合理的调优并重复测试。

  问题定位到什么程度才行?我认为是要让人看了知道改哪就可以了。比如提一个“这个SQL语句进行了大量的物理IO,性能不好”,这就不是个好问 题,物理IO是什么?怎么改?如果这么说就好多了“这个SQL语句没有使用索引,导致了全表扫描,进行了大量的物理IO,性能不好。如果要避免全表扫描, 需要调整SQL语句或者添加XX索引”,这才是定位问题。

  当然了,上面只是一个非常简陋的举例,真实的性能测试要比这复杂的多。

  总的来说,我认为,性能测试的难度主要不在技术手段上,互联网时代技术都是共享的,要善于去搜索利用他人的成果。即使自己搞不定,团队内一定还 有专业的开发工程师、数据库管理员、系统管理员可以帮你搞定。真正的难点在于,你要想出来如何去测是有效的、有保障的,这才是测试工程师最重要的能力。 

  还是那个观点,思想才是根本。

posted @ 2012-05-21 11:59 顺其自然EVO 阅读(268) | 评论 (0)编辑 收藏

自动化测试:功能测试设计七技巧

 自动化功能测试,或用户界面(UI)测试,以难以维护而著称,而且没有足够的能力找出缺陷。然而,在大多数情况下出现故障的原因不是测试工具或者测试框架,而是个别测试本身跟踪设计不良。

  下面有七个功能测试设计技巧,让UI测试更加可维护和更强力。

  不要只是点击 要检查后续状态

  很多自动化测试工具包含一个特性,就是可以自动记录一系列动作,然后回放。尽管这样的记录/回放功能在创建测试时容易驾驭,但是单纯的记录/回放动作会导致不良测试。具体而言,记录/回放测试并不会检测应用中操纵元素后的应用状态。

  点击、键入、选择以及其他的功能都会以某种方式改变应用的状态。好的测试会在应用中操作元素后检查本身的结果。如果自动化测试跟随一个链接,就要让测试检查结果页是否正确。如果测试生成一个报告,就要检查报告内容是否正确。

  等待,请勿停止

   通常,一个应用在结果可以用测试检查之前需要一些时间。这一点在Ajax在Web浏览器调用中尤为普遍。简单地进行测试停止或者在检查这样的结果之前休 眠几秒是很吸引人的,但是停止或者休眠是不良实践,如果应用用过长时间返回,然后测试就会生成错误失败。如果应用更快地返回,然后测试在转移的过程中就是 浪费时间。

  取代停止或者休眠,让测试等待应用的具体方面出现了。这不仅仅让测试减少错误失败的倾向,而且也导致了更强的测试,因此测试根据生成的测试等待方面,实际等待检查应用结果。

  使用分离定位 不是索引

  做测试的时候要是像“点击这个页面上的第三个链接”或者“选择列表上的第五个元素”这样就更好了。代替根据索引操纵应用的具体方面,为这样的元素找出或者创建唯一识别符值得努力。

  如果命令链接改变了,或者命令列表改变了,测试就会导向一种预期外的路径,维护这样不可预知的测试相当难。

  用正则表达式检查排列次序

  应用以正确的序列显示给用户非常重要。无论是表格的列数还是列表的元素,或者是页面本身的文本,自动化测试检测事物正确的排列很重要。

  这有一堆事情应该以“一”、“二”、“三”的顺序出现。测试可以使用类似的正则表达式检查出这些事情序列。下面是一个使用简化的正则表达式“glob”的例子,“glob”在Selenium以及其他自动化测试工具中可用:

以下是引用片段:
| getText | glob:one*two*three |
| click | sort_thing |
| getText | glob:three*two*one |

   这个测试检查的第一步是输入文本“one”,随后是文本“two”,然后是“three”。“*”表明测试允许“one”"two""three"之间 任意的字符。测试第二步点击导致“one”“two”“three”倒序排列,然后测试第三步检查这个排列是否成功了。

  一次且仅一次

   正如上面所指出的,在应用中等待一个元素出现是较好的实践。通常这样的例子中一旦元素出现,测试会希望操作这个元素,实例就是点击。这是抽象通用动作到 期自己的方法或者模型的最佳实践,然后测试按需调用这些动作。下面是一个例子,在Fitnesse和Selenium语法中wait-for-and- click抽象。

以下是引用片段:
!| scenario | Wait for and click | elementLocator |
| waitForElementPresent | @elementLocator |
| click | @elementLocator |
So from a test itself we need only write:
| open | www.foo.com |
| Wait for and click | link=Welcome to Foo! |
 这个例子中仅节省了一行键入,如果“Wait for and click”在测试套件中执行了数百次或者数千次,可维护性和可读性。另一个动作例子就是抽象到期自己可能登陆的模型,选择列表中的所有元素,为一系列错误做检查。

  不要使用条件语句

  有时,测试环境具有不可预见性。在这样的案例中,在测试中使用条件语句很诱人,例如“if this element exists, click it, if it does not exist, do something else.”这种方法会存在很多问题。一个问题就是类似使用索引代替具体定位器导致的问题:如果应用测试改变,自动化测试将会以完全不可预期和位置路径传 下去,导致错误失败(或者更糟糕的是错误成功),让维护更加困难。另一个问题是条件语句声明的一个分支(错误地)出现在一起,测试在引入时从未显示一个缺 陷。

  使用Javascript创建可重用随机数据

  最后,下面是使用Selenium和Fitnesse,进行具体的测试数据最佳实践的例子。在这个例子中,测试需要输入唯一的Social Security Number,然后检查SSN是否实际上输入到应用中:

以下是引用片段:
| type; | ssn | javascript{RN =Math.floor(Math.random()*9999999);while (String(RN).length < 8) { RN=RN+'0';}} |
| $SSN= | getValue | ssn |
| click | link=Save |
| type; | search | $SSN |
| GET SEARCH RESULTS CONTAINING THE SSN |

  Selenium会内嵌评估Javascript。这种测试的首行键入域ID值为“ssn”,在运行中生成随机的9个数字,通过评估 Javascript作为type()动作的证据。第二行使用Fitnesse功能来存储来自“ssn”域的9个数字,称之为“$SSN”。然后测试输入 九个相同数字到这个域,其ID值为“search”。在测试本身解决数据需求是唯一的时候,这是一种高雅有用的方法,在任何合理的测试工具或者框架中同样 的方法应该有效。

  优良测试的优良设计

  这些只是一些例子,协助确保自动化测试强力并可维护。很多其他的例子也存在,每一种自动化测试工具或者框架都有优良的设计实践单独针对工具。

posted @ 2012-05-21 10:08 顺其自然EVO 阅读(179) | 评论 (0)编辑 收藏

软件测试的13项原则

  软件测试过 程中,我们应注意和遵循一系列的具体原则,在ISTQB 软件测试基础认证大纲上,列出了7 项原则,但其中最后一项原则“不存在缺陷(就是有用系统)”的谬论不能算是一项合格的原则,所以可以认可的原则是6 项。除此之外,在这里还列出作者认为比较重要的7 项原则,合起来共13 项原则。

  1、ISTQB 的6 项原则

  1)原则1——测试显示缺陷的存在,但不能证明系统不存在缺陷。测试可以减少软件中存在未被发现缺陷的可能性,但即使测试没有发现任何缺陷,也不能证明软件或系统是完全正确的。

  2)原则2——穷尽测试是不可能的。由于有太多的输入组合、有太多的路径,而且时间是有限的,无法做到完全的测试(100%测试覆盖率)。通过运用风险分析和不同系统功能的测试优先级,来确定测试的关注点,从而替代穷尽测试。

  3)原则3——测试尽早介入。软件项目一启动,软件测试就应开始,也就是从项目启动的第一天开始,测试人员就应参与项目的各种活动和开展对应的测试活动。测试工作进行得越早,软件开发的劣质成本就越低,并能更好地保证软件质量。例如,在代码完成之前,可以进行各种静态测试,主导或积极参与需求文档、产品规格说明书等的评审,将问题消灭在萌芽阶段。

  4)原则4——缺陷集群性。版 本发布前进行测试所发现的大部分缺陷和软件运行失效是由于少数软件模块引起的。一段程序中发现的错误数越多,意味着这段程序的质量越不好。错误集中发生的 现象,可能和程序员的编程水平、经验和习惯有很大的关系,也可能是程序员在写代码时情绪不够好或不在状态等。如果在同样的测试效率和测试能力的条件下,缺 陷发现得越多,漏掉的缺陷就越多。这也就是著名的Myers 反直觉原则:在测试中发现缺陷多的地方,会有更多的缺陷没被发现。假定测试能力不变,通过测试会发现产品中90%的缺陷。如果在模块A 发现了180 个缺陷,在模块B 发现了45 个缺陷,意味着模块A 还有20 个缺陷没被发现,而模块B 只有5个缺陷未被发现。所以,对发现错误较多的程序段,应进行更深入的测试。

  5)原则5——杀虫剂悖论。采用同样的测试用例多次重复进行测试,最后将不再能发现新的缺陷。为了克服这种“杀虫剂悖论”,测试用例需要进行定期评审和修改,同时需要不断地增加新的不同的测试用例来测试软件或系统的不同部分,从而发现潜在的更多的缺陷。

  6)原则6——测试活动依赖于测试背景。针对不同的测试背景,进行的测试活动也是不同的。比如,对要求安全放在第一位的软件进行测试,与对一般的电子商务软件的测试是不一样的。

  2、其他重要的7 项原则

  1)持续地测试、持续地反馈。软件测试贯穿着整个软件开发生命周期,随时发现需求、设计或代码中问题,及时将发现的问题反馈给用户、产品设计人员、开发人员等,主动、积极地交流,持续提高软件产品质量,这在敏捷测试中更为重要。

  2)80/20 原则。在 有限的时间和资源下进行测试,找出软件中所有的错误和缺陷是不可能的,因此测试总是存在风险的。测试的一个重要目标是尽量减少风险,抓住重点进行更多的测 试。根据80/20 原则,即帕累托法则(Pareto Principle),用户80%的时间在使用软件产品中20%的功能。“重点测试”就是测试这20%的功能,而其他80%的功能属于优先级低的测试范 围,占测试20%的资源。

  3)建立清晰的阶段性目标。饭要一口一口地吃,不能一口就吃成胖子。测试的目标也要逐步达到,不可能在某一瞬间就达到。根据软件开发生命周期的不同阶段性任务,我们要决定相应的测试目标和任务。如在需求分析阶段,要参与需求评审以全面理解用户需求、发现需求的问题;在功能测试执行阶段,测试人员不仅要对新功能进行测试,而且要有效地完成回归测试。

  4)测试独立性。测试在一定程度上带有“挑剔性”,心理状态是测试自己程序的障碍。同时,对于需求规格说明的错误理解也很难在程序员本人进行测试时被发现。程序员应避免测试自己的程序,为达到最佳的效果,应由独立的测试小组、第三方来完成测试。

  5)确保可测试性。事先定义好产品的质量特性指标,测试时才能有据可依。有了具体的指标要求,才能依据测试的结果对产品的质量进行客观的分析和评估,才能使软件产品具有良好的可测试性。例如,进行性能测试前,产品规格说明书就已经清楚定义了各项性能指标。同样,测试用例应确定预期输出结果,如果无法确定所期望的测试结果,则无法进行正确与否的校验。

  6)计划是一个过程。虽 然通过文档来描述软件测试计划,并最后归档,但计划是一个过程,是指导各项软件测试活动的持续过程。在项目开始时很难将所有的测试点、测试风险等都了解清 楚,随着时间推移,通过需求和设计的评审和探索式测试,对产品的理解越来越深,对测试的需求和风险越来越了解,可以进一步细化、不断丰富测试计划。其次, 计划赶不上变化,软件产品的需求常会发生变化,测试计划不得不因此做出调整。所以,测试计划是适应实际测试状态不断变化而进行调整的一个过程。

  7)一切从用户角度出发。在 所有测试活动的过程中,测试人员都应该从客户的需求出发,想用户所想。正如我们所知,软件测试的目标就是验证产品开发的一致性和确认产品是否满足客户的需 求,与之对应的任何产品质量特性都应追溯到用户需求。测试人员要始终站在用户的角度去思考、分析产品特性,多问问类似下面这样的问题:

  这个新功能对客户的价值是什么?

  客户会如何使用这个新功能?

  客户在使用这个功能时,会进行什么样的操作?

  按目前设计,用户觉得方便、舒服吗?

  如果发现缺陷,去判断软件缺陷对用户的影响程度,系统中最严重的错误是那些导致程序无法满足用户需求的缺陷。软件测试,就是揭示软件中所存在的逻辑错误、低性能、不一致性等各种影响客户满意度的问题,一旦修正这些错误就能更好地满足用户需求和期望。

相关链接:

从1个中心到5个要素——金字塔与软件测试

软件测试中的8组关系

posted @ 2012-05-21 09:55 顺其自然EVO 阅读(242) | 评论 (0)编辑 收藏

进入软件测试行业的六年感悟

 来淘宝测试部三年了,也就是意味着我进入测试行业也快到六年的时间了。或多或少也有自己的一些感悟,而且不同阶段的感悟会一样。自己在淘宝的每一年的纪念日的时候都会写篇个人总结来慰问下自己。

  关于这次在淘三年的内容,我自己也是思索了好久,不知道要写什么,测试感悟的、测试技术的、测试方法的各个方面都想写,又都不想写。

  都想写的理由就是本身测试行业就是个比较工程和系统性的行业,自然有自己的一些领域知识,说太少了,怕有些人真的以为测试就是点点鼠标而已。

  都不想写的理由就是怕说太多了,就复杂了,就更让人摸不着头脑了;而且很多观点和事情不是说说就能明白的,只有自己亲身经历了才有深刻的体会。也所谓 如人饮水,冷暖自知。

  最后还是决定好好回顾下这几年的测试想法,因为这几年测试行业发生了很大的变化,不仅仅是敏捷测试、新测试技术、开发自测等等,都会影响我自己个人在测试行业的发展和能力的提升。真的怕自己走过弯路,所以需要不停的反省自己,这个能力是不是必须的、这个技术是不是应该需要了解的等等。

  介于北京的崔启亮的建议,还是确定了自己的部分写作思路,也大致分成几个部分吧。

  遇到的困难以及解决办法

  第一个三年:

  在06年毕业后的测试三年中,遇到了一些基础困难,幸好自己在观察和学习的同时,很快就能解决这些问题。 由于之前写过一个blog介绍了部分问题,大家可以参考下:http://www.51testing.com/html/70/n-807570.html

  但是这边我还想发表下自己的观点,是针对于黑盒测试方法来说的。 记得几天前讨论是否需要QA的时候,段念 写个一篇blog来说明 一个正常的工程师 都能在一个下午学会和理解大部分的黑盒测试方法。 对此观点,我是不敢苟同的,这就讨论到这些黑盒测试方法的深度的问题了。

   (0)学会和理解测试方法的使用步骤是很简单的,但是真正的在项目需求中应用起来可不是一朝一夕的。这就好比给你一张扑克一样,高手就能拿它杀人,一般 的人能做到什么程度呢。 这个也很像有些人能发现你不能发现的bug一样。至于原因有很多,具体看在淘两年的blog。

  (1)谈谈我自己的感想吧,我自己在工作前 两年也是认为这个黑盒测试方法一下午就可以学会的,找几个例子试着使用下,感觉自己掌握到这些黑盒测试方法,但是后来我看过很多这些测试方法的背景以及应 用的注意点后。我发现自己真的是了解了一些皮毛,没有深入的了解。对于个项目需求,如何快速且完整的应用这些黑盒测试方法设计出不多不少的测试用例,这个需要的经验的积累,也就是你测试价值的核心体现。

   (2)去年在成都MPD时,很多学员说自己都说自己是工作2-3年的人,已经遇到瓶颈了,感觉测试很单调和无味。我给的建议其实很简单,那就是真正的理 解和掌握所有的黑盒测试方法。怎么来验证呢,我自己就是这样:给你一个白板,你能把所有测试方法的5W2H(What、Why、When、Where、 Who、How、How Much)都能非常清晰明了的演讲出来,记住是不需要参考ppt或其他资料的情况下。

  就像火影里面的鸣人一样,他只会螺旋丸这个核心的攻击忍术,但是在扩展其他忍术之前,他会把这个忍术的深度发挥到机制,从而研究出威力更强的超大螺旋丸、超大玉螺旋丸、风遁螺旋丸等等。

  在淘宝的这几年也越到了很多的困惑,而且随着年龄的成长,考虑的问题就会越来越犹豫,需要权衡利益的去提升自己和学习。主要考虑的就是测试的深 度和广度问题。自己毕竟在测试行业待了那么长时间了,周围其他测试同仁的发展、国外测试行业的发展、自身利益和环境的影响等等,这些都会影响自己对某些测 试问题存在个人极端的想法。

  个人认为了解一个人测试的水平,需要考虑其测试行业中的深度和广度的知识。

  测试的广度:主要就是测试相关类型的了解。具体包括如下:需求分析、测试流程、测试管理、开发流程、开发技术、测试模型、基础测试方法和测试技 术、功能测试、性能测试、自动化测试(页面自动化、API)、安全测试、可靠性测试、易用性测试、稳定性测试,探索式测试(ET)、基于风险的测试 (RBT)、兼容性测试等等。

  测试的深度:也就是对广度说到的某一项你了解到的深度。当然这个深度,每个人都有自己的定位和看法,关键还是看自己是如何来对待的,这边我说下自己对自动化测试的深度的看法吧。

  基础:了解简单的测试脚本/代码的编写,了解不完整的测试框架架构。

  进阶一:快速编写测试脚本/代码,解决部分代码编写的问题,了解完整的测试框架架构。

  进阶二:理解和了解自动化测试设计,自动化测试在项目中的融入和实施策略问题,了解其他类似的测试工具,并能做出正确的判断。

  进阶三:快速编写合理的测试脚本/代码(体现在测试设计和测试数据设计上),指导他人编写可维护性的测试脚本,深入了解测试框架的实现细节和开发技术。

  高级:整体上来解决自动化测试效率和价值的问题,找到测试框架的问题或困难,并能解决它,或提出有效的建议,深入了解其他类似测试框架或工具,并了解其功能技术细节。提升测试框架的应用性和实效性和效率。

  就我个人而言,我一直也在扩大自己的测试广度,也在提升自己的测试深度。在淘宝的这几年,淘宝测试部的发展非常的快速,自己也从中学到了很多,我也庆幸自己在来淘宝之前就把某些的深度问题给解决了,从而可以提高自己其他的广度。

  一开始来淘宝,就选择 自动化测试这个广度,并在页面自动化测试和API接口测试方向 提升自己的深度(这是个长期的过程)。另外也选择了兼容性测试这个 广度,不过这个进展笔记缓慢。接着根据自己的方向和优势,选择了 探索式测试 这个广度,从而在这个领域学习到了更多的知识,从而影响其他广度的选择。接着不停的提升自己在需求分析、测试流程、测试模型、性能测试方面的深度,也会接 触安全测试这个广度等。 最近选择了 前端测试和无线测试领域,这也是扩大自己的广度,不断的学习和了解该领域的测试特点和工具。

  给大家的建议是根据公司测试技术的发展策略,有针对性的选择某几个测试广度,然后在其上提升自己的深度。你的测试能力就是 你的广度 * 你的深度。

  不管我去扩大其他的测试广度,有几个测试领域我是必须要求自己,也强烈建议其他测试同仁需要达到的较高深度的。也就是我自己一直深信的测试理 念,我是一个测试工程师,你可以说我level不高,考虑不到高层想要的东西。但是我是会追求自己所相信的,那就是测试设计能力:也就是不同测试类型的测 试方法的应用能力。不仅仅是有这个能力,而是 更快、更准、更狠的 测试设计。

  个人测试感悟

  0、时刻牢记自己的状态和目标

  你需要确定你目前所在的广度有哪些,和深度是怎么样的。根据自己的特点和测试信念和公司情况,选择深度和广度,然后指定计划和目标,执行下去。这个可以整体上解决 你的瓶颈问题。

  1、开发和测试是亦敌亦友的关系

  以前一个测试同仁说过,没有和开发吵过架的测试不是一个好测试。我虽然不是很认可,但是他还是有一定的道理,本身开发和测试的立场和思维逻辑就 不一样,短时间较难改变,那这里就需要表现测试的价值。但是测试需要开发的帮助才能更好的理解设计和代码,才能更好的设计用例,才能更好的保证质量,才能 更好的提升自己的技能。这是个平衡,测试和开发走的太近不好,走的太远也不好。不要说开发和测试共享质量、共同承担责任啥的,目前国内是这样,以后可能会 不一样。

  2、测试需求分析时多问为什么

  需求评审和需求分析,对应大多数测试同仁来说是个不易提高的地方,也是很难传承经验的地方,这里还是需要去学习一些需求分析方法,总体上就是建议你凡是多问问什么、为啥会这样、还有没有更好的。

  3、验证bug时多看看code change

  记得在华为和微软Onsite测试的时候,就讨论过了很多次,我还是很喜欢在验证bug时看code change。看不懂的地方直接问开发,不断的提升自己在代码方面的经验和敏感度,那段时间真的很快乐。后来我还会参与bug fix,这些都是多看code change的后期提升,让自己更加有价值,不仅仅能发现bug,还能fix bug。

  4、持续优化你的测试设计

  不管是项目还是产品,你只要是负责人,一定要保证该产品或项目的测试设计是最新状态,并且在不同的信息输入期间都有新版本的测试设计产出,特别是测试执行后期,那些未通过测试用例发现bug的用例,一定要保证测试设计的时效性和完整性和最新性。

  5、没事多看看其他人提的bug

  线下bug场景和线上故障的场景都是非常好的案例,不是单纯的由某个黑盒测试方法能发现的,所以我们需要关注这些场景案例,总结起来,并转换为自己所用。这个经验积累不是那么容易看出来,而且经验也不是那么容易show出来,但是不要低估它,关键时刻就靠他了。

 6、 控制自动化和它的价值

  这里让大家理解自动化测试的价值和目的是没有任何问题,关键是控制它。根据自己产品的特点要找到一个平衡点,不要盲目的自动化。一定要控制手工测试用例、自动化测试用例的比例(UI级别、API级别的)。不要让它成为你的累赘,不要让你每次的脚本排查成为惯例现象。

  7、坚持自己选择的测试信念

  之前很早就提到过test school,建议每个人根据自己的个人信仰和特点来选择某个test school。因为一旦你选择是某个school的人物,你就会学习这个school的很多测试理念和测试想法,坚信它们并在自己的团队中应用起来。我个 人就是属于context-driven school。

  8、用户体验和代码完美性是王道

  很多人都应该说过测试人员测试就是应该站在用户角度去思考问题,多去考虑用户体验,的确这是个能帮助测试人员研究用户和提升易用性测试的一个途 径,另外可以多看看用户提供的反馈意见,完善自己的测试思路和需求分析思路。另外一点就是,我们很多bug开发都会说用户不会这么去做,几乎不可能的,所 以这个bug是invalid的。我们不仅仅是考虑用户应该做什么,我们还要考虑用户不应该做什么,有可能做什么,能够做什么。这些都是不一样的,多从代 码健壮性和容错性考虑代码的完美性。

  9、享受测试带来的一切

  不管你是毕业就从事测试工作,还是先干开发再转测试,不管你做测试的原因和动机是什么,个人建议你只要还在测试行业,试着去发现测试的美,不要 人云亦云,也不要固步自封。测试会让你开心、会让你单调、会让你愤怒、会让你痛苦、会让你疯狂、会让你无味。不要担心自己会不会失业或没有价值,不管怎 样,提升自己的广度和深度,逐步的享受测试带来的一切。

  测试的发展趋势和职业发展

  看这几年,国内的测试发展还是不错的。不过相比较国外来说,我还是比较悲观的,测试和开发一样还是至少落后于国外10年。我们这几年在不停的学 习和实践自动化测试、探索式测试、敏捷测试、基于模型的测试等等。很多国外走过的弯路,国内的我们还是在走,这似乎就是历史的轮转。

  个人认为测试的多元化发展还是一个主要的方向,也就是测试本身所提供的价值。测试手段的多样性和深度是必须要经过的环节。个人认为没有一到两种 测试方法、技术、手段能够解决被测产品的所有测试任务,我们需要不断的从不同角度去测试,去工具SUT,最近流行的分层测试、敏捷测试其实都是基于这个认 可。对于持续集成,个人认为只要自动化测试不消失,事实上他的价值还是不错的,也应该不会出现这个情况,那持续集成就还是基础的测试底层框架搭建。只是这 个持续集成的作用,我们现在还只用到了不到五成,接下来大家应该会在这方面有所突破,不过这方面还是有难度的,且不好考核。

  另外个就是提升开发自测,提升开发自测的质量对测试来说,实在是太重要了,但是不意味着测试可以掉以轻心。目前的开发自测状况是开发人员发现 20%的bug后,到时间了,开始提测。测试这边发现70%的bug,到时间了,该上线了。那么开发自测的目标就是开发人员发现60%的bug,fix 后,提测。测试这边发现35%的bug,fix后上线。表面上看总体上只多发现了5%的bug,而测试发现bug也减少了,但是从开发整体进度和项目进度 上来说,可是个非常大的进步,绝对的快速发布了,测试人力成本也会减少较多。

  由于答应了某位测试同仁,这里大致说下探索式测试的发展。个人是在09年底开始了解ET,目前淘宝在ET方面并没有大范围的展开,还是在某些测 试组、某些项目实施了不同形式的ET方式(部分项目是Freestyle形式,部分是ET辅助或bug bash的,主要是我这边来把控的,我个人时间有限,你懂的),至于结果,仁者见仁智者见智。大家也可以我个人其他的blog里面看到,至于工具使用的是 Freemind和Session tester。个人认为ET应该是未来测试发展的某个重要的方向,几乎可以和自动化测试齐步,特别在ROI上,自动化测试肯定会低于ET的,但是事物都有 两面性,ET必然有它不完整、不成熟的阶段,这个阶段需要大家一起去完善,一起去坚持自己的测试信念。

  关于职业发展,我是想走技术的,但是我自己也迷茫了很多次,做到什么样的程度呢,我的测试广度和深度到底要达到什么样的程度呢?公司需要我这个 测试广度吗?公司需要我这个测试广度下面的这个深度吗?是不是还需要再深入一点呢?我心里有很多这样的迷惘。比如开发技术就是一个矛盾点,这个深度真的不 是那么容易把握的,大家都知道了解开发知识、懂开发知识对做好测试是有益的,但是到底应该懂得啥程度呢,能带来多大的好处呢,啥情况下呢,开发自己都痛苦 的学来学去,测试真的一定要跟着后面吗?这个精力我是否应该多了解下兼容性测试呢?是不是应该多了解下RBT呢?我心里确实有很多的矛盾,很多次我都不知 道怎么过来的。不过我还是有自己的决定,我会尽量地去寻找自己的平衡,时刻的去review自己的状态,自己的这个测试广度达到了什么样的深度了,是不是 可以暂停下,去提升下其他测试广度的深度了。

  想走管理的,就是测试管理了,多考虑一线测试工程师的生活,他们是如何进行测试的,他们遇到什么问题,解决问题才是王道,解决他们的痛苦,提升 他们的效率,让大家快速的干完,可以去做些自己感兴趣的事情。另外就是多考虑下国外的测试新技术,有些不一定现在有用,以后呢,做些储备是必要的,就像军 队一样,平时没事做,关键还要用的,特别是特种部队了,各方面要求都很高,做这些储备更需要管理层的觉悟和想法了。

  想走技术的路线,就是尽最大的努力提升开发技术,另外就是多扩展自己的测试广度吧,争取在几个核心的测试广度上达到最深的深度,成为真正的测试专家。

  另外就是可以考虑走产品经理或其他路线的,比如SQA等。另外提一下,我也喜欢叫tester,不喜欢被叫QA。

  废话说的有点多,期望对大家有帮助,大家有任何不同的观点,欢迎提出。

posted @ 2012-05-21 09:54 顺其自然EVO 阅读(175) | 评论 (0)编辑 收藏

流媒体服务器的自动测试系统

 摘要:随着网络带宽的日益增加,流媒体应用的规模与范围也日益扩大,如何测试评 价流媒体服务器的功能性与性能就成为一个亟待解决的问题。本文设计与实现了一种流媒体服务器的自动测试系统。该系统通过输入的测试任务,利用测试服务器与 测试客户端的两层架构对流媒体服务器进行测试。该系统能够测试流媒体服务器对于RTSP协议的支持情况,接收和分析RTP包中帧数据的准确性,并且可以测 试流媒体服务器的性能。实验表明,该系统具有良好的可用性,可以实现高效灵活的测试需求。

  引言

  目前,随着移动增值业务的快速发展和第三代数字通信技术的实施,移动增值业务已经不再仅仅局限于短信、彩信、彩铃等窄带业务,用户对于在移动网络环境下点播和观看视频的需求越来越迫切。流媒体技术作为在互联网上实时传输音、视频的主要方式,成为一种在数据网络上传递多媒体视频数据的主流技术。如此,流媒体服务系统对于作为承载多媒体基本业务的流媒体服务器的评估也显得由为重要。

   当前的流媒体系统包含了多种网络接入方式,多种软件体系架构,及多种应用场景如电视会议系统、网络电视(IPTV)系统等。如何有效的测量各种系统所提 供的视频业务支撑能力就成为一个有待研究的问题,此类问题直接关系到各流媒体系统的优越性、实用性以及其重大革新意义的展现。并且当前的各个流媒体系统都 面临不断升级的需求,对于系统升级前后的兼容性、一致性也需要给出评价。

  由于音频、视频信号很难量化表示,目前对流媒体服务器的测试方法一般还是通过人工“察言观色”的方式完成,即测试人员通过STB (Set-Top-Box,机顶盒) 或Web页面与流媒体服务器建立连接,由测试人员发起测试,并对测试结果进行主观判断,分析系统的工作情况。但是由人工来测试工作量将非常大,并且人工测试也很难提取服务器的各种性能响应参数,验证检查力度不够,测试有效性低,不够全面,可维护和可扩展性差,测试效果不理想。

  这里列举几个常见的问题实例:

  1、手工测试过程中,大量的精力花在输入数据、执行测试用例,监听观看系统的音视频输出是否正常上,无法集中精力到关键问题,如提高测试的有效性,编写更多更好的测试用例等。

  2、由于采用人工判断的方式,所以无法对系统的性能指标进行量化分析。

  3、测试工作中许多操作是重复性的、非智力性的和非创造性的,并要求准确细致地完成,对于重复性手工测试很难保证每一次测试的效率与有效性。

  4、如果有大量(如几千)的测试用例,需要在短时间内(如1天)完成,手工测试几乎不可能做到

  为解决手工测试存在的问题,我们很自然的就想到了自动化测试。自动化测试的优点有很多,如快速、可靠、可重复性、可重用性等等,这些优点使得自动化测试在流媒体服务器测试过程中的地位不断提高,成为评价流媒体服务器的重要方法。

  本文研究的主题就是如何设计实现针对流媒体服务器的自动化测试系统,达到快速量化的判定流媒体系统的目的。该测试系统包括以下内容:

  ● 流媒体操作功能测试

  ● 流媒体数据有效性正确性验证;

  ● 流媒体系统性能测试

  流媒体技术概述及研究现状

   在流媒体(Streaming Media)技术出现之前,人们若想从网络上观看影片,必须先将影视文件下载到本地,然后才可进行播放。流媒体技术的出现客服了这个限制,它可以让用户不 需要将整个影音文件下载到用户机器,而是一边下载一边播放。所以流媒体是指在数据网络上按时间先后次序传输和播放的连续音、视频数据流。流媒体数据流具有 3个特点:连续性、实时性、时序性,即其数据流具有严格的前后时序关系。这种提供一边下载一边播放的服务系统称为流媒体服务系统。所以对于流媒体服务系统 的评价需要测试系统的数据延时,丢包率,比特率等指标;不仅如此为不断提升移动环境下流媒体业务的服务质量,需要通过不断提升服务器能力,提升终端能力, 增加传输和编码效率等办法来多方面地提升整个移动流媒体系统的性能。而提升系统性能的前提是对目前系统性能可以进行准确地测试和评价。

   目前,对流媒体服务器的测试多关注与流媒体服务器的性能测试。流媒体服务器性能测试指标主要有最大并发流数目、带宽波动、丢包率和平均响应时间等,其中最 大并发流数目是关注的最多的。最大并发流数目是指流媒体服务器能够支持的有效的、能够同时在线正常观看节目的最大用户数目。

  ……………………

  查看全文请点击下载:http://www.51testing.com/html/56/n-811856.html

  3.3 RTP流的测试

  流媒体服务器通过RTP协议封装音频和视频流。流媒体自动化测试系统通过捕获发送的RTP流并分析这些RTP流来判断流媒体服务器的性能。

   RTP流中封装的是流媒体服务所需的音频流和视频流,其中音视频都是通过特定的压缩技术对音视频流进行编码,目前视频流传输中最为重要的编解码标准有国 际电联的H.261、H.263,运动静止图像专家组的M-JPEG和国际标准化组织运动图像专家组的MPEG系列标准。这些标准都采用帧作为每一幅画面 的单位,为了支持多种协议的编码格式,本文论述的流媒体自动化测试系统不直接按照各种协议分析帧数据,而是对所有的协议采用统一的处理方法,这样增加了测 试系统的通用性。

  具体的方法,按照PTS建立每一帧的索引,对每一帧的数据应用MD5算法产生信息摘要;然后对接收的媒体流与预存的媒体流中相同帧进行一次MD5校验,从而得出结论当前帧是否完全。

  RTP流中另一个重要的指标为丢包率,由于流媒体服务器需要经过对流媒体数据的编码和加密后将数据压缩到RTP数据包中,所以测试系统无法从简单的统计RTP包的个数中得到丢包率。本文论述的流媒体自动化测试系统根据RTP流中每个RTP包必须顺序传送来计算丢包率。

   具体的方法,根据当前RTP包的序号判断下一个RTP包的序号,如果RTP包的序号不符合,则丢包加一;然后在根据新的RTP包的序号判断下一个RTP 包的序号。在数据流结束时,根据丢包数与总的RTP包数计算丢包率。这样丢包率数据同时也可以反映数据传输的乱序问题。

 流媒体自动化测试系统采用分级分析的策略,针对测试不同任务的需要,按照不同的分析级别给出不同详细程度的测试结果分析。具体的,流媒体自动化测 试系统采用如下表的三层分级策略级别,即活跃级,探测级,完整级。其中完整级提供最详细的RTP包分析结果,这一级对它所包含的全部帧数据进行信息分析, 可用于需要对流媒体服务器进行详细的功能测试;探测按照设定的抽样间隔对整个RTP流进行抽样检测,可用于性能测试及稳定性测试等需要消耗较高资源的测试 任务;活跃级检查RTP包的延时,丢包率,比特率等基本信息的分析,可用于压力测试等消耗很高资源的测试任务。完整级与探测级需要使用预先设定的流媒体 源,这样才能比较客户端接收到的RTP流中的帧数据是否完全正确。

级别

功能

粒度

活跃级

检查RTP包的延时,丢包率,比特率等基本信息

基本

探测级

需设定采样率;除统计活跃级的信息外,还需要按照采样率分析关键帧的数据。

较详细

完整级

除统计活跃级的信息外,还要对所有的帧进行分析。

详细

  3.4 性能测试

  性能测试主要是测试被测的流媒体服务器在预期用户量或者打用户量情况下系统的稳定性、可靠性和响应时间。本测试系统通过逐渐增加并发流的数目的方法观察各个性能参数的变化从而得出服务器的最大服务能力。

  目前本测试系统对于流媒体服务器的性能参数定义如下:

  1)最大并发流数目:流媒体服务器可以长时间支持的客户端数目。

  2)聚合输出带宽:流媒体服务器发送的总的带宽。

  3)请求响应时延:从用户发出RTSP点播开始到接收第一个RTP数据包之间的时间间隔。

  4)丢包率:客户端接收到的不连续的数据包的比率。

  测试系统通过多线程的客户端以及可以配置多个客户端这些灵活的方案实现对流媒体服务器的测试。

  4、流媒体自动化测试系统实现

  4.1 测试服务器的实现

  本文所述的测试服务器完成测试任务的管理与测试数据的统计分析工作。它由主线程、调度线程、配置线程、定时线程和输 出线程组成。主线程完成其他线程的创建工作,然后轮询是否有新的任务,如果监测到新的任务,交由配置线程读取新任务的各种配置参数。调度线程负责将新的测 试任务分配给某个测试客户端进行执行。定时线程会定时触发分析线程读取测试客户端送上来的测试结果进行分析。最后交由输出线程保存测试结果的磁盘文件中。

  分析线程需要根据测试任务的需要根据不同的测试级别进行分析,当进行完整级的测试分析时会消耗较大的CPU与内存资源,所以使用时间片强制使得分析线程让出系统资源使得测试服务器可以响应外部的输入,并且可以使用定时器使得分析线程在特定的时间继续分析测试数据。

  测试服务器的内部线程实现如下图所示

  ……………………

  查看全文请点击下载:http://www.51testing.com/html/56/n-811856.html

  4.3 自动化测试系统的部署

  本文所述的流媒体自动化测试系统,基于测试服务器与测试客户端的实现,能够支持分布式的部署。在具体部署测试时,可以根据测试的流媒体服务器的能力进行灵活的部署配置。

  当测试的流媒体服务器系统可以支持多台服务器同时提供流媒体服务,可以将测试服务器与测试客户端部署在不同的硬件服务器,并且可以部署多个测试 客户端用于测试不同的服务器。当测试的流媒体服务器为单服务器或者提供的并发负载能力较低时,可以将测试服务器与测试客户端部署在同一个硬件服务器。由于 单个测试客户端就可以支持与多个流媒体服务器建立流媒体服务会话连接,所以一般情况下,单台测试服务器就可以支持对含有多个流媒体服务器的流媒体服务系统 进行测试。

  ……

  查看全文请点击下载:http://www.51testing.com/html/56/n-811856.html

  本文收录于《51测试天地》电子杂志第二十五期。

  版权声明:本文出自51Testing软件测试网电子杂志——《51测试天地》第二十五期。51Testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任

posted @ 2012-05-18 10:45 顺其自然EVO 阅读(1282) | 评论 (0)编辑 收藏

5个常见的Rails开发误区

本文作者是一名Rails开发者,他总结了在Rails开发过程中的一些常见误区。文章内容如下:

  我使用Rails已经有一段时间了,在这期间我看了大量的Rails项目,下面的这五个常见的误区,我几乎在每一个Rails代码中都看到过。

  1、没有 schema 规范的迁移

  数据模型是应用程序的核心。没有schema的约束,你的数据会因为项目代码上的bugs而慢慢变得糟糕,直到你无法相信库中的任何字段。这里有一个 Concact Schema:

  1. create_table "contacts" do |t|  
  2.     t.integer  "user_id" 
  3.     t.string   "name" 
  4.     t.string   "phone" 
  5.     t.string   "email" 
  6. end

  上面哪些需要更改呢?通常一个Contact必须依附于User,并且会有一个name 属性,这可以使用数据库约束来确保。可以添加“:null => false”,这样即使验证代码存在bugs,我们依然可以确保模型一致性,因为如果违反了null约束,数据库并不会允许模型保存这些数据。

  1. create_table "contacts" do |t|  
  2.     t.integer  "user_id", :null => false 
  3.     t.string   "name", :null => false 
  4.     t.string   "phone" 
  5.     t.string   "email" 
  6. end

  TIPS:使用“:limit => N”规范你的string类型字段的大小。Strings 默认255个字符,而phone字段应该不需要这么长吧!

  2、面向对象编程

  大多数Rails开发人员并不写面向对象的代码。他们通常会在项目中写面向MVC的Ruby代码(把模型和控制器分开写在合适的位置)。通常是在lib目录下添加带有类方法的工具模块,仅此而已。但开发人员往往需要花费2-3年才能认识到“Rails就是Ruby。我完全可以创建一些简单的对象,并且不一定按照Rails建议的方式去封装它们。”

  TIPS:对你调用的第三方服务使用facade(外观模式)。通过在测试中提供mock facade,你就不用在你的测试集中真的去调用这些第三方服务了。

  3、在 helpers中连接HTML

  如果你正在创建helper,恭喜,至少说明你正在试图让你的视图层更整洁。但是开发人员经常不知道一些使用helpers创建标签的常见方式,这就导致了槽糕的字符串连接或者糟糕的插值形式。

  1. str = "<li class='vehicle_list'> " 
  2. str += link_to("#{vehicle.title.upcase} Sale", show_all_styles_path(vehicle.id, vehicle.url_title))  
  3. str += " </li>" 
  4. str.html_safe

  看吧,相当糟糕,而且容易导致XSS安全漏洞!让content_tag来拯救这些代码吧。

  1. content_tag :li, :class => 'vehicle_list' do 
  2.   link_to("#{vehicle.title.upcase} Sale", show_all_styles_path(vehicle.id, vehicle.url_title))  
  3. end

  TIPS:现在就开始在helper中使用blocks(代码块)吧。当产生内嵌的HTML时,嵌入的blocks更自然、更贴切。

  4、Giant Queries(大查询,比如载入整张表的查询)会把一切都加载到内存

  如果你需要修正数据,你只需要遍历并且修正它,对吗?

  1. User.has_purchased(true).each do |customer|  
  2.   customer.grant_role(:customer)  
  3. end

  假设你有个百万级别客户的电商网站,假设每个用户对象需要500字节,上面的代码会在运行的时候消耗500M内存。

  下面是更好的方式:

  1. User.has_purchased(true).find_each do |customer|  
  2.   customer.grant_role(:customer)  
  3. end

  find_each使用 find_in_batches 每次取出1000条记录,非常有效的降低了对内存的需求。

  TIPS:使用 update_all 或者原始 SQL 语句执行大的更新操作。学习SQL可能需要花费点时间,不过带来的好处是明显的:你会看到100x的性能改善。

  5、代码审查

   我猜你会使用GitHub,并且我进一步猜测你不会去pull requests(GitHub上的申请代码合并操作)。如果你需要花费一到两天去构建一个新特性,那么到一个分支上去做吧,然后发送一个 pull request。团队会审查你的代码,并且给出一些你没有考虑到的改进或者最新特性的建议。我保证这样会提高你的代码质量。我们在TheClymb项目中 90%的改动都是通过这种方式完成的,并且这是100%值得去做的一个经验。

  TIPS:不要没有经过任何测试就合并你的pull request。测试对保证应用的稳定性非常有价值,并且可以让你踏实地睡一个好觉。

posted @ 2012-05-18 10:42 顺其自然EVO 阅读(171) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 325 326 327 328 329 330 331 332 333 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜