qileilove

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

安装操作系统需要注意的事项

 1、工作软件:
  360, editplus,office,flashfxp,腾讯通, flash cs3  cs4 cs5 cs6 cc, flash builder 4 4.6 4.7, google浏览器, 搜狗输入法, 有道笔记本, svn, mysql-font,7-zip, QQ游戏, QQ,暴风影音,驱动人生
  adobe captivate, httpWatch, firefox 及插件, 91手机助手,迅雷, iis, Charles,UltraFileSearch, TortoiseSVN, svn命令行,有道笔记本, netlimit, SecureCRT 6.5, SecureFx 等等。
  网页游戏加速器 硕思闪客精灵 procexp64 PluginSwitcher IPAnalyse Everything
  Fiddler2、 Alcon、 Git、 JetBrains WebStorm、xTools、filezilla
  2、安装操作系统前需要备份的数据文件:
  a)iis网站配置导出(方法见这里)
  b)mysql-font配置导出
  c)ftp配置导出
  d)各浏览器收藏夹
  e)Beyond Compare 配置
  f)filezilla 配置
  g)editplus配置
  h)jsfl文件备份
  i)备份flash builder 项目工作空间
  j)导出QQ聊天消息、rtx聊天消息
  3、重装系统后需要处理的事情:
  a)安装开发环境:flash 3、4、5 及注册激活;flash builder 等等
  b)浏览器收藏夹
  c)editplus快捷键、注册激活
  d)设置搜狗输入法快捷键
  e)配置flash jsfl命令
  f)配置iis环境
  g)配置apach+php环境
  h)svn绑定
  i)对比文件夹目录配置
  j)远程桌面设置
  k)状态栏 常用程序、常用文件夹锁定
  l)修改 Flash Builder 内存参数配置
  m)Charles 过滤网址配置

posted @ 2013-11-28 11:06 顺其自然EVO 阅读(150) | 评论 (0)编辑 收藏

性能测试需求指标分析方法

六、设计测试模型
  1.业务模型的设计
  一个系统的业务模型是通过业务调研获得,业务模型的正确性反映在两个方面首先业务选择的正确性和业务比例的正确性。
  首先业务选择,一个系统可能支持几百个业务活动(也有叫做交易)但是只有少数的业务活动非常频繁,占总业务量的80%以上,那么在性能测试时只需关心这些占了大部分业务量的少量业务上。
  其次业务比例,如何精确统计业务的数量是关键问题,针对一个全新的系统可能要通过对使用系统的涉众进行调研,搞清楚他们群体数量,操作行为周期。在通过组合这些数据确定在常规业务日中各种业务占总业务的比率,同时也要考虑特殊交易日的情况,
  例如某一个商务活动或周期性的业务结算日等都是特殊交易日,在特殊交易日时某一类业务量可能突然增高很多那么在常规业务日的业务比例就不再合适,这点在业务模型上要进行区分。常规业务模型用来测试系统容量,特殊日业务模型要单独做压力负载测试场景。
  对于已上线运营的系统做业务模型的调研相对简单,不再需要去调研那么多的涉众,只需与运营维护部门进行协调,由他们协助测试需求调研人员提取系统中的历史数据就可以,那么在数据选择上要有些规则,要选取相对长时期的数据比如几个月,有条件的选取一年数据,取一年中每月平均业务量,选取年度高峰月业务数据,选取月度高峰日业务数据。
  2.测试模型
  业务模型是根据系统运营真实数据得来的,真实反映系统运营的业务状况。测试模型是以业务模型为基础根据测试需求不同对业务模型调整或不调整纳入到测试场景中直接使用。
  七、性能指标分析方法
  1.性能测试指标
  业务处理能力:每秒处理交易数量
  业务响应性:每种业务执行响应时间
  业务正确率:执行过程中通过事务占总业务比例
  系统资源指标:系统资源占用率
  2.业务处理能力
  业务处理能力是评测系统每秒所能处理的最大业务量,单位是Transaction/sec
  计算每秒处理业务量需要两个关键数据,一个是在指定时间内的指定业务量,二是指定的时间段。如何选择这两个数据是非常关键。通常业务调研阶段给的每天平均业务量或者某高峰日最大业务量。如何转换数据为每秒业务量,通常有算法:
  28规则,这是比较常用的计算方法
  例如:一个系统日交易高峰某100000笔交易,系统每天运营8个小时
  那么计算规则是 100000笔*80% / (8*3600*20%) =14笔/秒  一、概述
  本文目的是提供性能测试分析人员在测试需求分析阶段提供技术指导作用,指导其对采集的业务数据进行整理并转换为合理的项目性能需求指标,并提供测试执行人员在执行过程中以此为目标。
  二、名词解释
  ·  业务模型:描述业务系统在运营过程中核心交易配比(通常采集80%业务量的交易作为参考)清晰描述每个交易在系统业务量中的比例
  ·  测试模型:在测试执行时采用的交易配比模型。
  三、数据源分析
  ·  线上业务数据
  ·  运维数情况数据
  ·  未来业务增长数据
  四、 输出描述
  1.测试需求分析报告中要清晰描述本次测试要进行哪几种类型的测试。例如容量测试、稳定性测试、异常测试、速度测试、负载测试等
  2.测试需求分析报告中要清晰描述测试模型情况,测试模型和业务模型是有区别的,业务模型是从线上业务实际情况统计得来的,统计的数据是真实的线上数据,因此业务模型是线上交易分布的真实展现。测试模型是以业务模型为依据并结合测试需要对业务模型进行调整。例如需要调高某一类交易所占比例来实现测试目的。
  3.测试需求分析报告中要清晰描述测试指标,测试指标是用来评价一个系统是否满足性能需求的标准,测试指标包括系统响应性、系统可用性、系统资源占用率。
  五、测试类型选择
  1.常见性能测试类型


   2、被测试系统背景分类



 3、系统与测试类型MAP
六、设计测试模型
  1.业务模型的设计
  一个系统的业务模型是通过业务调研获得,业务模型的正确性反映在两个方面首先业务选择的正确性和业务比例的正确性。
  首先业务选择,一个系统可能支持几百个业务活动(也有叫做交易)但是只有少数的业务活动非常频繁,占总业务量的80%以上,那么在性能测试时只需关心这些占了大部分业务量的少量业务上。
  其次业务比例,如何精确统计业务的数量是关键问题,针对一个全新的系统可能要通过对使用系统的涉众进行调研,搞清楚他们群体数量,操作行为周期。在通过组合这些数据确定在常规业务日中各种业务占总业务的比率,同时也要考虑特殊交易日的情况,
  例如某一个商务活动或周期性的业务结算日等都是特殊交易日,在特殊交易日时某一类业务量可能突然增高很多那么在常规业务日的业务比例就不再合适,这点在业务模型上要进行区分。常规业务模型用来测试系统容量,特殊日业务模型要单独做压力负载测试场景。
  对于已上线运营的系统做业务模型的调研相对简单,不再需要去调研那么多的涉众,只需与运营维护部门进行协调,由他们协助测试需求调研人员提取系统中的历史数据就可以,那么在数据选择上要有些规则,要选取相对长时期的数据比如几个月,有条件的选取一年数据,取一年中每月平均业务量,选取年度高峰月业务数据,选取月度高峰日业务数据。
  2.测试模型
  业务模型是根据系统运营真实数据得来的,真实反映系统运营的业务状况。测试模型是以业务模型为基础根据测试需求不同对业务模型调整或不调整纳入到测试场景中直接使用。
  七、性能指标分析方法
  1.性能测试指标
  业务处理能力:每秒处理交易数量
  业务响应性:每种业务执行响应时间
  业务正确率:执行过程中通过事务占总业务比例
  系统资源指标:系统资源占用率
  2.业务处理能力
  业务处理能力是评测系统每秒所能处理的最大业务量,单位是Transaction/sec
  计算每秒处理业务量需要两个关键数据,一个是在指定时间内的指定业务量,二是指定的时间段。如何选择这两个数据是非常关键。通常业务调研阶段给的每天平均业务量或者某高峰日最大业务量。如何转换数据为每秒业务量,通常有算法:
  28规则,这是比较常用的计算方法
  例如:一个系统日交易高峰某100000笔交易,系统每天运营8个小时
  那么计算规则是 100000笔*80% / (8*3600*20%) =14笔/秒

posted @ 2013-11-26 11:16 顺其自然EVO 阅读(1688) | 评论 (0)编辑 收藏

Android下进行单元测试

字体:        | 上一篇 下一篇 | 打印  | 我要投稿  | 推荐标签: 软件测试 单元测试

  Android测试中,主要使用JUnit进行单元测试。其执行主要注意以下两点
  1、测试类必须要继承android下的AndroidTestCase类,并使用assertEquals方法来测试结果是否正确
  2、对AndroidManifest.xml进行配置
  在manifest节点下添加指令集配置信息,如下:
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.callactivity"/>
  其中name表示指令集名称,该名称是固定的;targetPackage用于指定测试的目标应用程序。
  在application节点下添加函数库的配置信息,如下:
<uses-library android:name="android.test.runner"/>
  测试类编写完成后用,选择测试的方式:点击右键-“Run As”-“Android Junit Test”。若能正确执行,效果如下图所示。

posted @ 2013-11-26 11:15 顺其自然EVO 阅读(244) | 评论 (0)编辑 收藏

LoadRunner中HTML模式与URL模式的区别

  在Web(HTTP/HTML)录制中,有2种重要的录制模式。
  用户该选择那种录制模式呢?
  一)HTML-mode录制是缺省也是推荐的录制模式。它录制当前网页中的HTML动作。
  在录制会话过程中不会录制所有的资源。在回放时,HTML-mode脚本积极地解析返回的信息来获得要下载的资源。
  HTML-mode是亦称上下文敏感方式因为它只能在先前请求的结果的上下文之内执行。由于许多的HTTP 请求数据都是从内存中取出来的,所以语句必须在正确的前个请求之后执行。
  HTML-mode录制的优点是:
  1.资源从内存中取出且在回放时下载。因此,脚本比其他的录制方式更小且更容易阅读。
  2.由于只有较少的硬编码脚本,因此只有较少的动态数值需要关联。
  3.可以插入图片检查之类的语句以检查结果是否正确。
  4.因为HTML模式回放时需要积极地解析返回的信息,因此它可能会比其他录制模式更加占用资源。然而,HTML模式record/replay有相当大的改善,使得差异最小化且微不足道。
  二)URL-mode选项指导VuGen录制来自server的所有的请求和资源。它自动录制每一个HTTP资源为URL的步骤。这种录制模式甚至抓取非HTML应用程序,例如applets和非浏览器的应用程序。推荐使用这种录制方式录制以下情况:
  1。录制非browser的应用程序
  2。取得在下载或不下载哪些资源上更好的控制,既然你可以在脚本中修改。
  3。当使用LR6.x时,录制使用applet和/或javascript的浏览器应用程序
  由于URL-模式录制了所有的请求和资源,需要做更多的关联。脚本看起来也会相当的长
  ============================================================
  LoadRunner针对Web协议的两种录制级别
  ****************
  (一)HTML 录制级别
  HTML录制级别是工具默认的选项。
  使用HTML录制级别,VuGen将会基于当前Web页面的HTML上下文来 产生语句。

 (二)URL 录制级别
  VuGen会录制所有的客户端请求和从服务器返回的资源。这种录制级别下,VuGen会录制URL 步骤为web_url语句。录制表单提交为web_submit_data语句。
  Tips:当在表单提交或者点击链接时 遇到问题,使用高级选项下的URL Option来录制。
  URL录制级别把对服务器每个对象的请求,都录制成一个单独的请求。对业务过程有更好的控制。============================================================
  (1)HTML-based script(浏览器/上下文敏感)
  (2)URL-based script(HTTP/analog)
  html模式录制脚本,lr会把将页面发出的请求写在一个函数里,这样集成性较高,在代码阅读方面也比较容易,这种方式录制出来的脚本可以说是一种高级脚本
  url方式录制的脚本是将页面所有的请求分别建立一个函数,这样的代码比较靠近底层,能更容易的监控到页面每个元素的情况
  再举个例子
  HTML模式相当于编程语言中的VC,
  url模式相当于C或者汇编语言写的脚本
  ***************
  HTML-based Script,说明脚本中采用HTML 页面的形式来表示这种方式的Script 脚本容易维护,容易理解;
  URL-based Script,说明脚本中的表示采用基于URL 的方式,WAS 和ACT中的录制方式就是这种,这种方式看上去比较乱。
  选择哪种方式录制,有以下参考原则:
  (1) 基于浏览器的应用程序推荐使用HTML-based Script
  (2) 不是基于浏览器的应用程序推荐使用URL-based Script。
  (3)如果基于浏览器的应用程序中包含了JavaScript 并且该脚本向服务器产生了请求,比如DataGrid 的分页按钮等,flash等,也要使用URL-based 方式录制
  (4 )基于浏览器的应用程序中使用了HTTPS 安全协议,使用URL-based 方式录制
  ****************
  web_find只能用于基于HTML的脚本
  web_reg_find:HTML和URL脚本都可以用,还可以统计文本出现的次数,但它是注册类型函数,意味着它不会立即执行,仅在执行下一个操作函数(比如web_url,web_image)后才会执行

posted @ 2013-11-26 11:14 顺其自然EVO 阅读(4714) | 评论 (0)编辑 收藏

覆盖率测试工具(coverage tool)

 java:
  Emma:优点:1 开源软件;2 支持ANT TASK;Emma 是开源的,同时它对应用程序执行速度的影响非常小。
  缺点:1 ANT TASK的参数指定较弱,coverage参数需要追加配置文件。
  EMMA是一个免费且开源的Java代码覆盖率测试工具,100%纯Java编写,不依赖与任何第三方库。和其他代码覆盖率测试工具不同,EMMA支持大型项目的团队开发,每个开发人员都可以从中受益。
  EMMA通过对Class文件进行增强以测试覆盖率,它提供了Offline和Fly两种模式,在Fly模式下,EMMA不改动编译后的Class文件,仅仅在Class文件被ClassLoader装载时才进行增强。【AOP技术】
  EMMA支持对类,方法,代码行和基本的分支语句的覆盖率测试,并提供了多种格式的报告,包括纯文本,HTML和XML,所有的报告都可以进行详细设置以获得定制报告。
  使用EMMA时,不需要获得源代码就可进行覆盖率测试,此外,EMMA还支持对整个jar文件测试。
  EMMA默认提供了对Ant的集成,通过扩展EMMA还可以提供对Maven和Eclipse的支持。
  EclEmma:
  EclEmma的出现弥补了 Emma 用户一个大的遗憾 ---- 缺乏图形界面以及对集成开发环境的支持。将 Eclipse 和 Emma 这两个在各自领域最为优秀的工具结合起来,这就是 EclEmma 为我们提供的。接下来,我们就要在后续章节中和读者朋友一起看看 EclEmma 为开发人员提供了什么。
  Cobertura:
  优点:1 开源软件;2 支持MARVEN
  缺点:1 可定制参数太少,UTF-8编码文件,直接挂掉,从文件的输出上来看,还是以xml,html生成为主。
  http://www.ibm.com/developerworks/cn/java/j-lo-eclemma/index.html 使用 EclEmma 进行覆盖测试
  2007 年 5 月 10 日;级别: 初级 ;甘 志 (ganzhi@cn.ibm.com), 软件工程师, IBM 中国软件开发中心实验室
  覆盖测试是衡量测试质量的一个重要指标。在对一个软件产品进行了单元测试、组装测试、集成测试以及接受测试等繁多的测试之后,我们能不能就此对软件的质量产生一定的信心呢?这就需要我们对测试的质量进行考察。如果测试仅覆盖了代码的一小部分,那么不管我们写了多少测试用例,我们也不能相信软件质量是有保证的。相反,如果测试覆盖到了软件的绝大部分代码,我们就能对软件的质量有一个合理的信心。本文将介绍一个优秀的开源软件测试工具 EclEmma,它能够对由 Java 语言编写的程序进行覆盖测试,从而对程序运行的结果生成详尽的覆盖测试报告。
========================
linux+ c/c++ +gcc:
gcov/lcov:
http://ggcov.sourceforge.net
http://blog.csdn.net/livelylittlefish/article/details/6321861
http://blog.csdn.net/livelylittlefish/article/details/6321887

 1. gcov是什么?
  Gcov is GCC Coverage
  是一个测试代码覆盖率的工具
  是一个命令行方式的控制台程序
  伴随GCC发布,配合GCC共同实现对C/C++文件的语句覆盖和分支覆盖测试;
  与程序概要分析工具(profiling tool,例如gprof)一起工作,可以估计程序中哪一段代码最耗时;
  注:程序概要分析工具是分析代码性能的工具。
  2. gcov能做什么?
  gcov可以统计
  每一行代码的执行频率
  实际上哪些代码确实被执行了
  每一段代码(section code)的耗时(执行时间)
  因此,gcov可以帮你优化代码,当然这个优化动作还是应该有开发者完成。
  1. Lcov是什么?
  是GCOV图形化的前端工具
  是Linux Test Project维护的开放源代码工具,最初被设计用来支持Linux内核覆盖率的度量
  基于Html输出,并生成一棵完整的HTML树
  输出包括概述、覆盖率百分比、图表,能快速浏览覆盖率数据
  支持大项目,提供三个级别的视图:目录视图、文件视图、源码视图
  ========================
  Python代码覆盖工具coverage.py介绍(http://nedbatchelder.com/code/coverage/)
  http://magustest.com/blog/whiteboxtesting/python-coverage-py/
  ========================
  JavaScript:
  JavaScript测试覆盖率检测工具JSCoverage
  ========================
  PHP:
  PHPUnit是一个轻量级的PHP测试框架。它是在PHP5下面对JUnit3系列版本的完整移植,是xUnit测试框架家族的一员(它们都基于模式先锋Kent Beck的设计)。
  单元测试是几个现代敏捷开发方法的基础,使得PHPUnit成为许多大型PHP项目的关键工具。
  这个工具也可以被Xdebug扩展用来生成代码覆盖率报告 ,并且可以与phing集成来自动测试,最后它还可以和Selenium整合来完成大型的自动化集成测试。

posted @ 2013-11-26 11:13 顺其自然EVO 阅读(1145) | 评论 (0)编辑 收藏

Java程序基本优化

 1.尽量指定类的final修饰符,因为带有final修饰符的类是不可派生的。
  2.尽量重用对象。
  3.尽量使用局部变量。
  4.不要重复初始化变量。
  5.在Java+Oracle的应用系统开发中,Java中内嵌的SQL语句应尽量使用大写,以减轻Oracle解析器解析的负担。
  6.在Java编程过程中进行数据库连接、I/O流操作时务必小心,使用完毕后应及时关闭以释放资源。
  7.JVM(Java虚拟机)有自身的GC(垃圾回收机制),但并非十分机智。用户对象后手动设置成null。
  8.在使用同步机制时,应尽量使用方法同步代替代码同步。
  9.尽量减少对变量的重复计算。
  10.尽量采用lazy loading 的策略,即在需要时才开始创建。
  11.谨慎使用异常。
  12.不要在循环中使用try-catch,放在最外层。
  13.注意StringBuffer(表示可变的可写的字符串)的使用。设置合适的容量。
  14.合理使用Java类java.util.Vector。一个Vector就是一个java.lang.Object实例的数组。
  15.当复制大量数据时,使用System.arraycopy()命令。
  16.尽量使用重构。
  17.不适用new 关键字创建类实例。
  18.谨慎使用乘法和除法。如某些乘法可以用移位代替。
  19.在JSP网页关闭无用的会话。 <@page session = “false”>
  20.JDBC与I/O。
  21.Servlet与内存使用。
  22.使用缓冲标记。
  23.选择合适的引用机制。如include指令和include动作。
  24.及时清除不再需要的会话。
  25.不要将数组声明为public static final;
  26.HashMap的遍历效率。
  27.Array数组和ArrayList的使用。

posted @ 2013-11-26 10:52 顺其自然EVO 阅读(168) | 评论 (0)编辑 收藏

数据库子查询

 子查询就像使用普通的表一样,被当作结果集的查询语句被称为子查询。所有可以使用表的地方几乎都可以使用子查询来代替。
  SELECT  *  FROM  (SELECT * FROM student  where sAge<30)  as t
  只有返回且仅返回一行、一列数据的子查询才能当成单值子查询。
  子查询返回的值不止一个。当子查询跟随在=、!=、<、<=、>、>=之后,或子查询用作表达式时,这种情况是不允许的。
tips:
select * from TblStudent
where
exists
(
--子查询的结果,要依赖于当前父查询中当前行的tsClassid的结果。
select * from TblClass
wheret ClassName='计算机软件班' and  tClassId=TblStudent.tsClassId
)
  如果子查询是多行单列的子查询,这样的子查询的结果集其实是一个集合。可以使用in关键字代替=号
  select * from student where sClassId in  ( select cId from class where cName='高一一班' or cName='高二一班' )  等价于
  Select* from student where exists(select * from class where (cName=‘高一一班’or cName=‘高二二班’)and class.cid=student.sclassid)

posted @ 2013-11-26 10:48 顺其自然EVO 阅读(167) | 评论 (0)编辑 收藏

使用JMeter的Java请求功能测试Hetty性能

 1.JMeter介绍
  JMeter是Apache组织的开放源代码项目,它是功能和性能测试的工具,100%的用java实现。JMeter可以用于测试静态或者动态资源的性能(文件、Servlets、Perl脚本、java对象、数据库和查询、ftp服务器或者其他的资源)。JMeter用于模拟在服务器、网络或者其他对象上附加高负载以测试他们提供服务的受压能力,或者分析他们提供的服务在不同负载条件下的总性能情况。
  2.启动JMeter
  进入JMeter的bin目录,然后执行:
  sudo ./jmeter.sh
  3.原始的测试方法
  在没有使用JMeter前,我对hetty的性能测试,都是通过自己写多线程代码去完成的,相当苦逼,相当麻烦,不过也能锻炼自己的编码能力,我先贴出比较原始的测试方法,如下:
public class RpcHessianClient {
public static void main(String[] args) {
String url = "http://localhost:8081/apis/hello";
HessianProxyFactory factory = new HessianProxyFactory();
ExecutorService es = Executors.newFixedThreadPool(10);
int size = 1000000;
final CountDownLatch cdl = new CountDownLatch(size);
try {
long start = System.currentTimeMillis();
factory.setUser("client1");
factory.setPassword("client1");
factory.setOverloadEnabled(true);
final Hello basic = (Hello) factory.create(Hello.class,
url);
for (int i = 0; i < size; i++) {
es.submit(new Runnable() {
@Override
public void run() {
String u=basic.hello("guolei");
//System.out.println(u);
cdl.countDown();
}
});
}
cdl.await();
long time = System.currentTimeMillis() - start;
System.out.println("SayHello:");
System.out.println("耗时:" + (double) time / 1000 + " s");
System.out.println("平均:" + ((double) time) / size +" ms");
System.out.println("TPS:" + (double) size / ((double) time / 1000));
// System.out.println("Hello, " + s.getMail());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
es.shutdown();
}
}

 4.使用JMeter来进行现代化测试
  我们要使用JMeter来测试hetty,由于hetty是一款基于hessian和netty的RPC产品,我们必须使用JMeter的JAVA请求功能来进行测试,Java请求是指JMeter对Java Class进行性能测试。首先我们需要编写测试用例:
  1)新建JAVA工程。
  2)引入ApacheJMeter_java.jar 、ApacheJMeter_core.jar以及测试所需要的jar(jar包在JMeter目录的lib/ext目录中)。
  3)继承AbstractJavaSamplerClient类开始编写主业务。如下:
public class HettyTest extends AbstractJavaSamplerClient {
private static String label = "hettyTest";
/**
* 执行runTest()方法前会调用此方法,可放一些初始化代码
*/
public void setupTest(JavaSamplerContext arg0) {
}
/**
* JMeter测试用例入口
*/
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
sr.setSampleLabel(label);
try { // 这里调用我们要测试的java类,这里我调用的是一个Test类
Map<String,String> map = getDefaultParameters().getArgumentsAsMap();
sr.sampleStart(); // 记录程序执行时间,以及执行结果
Test.execute(map.get("ip"),map.get("port"));
sr.sampleEnd();
sr.setSuccessful(true);
} catch (Throwable e) {
sr.setSamplerData(e.getMessage());
e.printStackTrace();
sr.setSuccessful(false); // 用于设置运行结果的成功或失败,如果是"false"则表示结果失败,否则则表示成功
}
return sr;
}
/**
* JMeter界面中可手工输入参数,代码里面通过此方法获取
*/
public Arguments getDefaultParameters() {
Arguments args = new Arguments();
args.addArgument("ip", "localhost");
args.addArgument("port", "8081");
return args;
}
/**
* 执行runTest()方法后会调用此方法.
*/
public void teardownTest(JavaSamplerContext arg0) {
}
}
  Test类是我测试逻辑,如下:
public class Test {
public static void execute(String ip,String port) throws MalformedURLException {
String url = "http://"+ip+":"+port+"/apis/hello";
HessianProxyFactory factory = new HessianProxyFactory();
factory.setUser("client1");
factory.setPassword("client1");
factory.setOverloadEnabled(true);
final Hello basic = (Hello) factory.create(Hello.class, url);
//System.out.println("SayHello:" + basic.hello("guolei"));
}
}
  代码中都有注释,按照注释实际操作去理解。  System.out等的输出会显示在启动JMeter时的命令窗口内,但过多的输出会影响性能的准确性。

 代码中都有注释,按照注释实际操作去理解。  System.out等的输出会显示在启动JMeter时的命令窗口内,但过多的输出会影响性能的准确性。
  4)将项目打为jar包,放到JMeter目录下的lib/ext下(将项目依赖的jar也放到此目录)。
  5)重启JMeter。
  5.JMeter使用
  1)选中主界面左侧的“测试计划”,右键菜单->添加->Threads(Users)->线程组。
  2)再选中刚才新增的"线程组",右键菜单->添加->Sampler->Java请求。
  3)再选中刚才新增的"Java请求",右键菜单->添加->监视器->聚合报告。
  4)Ctrl + R,开始运行, Ctrl + E,清除历史结果。
  6.查看测试结果
  聚合报告中基本已经包含我们所关心的几个数据了:
  Samples -- 本次场景中一共完成了多少个Transaction
  Average -- 平均响应时间
  Median -- 统计意义上面的响应时间的中值
  90% Line -- 所有transaction中90%的transaction的响应时间都小于xx
  Min -- 最小响应时间
  Max -- 最大响应时间
  PS: 以上时间的单位均为ms
  Error -- 出错率
  Troughput -- 吞吐量,单位:transaction/sec
  KB/sec -- 以流量做衡量的吞吐量

posted @ 2013-11-25 10:38 顺其自然EVO 阅读(1749) | 评论 (0)编辑 收藏

使用DBUnit做单元测试

 DBUnit是一个方便的数据准备工具, 方便于我们做单元测试的时候准备数据, 它的数据准备是基于XML格式的, 如下:
<?xmlversion='1.0'encoding='UTF-8'?>
<dataset>
<YourTableName_1Field_1="1"Field_2="f2"Field_3="f3"/>
<YourTableName_1Field_1="2"Field_2="f2_1"Field_3="f3_1"/>
<YourTableName_2Field_1="1"Field_2="2"/>
</dataset>
  DBUnit的一个XML数据文件中,可以同时放多个表的数据,并且可以方便的把上面XML中准备的数据插入倒数据库中. 只需要使用下面简单的代码就可以做到:
protected ReplacementDataSet createDataSet(InputStream is) throws Exception {
return new ReplacementDataSet(new FlatXmlDataSetBuilder().build(is));
}
ReplacementDataSet createDataSet = createDataSet(Thread.currentThread().getContextClassLoader().getResourceAsStream("data.xml"));
DatabaseOperation.INSERT.execute(iconn, createDataSet);
  注:准备这处XML数据文件时,一定要把同一个表中字段数最多的记录放在前面,因为DBUnit在根据数据XML文件准备表的元数据字段的时候,是以当前表的第一记录为主的。如下面这个XML文件:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<YourTableName_1 Field_1="1" Field_2="f2"/>
<YourTableName_1 Field_1="2" Field_2="f2_1" Field_3="f3_1"/>
<YourTableName_2 Field_1="1" Field_2="2"/>
</dataset>
  Table YourTableName_1有三个字段,但是第三个字段Field_3是允许为空的,所以上面的XML是可以这样写的,并且DBUnit在执行插入的时候也不会报错,但是这里会出现一个问题,因为DBUnit在第一次分析到table YourTableName_1时,第一条记录只有两个字段,因而它在记录table YourTableName_1的字段的时候,就只会记录两个到这个表的元数据信息,因而在对在对后面记录进行数据处理的时候,只会取后面记录的两个字段,而第三个字段是不会被插入到数据库中。解决这个问题很简单,把YourTableName_1的第二条记录和第一条记录给换一下位置就好了。 同理,在数据result数据文件的时候,也要遵循这样的规则,否则会得不到想要的结果的。这是经验总结。
 你可能会担心如果是要准备的数据比较多是不是会比较麻烦,如上百条的数据准备,这个可以不用担心,因为使用DBUnit可以方便的从数据库中导出数据到指定的文件中,然后供我们使用,使用以下这个方法就可以导出数据:
/**
* Export data for the table names by the given IDatabaseConnection into the resultFile.<br>
* The export data will be DBUnit format.
*
* @param conn
* @param tableNameList
* @param resultFile
* @throws SQLException
* @throws DatabaseUnitException
* @throws FileNotFoundException
* @throws IOException
*/
public void exportData(IDatabaseConnection iconn, List<String> tableNameList, String resultFile) throws SQLException, DatabaseUnitException, FileNotFoundException, IOException {
QueryDataSet dataSet = null;
if (iconn == null) {
return;
}
if (tableNameList == null || tableNameList.size() == 0) {
return;
}
try {
dataSet = new QueryDataSet(iconn);
for (String tableName : tableNameList) {
dataSet.addTable(tableName);
}
} finally {
if (dataSet != null) {
FlatXmlDataSet.write(dataSet, new FileOutputStream(resultFile));
}
}
}
  DBUnit的另一个非常有用的功能,就是对执行结果进行比较,这样可以直接得到执行结果是否正确。 操作方式是准备一个执行期待结果的XML文件,再准备一条从数据库查询结果的SQL。这里有一个经验非常重要,那就是用于查询的执行结果的SQL文件,最好是加上某个关键字段的ORDER BY语句,否则可能会因为记录的顺序而比较失败,因为DBUnit是把查询出来的结果和准备的结果进行一一对应的比较。当然,既然SQL查询都加上了排序,那我们的结果XML文件,也应该是根据关键字段排好序的结果的,否则也会因为记录的顺序问题而比较失败。
 你可能会担心如果是要准备的数据比较多是不是会比较麻烦,如上百条的数据准备,这个可以不用担心,因为使用DBUnit可以方便的从数据库中导出数据到指定的文件中,然后供我们使用,使用以下这个方法就可以导出数据:
/**
* Export data for the table names by the given IDatabaseConnection into the resultFile.<br>
* The export data will be DBUnit format.
*
* @param conn
* @param tableNameList
* @param resultFile
* @throws SQLException
* @throws DatabaseUnitException
* @throws FileNotFoundException
* @throws IOException
*/
public void exportData(IDatabaseConnection iconn, List<String> tableNameList, String resultFile) throws SQLException, DatabaseUnitException, FileNotFoundException, IOException {
QueryDataSet dataSet = null;
if (iconn == null) {
return;
}
if (tableNameList == null || tableNameList.size() == 0) {
return;
}
try {
dataSet = new QueryDataSet(iconn);
for (String tableName : tableNameList) {
dataSet.addTable(tableName);
}
} finally {
if (dataSet != null) {
FlatXmlDataSet.write(dataSet, new FileOutputStream(resultFile));
}
}
}
  DBUnit的另一个非常有用的功能,就是对执行结果进行比较,这样可以直接得到执行结果是否正确。 操作方式是准备一个执行期待结果的XML文件,再准备一条从数据库查询结果的SQL。这里有一个经验非常重要,那就是用于查询的执行结果的SQL文件,最好是加上某个关键字段的ORDER BY语句,否则可能会因为记录的顺序而比较失败,因为DBUnit是把查询出来的结果和准备的结果进行一一对应的比较。当然,既然SQL查询都加上了排序,那我们的结果XML文件,也应该是根据关键字段排好序的结果的,否则也会因为记录的顺序问题而比较失败。

  上面的是热身,该来点实际的东西了, 弄个真实的实例来看看,下面是一个用于DBUnit测试的抽象类:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import junit.framework.Assert;
import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/spring.xml" })
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })
@Transactional
public abstract class BasedTestCase {
protected static Properties properties = new Properties();
static {
try {
/**
* The DatabaseConfig.properties stores the database configuration information. It's like this: <br>
* driverClass=oracle.jdbc.OracleDriver<br>
* db_inst=jdbc:oracle:thin:@1.1.1.1:1521:schema<br>
* db_user=username<br>
* db_pwd=password<br>
*/
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("DatabaseConfig.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This abstract is used for prepare data before do the real method call.
*
* @param iconn
* @throws Exception
*/
protected abstract void prepareData(IDatabaseConnection iconn) throws Exception;
/**
* Execute one sql
*
* @param iconn
* @param sql
* @throws Exception
*/
protected void execSql(IDatabaseConnection iconn, String sql) throws Exception {
Connection con = iconn.getConnection();
Statement stmt = con.createStatement();
try {
stmt.execute(sql);
} finally {
if (stmt != null) {
stmt.close();
}
}
}
/**
* Get IDatabaseConnection connection
*
* @return
* @throws Exception
*/
protected IDatabaseConnection getIDatabaseConnection() throws Exception {
String db_inst = "", db_user = "", db_pwd = "", driverClass = "";
//The default is commit the record
db_user = properties.getProperty("db_user");
db_inst = properties.getProperty("db_inst");
db_pwd = properties.getProperty("db_pwd");
driverClass = properties.getProperty("driverClass");
IDatabaseConnection iconn = null;
IDatabaseTester databaseTester;
databaseTester = new JdbcDatabaseTester(driverClass, db_inst, db_user, db_pwd);
iconn = databaseTester.getConnection();
return iconn;
}
/**
* This is used to assert the data from table and the expected data set. If all of the them has the same records, then the assert is true.
*
* @param tableName
* @param sql
* @param expectedDataSet
* @param iconn
* @throws Exception
*/
protected void assertDataSet(String tableName, String sql, IDataSet expectedDataSet, IDatabaseConnection iconn) throws Exception {
printDataAsXml(iconn, tableName, sql);
QueryDataSet loadedDataSet = new QueryDataSet(iconn);
loadedDataSet.addTable(tableName, sql);
ITable table1 = loadedDataSet.getTable(tableName);
ITable table2 = expectedDataSet.getTable(tableName);
Assert.assertEquals(table2.getRowCount(), table1.getRowCount());
DefaultColumnFilter.includedColumnsTable(table1, table2.getTableMetaData().getColumns());
Assertion.assertEquals(table2, table1);
}
/**
* Create the data set by input stream which read from the dbunit xml data file.
*
* @param is
* @return
* @throws Exception
*/
protected ReplacementDataSet createDataSet(InputStream is) throws Exception {
return new ReplacementDataSet(new FlatXmlDataSetBuilder().build(is));
}
/**
* Convert the data in the ITable to List
*
* @param table
* @return
* @throws Exception
*/
private List<Map<?, ?>> getDataFromTable(ITable table) throws Exception {
List<Map<?, ?>> ret = new ArrayList<Map<?, ?>>();
int count_table = table.getRowCount();
if (count_table > 0) {
Column[] columns = table.getTableMetaData().getColumns();
for (int i = 0; i < count_table; i++) {
Map<String, Object> map = new TreeMap<String, Object>();
for (Column column : columns) {
map.put(column.getColumnName().toUpperCase(), table.getValue(i, column.getColumnName()));
}
ret.add(map);
}
}
return ret;
}
/**
* Get data by the SQL and table name, then convert the data in the ITable to List
*
* @param iconn
* @param tableName
* @param sql
* @return
* @throws Exception
*/
protected List<Map<?, ?>> getTableDataFromSql(IDatabaseConnection iconn, String tableName, String sql) throws Exception {
ITable table = iconn.createQueryTable(tableName, sql);
return getDataFromTable(table);
}
/**
* Get data by the SQL and table name, then convert the data in the ITable to List. And the print the data as xml data format.
*
* @param iconn
* @param tableName
* @param sql
* @throws Exception
*/
protected void printDataAsXml(IDatabaseConnection iconn, String tableName, String sql) throws Exception {
List<Map<?, ?>> datas = getTableDataFromSql(iconn, tableName, sql);
StringBuffer sb;
for (Map<?, ?> data : datas) {
sb = new StringBuffer();
sb.append("<" + tableName.toUpperCase() + " ");
for (Object o : data.keySet()) {
sb.append(o + "=\"" + data.get(o) + "\" ");
}
sb.append("/>");
System.out.println(sb.toString());
}
}
/**
* Export data for the table names by the given Connection into the resultFile.<br>
* The export data will be DBUnit format.
*
* @param conn
* @param tableNameList
* @param resultFile
* @throws SQLException
* @throws DatabaseUnitException
* @throws FileNotFoundException
* @throws IOException
*/
public void exportData(Connection conn, List<String> tableNameList, String resultFile) throws SQLException, DatabaseUnitException, FileNotFoundException, IOException {
if (conn == null) {
return;
}
IDatabaseConnection iconn = new DatabaseConnection(conn);
exportData(iconn, tableNameList, resultFile);
}
/**
* Export data for the table names by the given IDatabaseConnection into the resultFile.<br>
* The export data will be DBUnit format.
*
* @param conn
* @param tableNameList
* @param resultFile
* @throws SQLException
* @throws DatabaseUnitException
* @throws FileNotFoundException
* @throws IOException
*/
public void exportData(IDatabaseConnection iconn, List<String> tableNameList, String resultFile) throws SQLException, DatabaseUnitException, FileNotFoundException, IOException {
QueryDataSet dataSet = null;
if (iconn == null) {
return;
}
if (tableNameList == null || tableNameList.size() == 0) {
return;
}
try {
dataSet = new QueryDataSet(iconn);
for (String tableName : tableNameList) {
dataSet.addTable(tableName);
}
} finally {
if (dataSet != null) {
FlatXmlDataSet.write(dataSet, new FileOutputStream(resultFile));
}
}
}
}


这个抽象类里面有实用插入数据、导出数据及验证数据的实现,也包括了数据库连接的准备,该类里面包含了一个抽象方法prepareData,因为任何使用DBUnit做单元测试的,应该是少不了数据准备这么一个过程,否则就只能够使用数据库中的现成数据,这样的单元测试是不靠谱的,因为数据库中的数据随时可能发生变化,这里的抽象方法prepareData就相当于在提醒写单元测试的人,不要忘了准备单元测试要用的数据。
  根据上面的思路,准备一个用于测试的Table:
create table YouTableName_1(
filed_1 int,
filed_2 varchar2(50),
filed_3 varchar2(50)
)
  用于测试的数据:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<YouTableName_1 Filed_1="1" Filed_2="f2" Filed_3="f3"/>
<YouTableName_1 Filed_1="2" Filed_2="f2_1" Filed_3="f3_1"/>
</dataset>
  用于验证测试结果的数据:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<YouTableName_1 Filed_1="1" Filed_2="a" Filed_3="a1"/>
<YouTableName_1 Filed_1="2" Filed_2="b" Filed_3="b1"/>
</dataset>
  我们这个测试非常简单,就是把Filed_1为1的字段中Filed_2和Filed_3的字段的值分别设为"a"和"a1",把Filed_1为2的字段中Filed_2和Filed_3的字段的值分别设为"b"和"b1",做完测试后,数据库中是不会插入我们的单元测试的数据的。
  下面这个类UpdateTest用于更新数据:
import java.sql.Connection;
import java.sql.SQLException;
public class UpdateTest {
private static boolean commit = true;
public UpdateTest() {
}
private void commit(Connection conn) throws SQLException {
if (commit) {
conn.commit();
}
}
public void updateFiled(Connection conn) throws SQLException {
conn.createStatement().execute("update YouTableName_1 set filed_2='a',filed_3='a1' where filed_1=1");
conn.createStatement().execute("update YouTableName_1 set filed_2='b',filed_3='b1' where filed_1=2");
commit(conn);
}
}
 下面这个MyTest类,就是用于单元测试的类:
package com.ubs.cre.tools.datatool.ipl;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import junit.framework.Assert;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Test;
import com.ubs.cre.BasedTestCase;
public class MyTest extends BasedTestCase {
@Test
public void testSend() throws IOException, SQLException {
Connection conn = null;
Boolean result = Boolean.FALSE;
IDatabaseConnection iconn = null;
try {
//Get DBUnit conneciton
iconn = getIDatabaseConnection();
//Get database connection
conn = iconn.getConnection();
//Set auto commit false
conn.setAutoCommit(false);
//prepare data
prepareData(iconn);
//use reflect to set the commit field to false
Class<UpdateTest> clazz = UpdateTest.class;
Field commitField = clazz.getDeclaredField("commit");
commitField.setAccessible(true);
commitField.setBoolean(clazz, false);
//call the method updateFiled
Method method = clazz.getDeclaredMethod("updateFiled", java.sql.Connection.class);
method.setAccessible(true);
//Before call the method, the clazz must be get an new install, because the called method "updateFiled" is not static.<br>
//If the called method is static, it will not need newInstance.
method.invoke(clazz.newInstance(), conn);
// get result data set by result xml file
ReplacementDataSet dataload_result = createDataSet(Thread.currentThread().getContextClassLoader().getResourceAsStream("MyTest_Result.xml"));
// compare the data which get from database and the expected result file
assertDataSet("YouTableName_1", "select filed_1,filed_2,filed_3 from YouTableName_1 order by filed_1", dataload_result, iconn);
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue(result);
} finally {
if (conn != null) {
conn.rollback();
conn.close();
}
}
}
protected void prepareData(IDatabaseConnection iconn) throws Exception {
//Remove the data from table YouTableName_1
execSql(iconn, "delete from YouTableName_1");
//INSERT TEST DATA
ReplacementDataSet createDataSet = createDataSet(Thread.currentThread().getContextClassLoader().getResourceAsStream("MyTest.xml"));
DatabaseOperation.INSERT.execute(iconn, createDataSet);
}
}
  好了,示例完了,非常的简单,也非常的清晰,不过美中不足就是和DBUnit的代码耦合度太高了,这过对于我们使用习惯了Spring的人来说,看起来是非常别扭的,后面我会写另外一个与Spring集成的、完全非侵入式的测试实现,等着吧。

posted @ 2013-11-25 10:35 顺其自然EVO 阅读(664) | 评论 (0)编辑 收藏

软件测试工程师岗位职责概括

 part1. 主要职责说明:
  1 编写测试计划:仔细阅读项目规格说明、设计文档、使用说明书等,充分掌握软件的性能、特点、使用方法、业务流程等,协助测试经理制定项目的测试计划,保证产品测试工作的计划性与规范性
  2 编写测试用例:按照测试流程、计划以及对产品特性的把握,沟通确认测试的范围、重点,考虑逻辑、数据完整性等要求,详细规定测试的要求,策划、编写测试用例,设计测试用数据及预期结果,做好测试前的准备工作,确保测试目的的达成
  3 搭建测试环境,保证测试环境的独立和维护测试环境的更新,做好测试前的准备工作,确保测试环境的稳定和版本的正确。
  4 执行测试,根据测试计划及测试案例,执行测试,并根据产品特点及测试要求,实施集成测试、系统测试等,及时发现软件缺陷,评估软件的特性与缺陷,确保测试目的的达成。
  5 进行BUG验证根据测试结果,与开发部门反复沟通测试情况,督促开发部门解决问题,修正测试中发现的缺陷,完善软件功能
  6 进行测试记录和相应文档编写。
  7 编写测试报告和对测试结果分析,通过测试,掌握软件具有的能力、缺陷、局限等,对软件质量给出评价性的结论与意见,整理测试文档,填写软件测试报告,编写测试总结,为软件开发成果提供总结性意见
  8 完成上级及部门其他领导交办的临时任务
  part2. 熟悉测试流程,能独立完成测试计划,测试用例设计。
  熟悉数据库检索操作,需要熟悉Oracle,Sybase,Mysql,SQLserver中至少一种。
  黑盒测试,灰盒测试,需要有一定的代码基础(.net/c#/php)
  会使用一种或多种功能自动化测试工具
  有一定的系统配置经验的优先考虑
  part3. -根据项目计划制定项目测试用例并实施,保证项目质量和进度
  -根据项目设计与实现有关自动化测试的代码与用例
  -根据项目特点,开发合适测试工具或自动化解决方案,提高测试效率
  -参与程序架构和代码的评审工作,并提出改进意见
  -设计与执行测试用例,跟踪定位产品软件中的缺陷或问题
  -与项目相关人员就项目进度和问题进行沟通
  -参与电信项目开发;参与参加定制终端项目开发,包括但不限于:
  负责测试计划编写,测试用例设计,测试执行和报告,编写必要的测试工具。
  part4.任职要求:
  统招正规大学本科以上计算机相关及相关专业;
  熟练操作UNIX和windows操作系统,熟悉Unix Shell编程;
  熟悉常用的Test工具和bug tracking 工具;
  熟悉常用大型数据库如Oracle/Sybase的使用及安装;
  良好的文档书写能力;
  要求英语具有良好的听写能力;
  具有电信软件开发经验者优先;
  学习能力强,善于思考总结,工作认真、责任心强,有较强的沟通和协作开发能力,工作效率高。

posted @ 2013-11-25 10:30 顺其自然EVO 阅读(349) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 178 179 180 181 182 183 184 185 186 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜