qileilove

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

软件测试流程总结

 1、需求讨论,测试角度关注的问题:

  (1)系统架构、开发方法、人员安排、实现过程、开发周期

  (2)产品应用范围、面向的用户及用户人数、产品要实现的功能、使用的数据类型

  (3)开发环境:开发工具版本、数据库版本、操作系统版本

  (4)运行环境:硬件平台、操作系统、支撑环境(数据库版本、IE版本)、相关组件、服务

  (5)安全要求:产品权限、数据库权限、部署的服务器信息、防火墙信息、要放开的端口号

  (6)性能需求:系统支持的并发数量、响应时间、数据库中数据容量、占用的系统CPU、磁盘空间、传输速度、网络带宽等。

  2、需求分析

  (1)画出整体系统的(网络)拓扑图

  (2)根据不同角色身份进行分析,画出系统流程图:用户角度、安装人员角度、维护人员角度

  (3)从数据库角度进行深入分析:数据层、业务层、表现层

  (4)系统包含的功能模块/子系统列表,画出各模块的流程图,各模块间的关系及衔接接口

  (5)安全级别是否达标、对性能需求进行分析

  3、测试准备工作

  (1)环境准备:开发环境、测试环境、用户机干净环境虚拟机、复杂环境虚拟机(IE不同版本、操作系统不同版本、防火墙不同、数据库版本不同)

  (2)数据准备:正式数据、不自洽数据

  (3)书写测试功能点

  (4)根据需求分析结果和测试功能点,制定测试策略、测试方法、测试周期、人员安排。

  4、测试开始

  (1)测试用例书写:根据八大测试用例方法书写:等价类划分方法、边界值分析方法、错误推测方法、因果图方法、判定表驱动分析方法、正交实验设计方法、功能图分析方法、场景设计方法

  (2)编写测试使用的sql语句、编写自动化测试脚本

  (3)功能测试:可借助测试工具,例如:Xenu、Cookie Editor、QTP

  (4)白盒测试:代码走读、静态结构分析法、逻辑覆盖法、基本路径测试法,工具:NUnit。详读web.config等配置文件,辅助理解程序整体结构,检查之前的测试点是否完善。

  (5)数据库测试:数据备份与恢复测试、故障转移和恢复测试、数据迁移数据操作测试(包括不同版本数据库间的迁移、跨数据库类型迁移,例如SQL迁移到Oracle)。

  (6)数据库压力测试:

  ● 通过数据库连接数的变化,测试是否有连接泄露的现象

  ● 是否有数据表锁死等现象

  (7)性能测试:连接速度测试、负载测试、压力测试,工具loadrunner

  (8)安全性测试:建立整体的威胁模型,测试溢出漏洞、信息泄漏、错误处理、SQL 注入、身份验证和授权错误、XSS攻击。可用工具:

  ● Paros proxy (http://www.parosproxy.org),用于截获HTTP 通信数据

  ● Fiddler (http://www.fiddlertool.com/fiddler),用于截获HTTP 通信数据

  ● TamperIE (http://www.bayden.com/dl/TamperIESetup.exe),用于修改GET 和POST

  (9)兼容性测试:利用之前准备的不同环境,测试产品兼容性及支持环境

  (10)安装测试:不同环境、安装过程不同选项、不同路径

  (11)参数测试:书写可配置参数的意义及语法说明文档,并进行测试

  5、测试结束:

  (1)测试总结:bug情况、系统稳定性、使用方便度、遗留待解决改进的问题

  (2)功能点测试报告

  (3)性能测试报告

  (4)环境要求文档:操作系统的版本(包括企业版、标准版等)、位数;数据库的版本(包括企业版、标准版等)、位数;.Framework版本;不支持的环境

  (5)使用手册:系统常见故障分析及排除说明、错误信息编码说明

  (6)部署文档:包含FAQ的内容以及截图

  (7)维护文档:系统目录结构说明、系统启动进程说明、数据备份说明

  (8)外出安装前的检查文档

  6、外出安装注意事项:

  (1)设计若安装出现问题的紧急预案

  (2)安装前检查环境(待写一个环境检查的小工具)

  (3)根据事先写的检查文档一项项打勾、安装后对每一模块进行测试验证

  (4)安装结束后,将IIS、WEB.CONFING、注册表信息、日志信息、防火墙信息、安装路径、安装程序等拷贝回来,撰写文档。

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

5个须警惕的数据库设计错误

  每个人都会犯错误,但作为数据库管理员,我们应该尽量避免失误,从而为公司降低成本,并确保数据质量。下面的五个数据库设计失误必须引起我们的警惕。

  1、选择恰当的数据类型,避免数据库的过度膨胀

  请留意数据类型的选择。例如,如果你很清楚某列的数值范围在0-100,000之间,那么就不必使用BIGINT数据类型,因为INT类型就已经足够了。

  选择前者意味着,你每插入一条数据就比后者浪费了4个字节。这听起来也许微不足道,但随着数据量的增长,问题将会凸显出来。

  2、遵循ISO标准,保证异构数据库系统之间的互通性

   大型企业的IT基础架构非常复杂,可能需要不同数据库系统之间的数据交换。我们以TIMESTAMP数据类型为例,在Transact-SQL中定义的 TIMESTAMP数据类型与ISO标准有所不同。其它的数据库系统与ISO标准也有所差别。所以,我们要尽可能地遵循ISO标准,以保证异构数据库系统 之间的互通性。

  3、以恰当的机制实现序列化

  保证在数据库中插入记录的序列化非常 有必要,许多数据库设计者通过各种机制来确保序列化的应用。一些数据库设计者喜欢在数据库设计中引入GUID,但引入GUID并不是一个好的选择,这是因 为GUID默认并非序列化的,使用GUID列作为主键和/或索引甚至会造成性能问题。

  4、创建索引时要将外键考虑在内

  如果你的数据库中已定义外键,那么在建立索引的时候就要多加留神了,要把这种情况纳入数据库设计的整体之中去。

  5、不要忽略与业务需求相关的候选键

  数据库设计者不应只将注意力放在代理键上,而忘却业务需求。显然,这对数据质量非常不利。如果你没有在与业务相关的候选键上建立任何约束或索引,可能会出现重复值。

  请远离上面的5个数据库设计失误吧,这会帮助你为公司节省成本,并提高数据质量。

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

软件测试中的8组关系

 金字塔的5个点之间相连的8条边代表着测试要素之间的关系,这些要素之间的关系处理是否妥当,将显著影响测试工作的质量和效率。

  这8组关系为如下所示。

  1)质量与人员的关系。

  2)质量与流程的关系。

  3)质量与技术的关系。

  4)质量与资源的关系。

  5)人员与技术的关系。

  6)人员与流程的关系。

  7)技术与资源的关系。

  8)流程与资源的关系。

  下面就简单说明一下这些关系的内涵,以及如何处理它们之间的关系(参见图1-1)。

图1-1

  1、质量与人员的关系

  质量需要组织中的全员负责,每个人的行为都能对软件产品质量有直接的影响,每个人都应树立积极的态度,做正确的事,对软件产品质量的提高贡献自己的力量。

  2、质量与流程的关系

  借助流程避免或减少人为的错误,借助流程可以督促人们在正确的时间做正确的事,甚至基于已有的良好流程迫使流程自身的优化,持续改进。所以,基于流程的质量改进是相对可靠、稳定的,基于流程的质量改进是可持续发展的。

 3、质量与技术的关系

  有些流程的实施需要技术的支撑,例如,将流程融入软件项目管理系统,就可以看做:借助技术,流程被固化在某个信息系统中,这样流程的执行更加可 靠。例如,要求所有的代码在检入(check in)前都需要进行代码评审,如果没有评审,就不能检入。如果流程仅写在纸上,其执行比较困难,有的人在代码没有评审的情况下可以偷偷检入代码。但是,如 果开发一个辅助代码评审的系统(如Review Board、JCR 等),并将这个系统和源代码配置系统(如CVS、SubVersion 等)集成起来,代码没评审就根本无法检入代码。这就是从技术上解决流程的执行问题,使流程执行不流于形式,从这个角度保证质量。除此之外,基于技术能力, 可以开发代码安全性检查工具、代码规范符合性扫描工具等,更彻底地确保代码的质量。从这个意义上看,技术完全可以服务于质量,并能更好地保证质量,或使质 量保证工作能事半功倍。

  4、质量与资源的关系

  质量保证是需要成本的,从这个角度看,质量的提高需要更多的资源。可以说,质量和资源是成正比的,资源不足会降低质量,而资源充足可以改进质 量。质量与资源的关系是被动的,最终取决于人、流程和技术。例如,服务器资源不够时,可以通过虚拟技术来增加逻辑服务器,满足测试的需要。

  5、人员与技术的关系

  软件测试人员隶属于研发团队,在工程师范畴内,因是技术人员,故以技术为本。软件测试人员作为用户代表,虽然更多的是站在用户的角度去看问题, 去测试产品,但还是要靠技术武装自己。因为,要完成测试任务,无论是测试环境设置,还是测试工具及其脚本开发、性能测试、可靠性测试等,都需要技术,包括 系统部署技术、网络技术、编程技术等。没有技术,很难和开发人员进行有效沟通,甚至因无法进行对话而得不到开发人员的尊重。

  有了技术,便能理解系统架构设计和系统实现,就可以更有针对性地进行测试,做到事半功倍。另外,也只有掌握编程技术,才能参加代码评审,接受敏捷方法的挑战。因此,作为工程师,技术能力可体现自身价值,是未来发展的基础。

  6、人员与流程的关系

  树挪死、人挪活,流程是死的,人是活的。人发现流程有问题,就需要做出调整,对流程进行修改。流程是人开发出来的,流程是为人服务的,而不是人 为流程服务。但同时,我们也要认识到,流程是多数人甚至是组织的全部人员达成一致意见的结果,是一种约定,在流程没有改变之前,人们要遵守流程。作为个 体,人要遵守流程,而作为人的整体,当流程不适应组织的变化时,就要服从组织、服从人的整体。

  7、技术与资源的关系

  技术与资源相辅相成,技术的发展需要资源的支撑,而技术发展以后,又可以反过来优化资源,减少资源的需求。如果技术和资源之间的关系建立在这样 和谐的良性循环基础上,对企业、对产品都有利;反过来,当技术和资源之间的关系始终处在激烈的矛盾之中,那它们不利于软件测试,不利于软件产品的开发,一 定会阻碍企业的发展。

  8、流程与资源的关系

  流程与资源的关系,和技术与资源的关系类似,也是相辅相成的关系。流程需要资源支持,资源为流程服务;同时,流程可以帮助我们更好地管理资源,充分地利用资源。

相关链接:

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


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

STAF测试框架的应用总结和分析

之STAF的应用总结和分析

  序言:我想主要从实际原理和应用上来说说测试框架,这些框架包括:关键字测试框架robot,基于各种语言的分布式STAF框架,集成测试框架Fit(husdon),以及elipse TPTPd性能测试框架等。这不是一套工具教程,而是一套应用的简单思想,个人难免有局限性,见谅。

  一、STAF介绍

  STAF全名叫Software Testing Automation Framework,即软件自动化测试框架,我觉得,STAF可以完全称得为一个测试框架,其基于软件开发中 “系统+组件”的思想,系统是一个架子,各个组件都可以插入到架子中成为其功能一部分。即,STAF是一个这么一个架子,提供了组件插入的规则,不管你的 组件是用什么语言写的,只要符合STAF的组件规范,就都能做为STAF的组件服务与其他的组件服务进行通信,即其提供了轻量级分发机制,负责将请求转发 给服务,从而调用这些服务的功能。

  二、staf原理

  staf的基本运作原理如下:

   1、启动STAF时,STAF做为系统的一个守护进程开启,然后同时加载其架构中的服务,这些服务可以是DLL文件、JAR文件。当你设计一个STAF 的外部服务的时候,即继承STAF提供你的接口,你只需要撰写一个类实现接口的方法即可。也可以这么理解,STAF就像一个操作系统,而这些服务就像这些操作系统上的应用功能软件,每个软件之间可以通过内存或者管道或者网络通道进行互相通信。所以,你若是设计一个测试框架时,可以参考STAF或者操作系统的这种理念,定义一套规范接口,以便于框架的灵活拓展和实现,而不是将一套框架写的死死的。

  2、STAF在加载服务的时候,为每个服务分配了一个句柄,即STAFHandle,这个句柄即作为服务的唯一标识。类比于操作系统会给每一个进程一个进程ID,你打开系统的任务管理器,能看到很多进程在运作,而你可以通过每个进程的ID对这些进程进行操作。

  3、STAF之间服务的交互则可以通过命令行的形式或者向服务的队列读写的形式进行。命令行可以看做为每个服务向外公开的消息接口。

  三、staf的应用

  staf的缺陷在于掌握困难,你需要很清楚它的机制以及其提供的一些服务的作用后,你才能真正的把他用好

  1、分布式多执行端应用:STAF采用P2P架构,即没有服务器和客户端之分,任何安装了STAF的机器之间可以互相通信,可以利用STAF的这种特性实现分布式执行的功能,例如:你有10个测试用例, 一般都会将10个测试仪用例在一台执行机器上串行运行,脚本少的话当然不会有什么问题,但是当脚本数量庞大到一定程度时,那么你需要一个分配机制,能够将 这些脚本分配到不同的空闲执行端运行,那么STAF可以帮助你实现这些机制,可以指定一台STAF机器为脚本任务分配端,然后指定一些STAF机器为执行 端,那么任务分配端收到任务,即一系列测试脚本后,它可以寻找到空闲执行端,应用STAF之间的通信,将这些测试脚本分配下去,在每一台机器上执行,然后 返回结果。这样,就可以大大节约一些测试时间了。当然,你也可以自己开发属于自己的网络分配系统,可以采用socket机制实现。

  2、STAF几个比较常用的的内外服务:

  文件系统服务:即FS服务,你可以采用FS服务进行不同机器之间或者一台机器上的文件之间的传递。例如:一些测试脚本和测试结果、日志等都可以采用这种方式传递。

  时间驱动服务:即调用此服务来按特定的时间间隔发送STAF命令,从而调用别的STAF功能服务,这其实相当于在自动化测试中,每隔多少时间,进行一次测试,这种概念跟持续集成的按时间间隔进行build有些相似。

  事件驱动服务:即由发生的事件来驱动进行通信,从而执行STAF命令,事件是通过队列形式发送,每个服务都有自己的一个队列,服务通过接收队列中的请求从而进行功能操作;这种概念跟持续集成的按事件驱动进行build有些相似。

  邮件服务:即发送邮件的服务,当测试完成或者失败时可以触发这个服务发送邮件。

  日志服务:即可以将一些测试结果或者日志信息按照表格序列的形式存在指定的STAF机器上,然后可以随时进行读取。这样可以当一台STAF机器的测试执行完毕后,将测试结果存在本机或者专门存放日志的STAF机器上,然后随时可以读取显示。

  压缩服务:调用STAF命令对文件进行压缩。

  名字空间服务:这个服务挺重要的,就是可以将一些数据存在STAF的指定内存中,然后独特的名字对应着独特的数据,这个与哈希表有些类似,你可以随时取得这些数据,这些数据在后台都是保存在本地XML文件中的。

  当然,这些服务只是一些基本服务,为了拓展你自己定制性的测试框架或者平台,你可以很好的利用这些基本功能。

  3、STAX,很多人都不清楚STAX和STAF的关系,其实从本质上而言,STAX和STAF本身没有太大关系,即STAX只是调用了STAF的内外部服务来构造了一个测试执行引擎。STAX整体机制是:你通过在按照STAX的XML格式定义测试工作流, 可在其中嵌套要执行的测试用例,然后由STAX导入,然后执行STAF命令,调用相关的执行服务执行测试,STAX能够监测服务的状态,并且读取指定机器 的日志服务并显示。不过我认为:STAX在执行操作上太过于繁琐,不用也罢。你可以自己设计控制界面,来下发脚本,并且可以读取日志服务或者可以获得 STAF的一个句柄,从而可以接收STAF发送过来的回应,将结果和执行状态显示在界面上。

  4、总而言之,STAF只是一个请求消息的分发机制,而那些基于STAF规则的服务才是实现整个测试的重点。你需要拓建多大的测试框架,那么你就得找到更多的需求,将其转化为服务,并且定义好他们之间的请求消息,让它们很好的协同合作。

  总结:

  1、一个好的测试工具或者框架,简单的使用并不难,如果真想在自动化测试领域得到进一步的发展,那么学习这些框架的思想,因为这些框架都是前人在实践基础上构建出来的,学习其思想,不仅能掌握自动化测试的理念,更能在软件思想上更进一步。

  2、想当时学习STAF框架时,实践很少,对于自动化测试框架一些认识都限于理论,所以学习了很长时间,但是在一段时间后,再去学习robot框架以及别的框架,都很快的从里到外认识,所以,学习很多工具不如先把一个学通。

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

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

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

谁修改了我的数据库密码--强制实施密码策略

 昨天在调试机房收费系统的时候,发现原来类的功能不能用了,可我没有改动过,经过再次调试发现数据库连接出现了问题。于是打开Sql sever ,连接。咦?怎么提示密码错误啊???明明昨天系统还是这个密码登陆的,怎么会突然失效了呢?

  谁修改了我的密码?

  于是开始在网上找:为什么sql server 密码突然失效? 查了半天没找到原因......

  于是在网上找:如何修改sql server 密码?发现大多是在已知旧密码基础上再去修改密码,可是我不知道。

  继续,终于找到解决方法:

  用windows验证方式登录,然后执行sql语句:alter login [sa]with password=N'NewPassword' 即可!这里是不需要知道旧密码的哦!

  问题是解决啦,可是不能不把元凶找到啊。原来是他......

  踏破铁鞋啊!原来是自己造成的!在sqlserver安装时这些选项没有注意,才造成今天的后果。

  在这里,虽然我勾选了强制实施密码策略,但是我设置的密码很简单依然可以,这是为什么?原来,这个功能要用到NetValidatePasswordPolicy() API这个函数。(该功能只有在安全要求较高的时候才用,我们是自己做练习,无需使用啦!)

  解决方法:在运行里输入 gpedit.msc 打开 本地策略编辑器依次 展开 计算机配置-Windows设置-安全设置-帐户策略-密码策略“密码必须符合复杂性要求”应该是禁用状态,改为已启用,之后再创建SQL Server用户即可。

  元凶已经找到,希望大家不要被“他”把密码“修改”掉啊!!!

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

构造器的执行顺序

 1、在没有静态块的情况下,子类的对象创建时,父类的无参构造器-->子类的构造器(产生对象的构造器,如果是无参则执行的是无参构造器,如果执行的是有参则执行的有参构造器)。现在的父类中只有两个构造器:
  1. Father.java  
  2.  Father {  
  3.     public Father(){  
  4.         System.out.println("我是父类的无参构造器");  
  5.     }  
  6.        
  7.     public Father(String username){  
  8.         System.out.println("我是父类有参构造器,传过来的参数是+"+username);  
  9.     }  
  10. public class SonDemo extends Father{  
  11.    
  12.     public SonDemo(){  
  13.         System.out.println("我是--子类--的无参构造器");  
  14.     }  
  15.     public SonDemo(String username){  
  16.         System.out.println("我是子类的有参构造器,参数是"+username);  
  17.     }  
  18.        
  19.     public void sys(){  
  20.         System.out.println("我是子类的sys方法");  
  21.     }  
  22.        
  23.     public static void main(String[] args) {  
  24.         //里面的内容在下面有说明 
  25.     }  
  26.        
  27.        
  28.        
  29. }

  ① 子类使用无参构造器创建对象:

  在SonDemo 的main方法中加入创建对象的代码:

  1. SonDemo son = new SonDemo();  
  2.        
  3. }

  我是父类的无参构造器

  我是--子类--的无参构造器

  ② 子类使用有参构造器创建对象:

  SonDemo的main方法中加入

SonDemo son = new SonDemo("than you ma");

  那么控制台打印的结果是:

  我是父类的无参构造器

  我是子类的有参构造器,参数是than you ma

  也就是说在子类调用无参构造器创建对象的时候,在执行它自己的有参构造器之前首先执行父类的无参构造器。

  ③ 在子类中创建父类的对象,使用无参

  1. SonDemo son = new SonDemo("than you ma");  
  2. Father ff = new Father();

  SonDemo的main方法中加入

  我是父类的无参构造器

  我是--子类--的无参构造器

  我是父类的无参构造器

  调用了父类的无参构造器,有参的创建对象调用的是有参构造器。

  总结:在创建子类对象的时候,首先会调用父类的构造器,让后在调用子类相应的构造器创建对象,在子类创建父类对象时,就是直接调用父类自己相应的构造器。

2、如果在子类和父类中存在静态块;执行顺序有会是怎么样的了?

  答,静态块会在构造器之前运行。不管是子类还是父类。创建一个对象的时候,会首先加载它的静态块。

  1. Father.java  
  2. public class Father {  
  3.    
  4.     //静态块  
  5.     static{  
  6.         System.out.println("father  static ");  
  7.     }  
  8.        
  9.     public Father(){  
  10.         System.out.println("我是父类的无参构造器");  
  11.     }  
  12.        
  13.     public Father(String username){  
  14.         System.out.println("我是父类有参构造器,传过来的参数是+"+username);  
  15.     }  
  16. }  
  17.    
  18. SonDemo.java  
  19. public class SonDemo extends Father{  
  20.     //静态块  
  21.     static{  
  22.         System.out.println("sonDemo static ");  
  23.     }  
  24.        
  25.     public SonDemo(){  
  26.         System.out.println("我是--子类--的无参构造器");  
  27.     }  
  28.     public SonDemo(String username){  
  29.         System.out.println("我是子类的有参构造器,参数是"+username);  
  30.     }  
  31.        
  32.     public void sys(){  
  33.         System.out.println("我是子类的sys方法");  
  34.     }  
  35.        
  36.     public static void main(String[] args) {  
  37.         SonDemo son = new SonDemo();  
  38.     }  
  39. }

  ① 程序的结果:

father static
sonDemo static
我是父类的无参构造器
我是--子类--的无参构造器

  因为在创建子类对象之前:会创建父类的一个对象,而静态块会在main之前被加载,所以两个类的静态块首先执行。

  然后执行构造器。

  ② 如果在子类中的main中只创建父类的对象结果是怎么样的呢?

  打印结果:

father static
sonDemo static
我是父类的无参构造器

  为什么子类的静态块会被加载了?是因为我们是在SonDemo中测试,如果在其他类中测试就不会打印。

  总结:我们说了这么多就是重要的一点。静态块会在构造器器之前执行。

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

JVM的内部体系结构浅析

jvm全称是Java Virtual Machine(java虚拟机)。它之所以被称之为是“虚拟”的,就是因为它仅仅是由一个规范来定义的抽象计算机。我们平时经常使用的Sun HotSpot虚拟机只是其中一个具体的实现(另外还有BEA JRockit、IBM J9等等虚拟机)。在实际的计算机上通过软件来实现一个虚拟计算机。与VMWare等类似软件不同,你是看不到jvm的,它存在于内存。

  当启动一个Java程序时,一个虚拟机实例也就诞生了。当该程序关闭退出,这个虚拟机实例也就随之消亡。如果在同一台计算机上同时运行三个Java程序,将得到三个Java虚拟机实例。每个Java程序都运行于它自己的Java虚拟机实例中。

  Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。根据《Java虚拟机规范(第2版)》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如下图1所示。

图1 Java虚拟机的内部体系结构

  下面先对图中各部分做个简单的说明:

   1、class文件:虚拟机并不关心Class的来源是什么语言,只要它符合Java class文件格式就可以在Java虚拟机中运行。使用Java编译器可以把Java代码编译为存储字节码的Class文件,使用JRuby等其他语言的 编译器一样可以把程序代码编译成Class文件。

  2、类装载器子系统:负责查找并装载Class 文件到内存,最终形成可以被虚拟机直接使用的Java类型。

   3、方法区:在类装载器加载class文件到内存的过程中,虚拟机会提取其中的类型信息,并将这些信息存储到方法区。方法区用于存储已被虚拟机加载的类 信息、常量、静态变量、即时编译器编译后的代码等数据。由于所有线程都共享方法区,因此它们对方法区数据的访问必须被设计为是线程安全的。

  4、堆:存储Java程序创建的类实例。所有线程共享,因此设计程序时也要考虑到多线程访问对象(堆数据)的同步问题。

   5、Java栈:Java栈是线程私有的。每当启动一个新线程时,Java虚拟机都会为它分配一个Java栈。Java栈以帧为单位保存线程的运行状 态。虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈或出栈。当线程调用java方法时,虚拟机压入一个新的栈帧到该线程的java栈中。当方 法返回时,这个栈帧被从java栈中弹出并抛弃。一个栈帧包含一个java方法的调用状态,它存储有局部变量表、操作栈、动态链接、方法出口等信息。

  6、程序计数器:一个运行中的Java程序,每当启动一个新线程时,都会为这个新线程创建一个自己的PC(程序计数器)寄存器。程序计数器的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时 就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。如果线程正 在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空 (Undefined)。

  7、本地方法栈:本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚 拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。任何本地方法接口都会使用某种本地方法 栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的 Java栈中压入新的帧,虚拟机只是简单地动态链接并直接调用指定的本地方法。如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法 栈就是C栈。

  8、执行引擎:负责执行字节码。方法的字节码是由Java虚拟机的指令序列构成的。每一条指令 包含一个单字节的操作码,后面跟随0个或多个操作数。执行引擎执行字节码时,首先取得一个操作码,如果操作码有操作数,取得它的操作数。它执行操作码和跟 随的操作数规定的动作,然后再取得下一个操作码。这个执行字节码的过程在线程完成前将一直持续。

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

三种东西永远不要放到数据库里

我已经在很多演讲里说过,改进你的系统的最好的方法是先避免做“蠢事”。我并不是说你或你开发的东西“蠢”,只是有些决定很容易被人们忽略掉其暗含 的牵连,认识不到这样做对系统维护尤其是系统升级带来多大的麻烦。作为一个顾问,像这样的事情我到处都能见到,我还从来没有见过做出这样的决定的人有过好 的结果的。

  图片,文件,二进制数据

  既然数据库支持BLOB类型的数据,把文件塞进BLOB字段里一定没有错了!?错,不是这样的!别的先不提,在很多数据库语言里,处理大字段都不是很容易。

  把文件存放在数据库里有很多问题:

  ● 对数据库的读/写的速度永远都赶不上文件系统处理的速度

  ● 数据库备份变的巨大,越来越耗时间

  ● 对文件的访问需要穿越你的应用层和数据库层

  这后两个是真正的杀手。把图片缩略图存到数据库里?很好,那你就不能使用nginx或其它类型的轻量级服务器来处理它们了。

  给自己行个方便吧,在数据库里只简单的存放一个磁盘上你的文件的相对路径,或者使用S3或CDN之类的服务。

  短生命期数据

   使用情况统计数据,测量数据,GPS定位数据,session数据,任何只是短时间内对你有用,或经常变化的数据。如果你发现自己正在使用定时任务从某 个表里删除有效期只有一小时,一天或数周的数据,那说明你没有找对正确的做事情的方法。使用redis, statsd/graphite, Riak,它们都是干这种事情更合适的工具。这建议也适用于对于收集那些短生命期的数据。

  当然,用挖土机在后花园里种土豆也是可行的,但相比起从储物间里拿出一把铲子,你预约一台挖土机、等它赶到你的园子里挖坑,这显然更慢。你要选择合适的工具来处理手头上的事。

  日志文件

  把日志数据存放到数据库里,表面上看起来似乎不错,而且“将来也许我需要对这些数据进行复杂的查询”,这样的话很得人心。这样做并不是一个特别差的做法,但如果你把日志数据和你的产品数据存放到一个数据库里就非常不好了。

  也许你的日志记录做的很保守,每次web请求只产生一条日志。对于整个网站的每个事件来说,这仍然会产生大量的数据库插入操作,争夺你用户需要的数据库资源。如果你的日志级别设置为verbose或debug,那等着看你的数据库着火吧。

  你应该使用一些比如Splunk Loggly或纯文本文件来存放你的日志数据。这样去查看它们也许会不方便,但这样的时候不多,甚至有时候你需要写出一些代码来分析出你想要的答案,但总的来说是值得的。

  可是稍等一下,你是那片不一样的雪花,你遇到的问题会如此的不同,所以,如果你把上面提到的三种东西中的某一种放到了数据库里也不会有问题。不,你错了,不,你不特殊。相信我。

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

软件测试中的心理学

软件测试是一项技术性工作,但同时也涉及经济学和人类心理学的一些重要因素。

  在理想情况下,我们会测试程序的所有可能执行情况,而在大多数情况下,这几乎是不可能的。即使一个看起来非常简单的程序,其可能的输入与输出组合可达到数百种甚至数千种,对所有的可能情况都设计测试用例是不切合实际的。对一个复杂的应用程序进行完全的测试,将耗费大量的时间和人力资源,这样在经济上是不可行的。

   另外,要成功地测试一个软件应用程序,测试人员也需要有正确的态度(也许用“愿景”(vision)这个词会更好一些)。在某些情况下,测试人员的态度 可能比实际的测试过程本身还要重要。因此,在深入探讨软件测试的本质之前(指技术层面),我们先探讨一下软件测试的心理学问题。

  测试执行得差,其中一个主要原因在于大多数的程序员一开始就把“测试”这个术语的定义搞错了。

  他们可能会认为:

  “软件测试就是证明软件不存在错误的过程。”

  “软件测试的目的在于证明软件能够正确完成其预定的功能。”

  “软件测试就是建立一个‘软件做了其应该做的’信心的过程。”

  这些定义都是本末倒置的。

  每当测试一个程序时,应当想到要为程序增加一些价值。通过测试来增加程序的价值,是指测试提高了程序的可靠性或质量。提高了程序的可靠性,是指找出并最终修改了程序的错误。

  因此,不要只是为了证明程序能够正确运行而去测试程序;相反,应该一开始就假设程序中隐藏着错误(这种假设对于几乎所有的程序都成立),然后测试程序,发现尽可能多的错误。

  那么,对于测试,更为合适的定义应该是:“测试是为发现错误而执行程序的过程”。

  虽然这看起来像是个微妙的文字游戏,但确实有重要的区别。理解软件测试的真正定义,会对成功地进行软件测试有很大的影响。

   人类行为总是倾向于具有高度目标性,确立一个正确的目标有着重要的心理学影响。如果我们的目的是证明程序中不存在错误,那就会在潜意识中倾向于实现这个 目标;也就是说,我们会倾向于选择可能较少导致程序失效的测试数据。另一方面,如果我们的目标在于证明程序中存在错误,我们设计的测试数据就有可能更多地 发现问题。与前一种方法相比,后一种方法会更多地增加程序的价值。

  这种对软件测试的定义,包含着无穷的内蕴,其中的很多都蕴涵在本书各处。举例来说,它暗示了软件测试是一个破坏性的过程,甚至是一个“施虐”的过程,这就说明为什么大多数人都觉得它困难。这种定义可能是违反我们愿望的;所幸的是,我们大多数人总是对生活充满建设性而不是破坏性的愿景。大多数人都本能地倾向于创造事物,而不是将事物破坏。这个定义还暗示了对于一个特定的程序,应该如何设计测试用例(测试数据)、哪些人应该而哪些人又不应该执行测试。

   为增进对软件测试正确定义的理解,另一条途径是分析一下对“成功的”和“不成功的”这两个词的使用。当项目经理在归纳测试用例的结果时,尤其会用到这两 个词。大多数的项目经理将没发现错误的测试用例称为一次“成功的测试”,而将发现了某个新错误的测试称为“不成功的测试”。

  这又是一次 本末倒置。“不成功的”表示事情不遂人意或令人失望。我们认为,如果在测试某段程序时发现了错误,而且这些错误是可以修复的,就将这次合理设计并得到有效 执行的测试称做是“成功的”。如果本次测试可以最终确定再无其他可查出的错误,同样也被称做是“成功的”。所谓“不成功的”测试,仅指未能适当地对程序进 行检查,在大多数情况下,未能找出错误的测试被认为是“不成功的”,这是因为认为软件中不包含错误的观点基本上是不切实际的。

  能发现新错误的测试用例不太可能被认为是“不成功的”,也就是说,能发现错误就证明它是值得设计的。“不成功的”测试用例,会看到程序输出正确的结果而没发现任何错误。

   我们可以类比一下病人看医生的情况,病人因为身体不舒服而去看医生。如果医生对病人进行了一些检查和化验,却没有诊断出任何病因,我们就不会认为这些检 查和化验是“成功的”,因为病人支付了昂贵的检查和化验费用,而病状却依然如故。病人会因此而质疑医生的诊断能力。但是,如果医生诊断出病人是胃溃疡,那 么这次检测就是“成功的”,医生可以开始进行相应的治疗。因此,医疗行业会使用“成功的”或“不成功的”来表达诊断结果。我们当然可以类推到软件测试中 来,当我们开始测试某个程序时,它就好似我们的病人。

  “软件测试就是证明软件不存在错误的过程”,这个定义会带来第二个问题。对于几乎所有的程序而言,甚至是非常小的程序,这个目标实际上也是无法达到的。

   另外,心理学研究表明,当人们开始一项工作时,如果已经知道它是不可行的或无法实现时,人的表现就会相当糟糕。举例来说,如果要求人们在15分钟之内完 成星期日《纽约时报》里的纵横填字游戏,那么我们会观察到10分钟之后的进展非常小,因为大多数人都会却步于这个现实,即这个任务似乎是不可能完成的。但 是如果要求在四个小时之内完成填字游戏,我们很可能有理由期望在最初10分钟之内的进展会比前一种情况下的大。将软件测试定义为发现程序错误的过程,使得 测试是个可以完成的任务,从而克服了这个心理障碍。

  诸如“软件测试就是证明‘软件做了其应该做的’的过程”此类的定义所带来的第三个问 题是,程序即使能够完成预定的功能,也仍然可能隐藏错误。也就是说,当程序没有实现预期功能时,错误是清晰地显现出来的;如果程序做了其不应该做的,这同 样是一个错误。如果我们将软件测试视作发现错误的过程,而不是将其视为证明“软件做了其应该做的”的过程,我们发现后一类错误的可能性会大很多。

   总结一下,软件测试更适宜被视为试图发现程序中错误(假设其存在)的破坏性的过程。一个成功的测试用例,通过诱发程序发生错误,可以在这个方向上促进软 件质量的改进。当然,最终我们还是要通过软件测试来建立某种程度的信心:软件做了其应该做的,未做其不应该做的。但是通过对错误的不断研究是实现这个目的 的最佳途径。

  有人可能会声称“本人的程序完美无缺”(不存在错误),针对这种情况建立起信心的最好办法就是尽量反驳他,即努力发现不完美之处,而不只是确认程序在某些输入情况下能够正确地工作。

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

浅谈如何维护软件测试用例

 软件产品的版本是随着软件的升级而不断变化的,而每一次版本的变化都会对测试用例集产生影响,所以测试用例集也需要不断地变更和维护,使之与产品的变化保持一致。以下原因可能导致测试用例变更:

  1)软件需求变更:软件需求变更可能导致软件功能的增加、删除、修改等变化,应遵循需求变更控制管理方法,同样变更的测试用例也需要执行变更管理流程。

  2)测试需求的遗漏和误解:由于测试需求分析不到位,可能导致测试需求遗漏或者误解,相应的测试用力也要进行变更。特别是对于软件隐性需求,在测试需求分析阶段容易遗漏,而在测试执行过程中被发现,这时需要补充测试用例。

  3)测试用例遗漏:在测试过程中,发现测试用例未覆盖全部需求,需要补充相应的测试用例。

  4)软件发布后,用户反馈的缺陷:表明测试不全面,存在尚未发现的缺陷,需要补充或者修改测试用例。

  对于提供软件服务的产品,其多个版本常常共存,而对应的测试用例也是共存的,而且测试用例需要专人定期维护,并遵循以下原则:

  1)及时删除过时的测试用例

  需求变更可能导致原有部分测试用例不再适合新的需求要求。例如,删除了某个功能,那么针对该功能的测试用例也不再需要。所以随着需求的每一次变更,都要删除那些不再使用的测试用例。

  2)及时删除冗余的测试用例

  在设计测试用例时,可能存在两个或者多个用例测试相同内容,降低回归测试效率,所以要定期整理测试用例集,及时删除冗余的测试用例。

  3)增加新的测试用例

  由于需求变更、用例遗漏或者版本发布后发现缺陷等原因,原有的测试用例集没有完全覆盖软件需求,需要增加新的测试用例。

  4)改进测试用例

  随着开发工作进行,测试用例不断增加,某些用例随着系统输入和当前状态的变化而变得不再适用,这些用例难以重用,影响回归测试的效率,需要进行改进,使之可重用可控制。

  总之,测试用例的维护是一个长期的过程,也是一个不断改进和完善的过程。

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

仅列出标题
共394页: First 上一页 326 327 328 329 330 331 332 333 334 下一页 Last 
<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜