所谓自动化测试框架,可以解释为自动化测试的整体解决方案,是由一些假设、概念和为自动化测试提供支持的系统及其最佳实践等构成的集合。对不同的应用领域或不同的测试水平,自动化测试的框架具有不同的构成,但我们必须清楚如何满足自动化测试的基本要求,了解自动化测试框架的基本构成,从而在此基础上,根据自己组织的实际情况来进行扩充,从而构造适应性更强、效率更高、功能更强的自动化测试框架。
为了能开展自动化测试的工作,首先需要基础设施(infrastructure)来支撑测试工具的运行,这包括Web 服务器、邮件服务器、FTP 服务器等。其次是执行自动化测试,要有一套机制来保证测试脚本的执行。具体地说,就是先建立测试环境,创建和执行测试套件,然后获取执行状态并给出测试结果报告。根据这个分析,可以描述一个自动化测试框架的雏形,如图2-11 所示。
图2-11 软件自动化测试框架的雏形
图2-11 中的雏形给出了自动化测试框架的基本构成要素,包括执行器、脚本管理器、报告生成器等,也比较清楚地描述了这些要素之间的关系。但是,这个框架还没给出其他一些必要的信息,例如:
测试脚本的层次性,如何分离业务逻辑和系统基本操作?
如何实现自动化测试工具的接口?
如何实现被测试系统的对象映射?
如何事先安排测试任务?
如何管理有效测试资源?
如果要在测试脚本上分离业务逻辑和系统基本操作,必须将各种基本操作封装为特定的关键字,每个关键字对应一个函数,而业务逻辑可以由关键字和参数来描述,即可以通过图2-12 来描述这种脚本结构。
图2-12 关键字驱动脚本框架示意图
事先安排测试任务,也是非常重要的。例如,测试人员在下班前将测试任务安排好,测试实际执行可以在晚上9 点钟以后或得到新的软件包后自动开始。这样,测试人员在第二天上班前就可以得到测试报告。安排完任务,还需要开发具有相应触发机制的引擎(Engine/ Cron Job)来执行测试任务。它负责完成自动部署软件包、向各台远程测试机器分发脚本并启动测试工具等工作。对于这部分,可以用图2-13 来描述,其中底层的基础设施可以由STAX 实现。
图2-13 自动化测试任务的安排和执行
介绍
最近忙着赶项目,无暇去写博客。今天我想知道大家是怎么估算项目时间进度的?
我把我这次项目经历,唠叨唠叨。
情况
要做新的项目,产品经理A来找我,问我,这个项目你需要多长时间完成?
前提条件:我没看过需求,我只是泛泛的看了下demo,只是知道,页面上有哪些内容,有多少种情况?我没有办法回答她,因为我自己也不知道到底用多长时间。因为我实在没有办法估算时间。然后产品经理A告诉我,你差不多2周就能完成。那我说,你给我3周吧?我还得做代码调试呢!(其实我挺心虚的,我知道这个页面的功能相当的复杂,但是产品经理A告诉我,数据,接口都是准备好的)。
然后又过了两天,产品经理B找了我,问我,这个项目你估计多长时间能做完?我说3周。B跟我说,我们这个项目比较紧,老大那里着急要呢?时间拖的太长了(这不是因为你们一直拿不下方案,拖了快半年了,怎么到我这里就剩这么点时间了)。我跟他解释:差不多代码2周就能形成,还要一周进行相关调试呢?然后B就回去了。
又过了两天,项目下来了,时间是维期2周,我的开发时间就2周,怎么会这样?A跟我说,不是你跟B说,2周吗?——我冤死了,算了,反正就是做事吗?自己赶紧点应该能完成。
意外不断
我周一需要开始开发,A还没有给我需求。A说,周日他过来加班,然后再给我需求。周一回来了,需求只是一部分,A说,这个估计你也要开发一段时间了。等你开发完了,我后面的需求也就上来了。
就这样开发了一周。设计人员那里的demo也在同步进行中。
后来,开发一周左右,发现原来使用的模块,要用新的接口A,但是接口A还不能满足我现有的需求,必须需要程序员A重新包装给我,这样再等了一下午,第二天,问题不断,不停的跟程序员A进行调试,终于完成此模块的功能。
临近项目结束,模块B又出现问题,产品人员许诺的接口,找了相关技术人员,并没有准备好。原有的接口B也要抛弃掉,跟产品A商量后,决定先放弃此模块,项目结束后再继续开发。
临近项目上线的前两天,测试人员才开始真真正正的测试,给我提了一堆的bug。然后第二天,我疯狂的修改bug。
在项目开发阶段,小问题不断,这里不要这个模块了,这个模块需要列表了,这个模块要移动按钮要修正了……。
终于项目于昨日匆匆结束。
今天一天,问题不断,不停修改bug。
感受
这两周,我快累得吐血了,不停的编码,几乎就没有休息过。
1、产品人员追的太紧了,他们自己不紧不慢的定方案快小半年了,给我的开发时间就2周。——我快疯了。
2、测试人员,给了他一周的测试时间,结果临近上线才真正的测试,然后快要上线了,给我提了一堆的bug。——我快神经质了。
3、接口提供的开发人员。不停的把事情推到我这里,我自己这边的事情越来越多。估计是我嘴笨,老是说不过他们,我也不知道,他们哪里来的那么多道理。——我快气死了。
痛定思痛
1、在项目开始阶段,我并不十分清楚每个模块详细情况(如,接口数据的存储情况,复杂度,以及怎么展现)。因为本身这时根本就没有需求文档。
2、项目开始阶段,本身就不应该受产品人员的影响,他们说多长时间,你就受他们的影响,而拟定自己的时间计划,应该让更熟悉这块的人来给你拟定时间度(如找我们头,项目经理)。
3、在开发阶段,不应该让产品不停的修改方案,我本身知道这个道理,但是没有办法,因为本身就没有详细的需求文档,想到哪里就做哪里。
4、应该在临近上线的时候不能让测试人员提bug,或者此bug(不是紧急的bug)只能上线之后,后期再进行跟踪修复。——这个我明天找项目经理,反应一下这个情况。否则,明天上线,你还在不停的修改代码。
5、接口提供的开发人员,必须要求他们给我们详细的文档,以邮件的形式发给我们,否则,你根本就无从入手。——此次开发,我不停的去他们那里询问接口调用细节。
6、同事建议我,把需求打成碎片,一块一块的评估。——天,哪有什么需求,他们自己拟定方案的时候,我就参与过一次会议,其他会议我都没有参与过,无暇知道他们是怎么想的。——估计是有预谋不让我参加,怕我知道,时间拖得比较长吧?(我猜的)。
总结
以上是我这次项目的经历,在这过程中,我知道自己有很多的问题,但是我最大的疑虑,也是我5年开发中一直遇到的问题,就是开发周期问题。
我同事跟我说,开发周期,你要预估下时间,然后你再这个时间基础上再加一周时间。但是我这预估的时间,我自己都没办法预估出来。很多时候我都是被自己的项目搞的晕头晕脑的。——很多道理我懂,但是真正到实际中,实在摸不开面子,既然拿了人家的工资,就要努力给人家做事情。自己吃点亏,累点没什么。
也许大家会责怪我,这一切都是你自己的错误,自己酿下的苦果,自己就要承受。——呵呵,是啊,我写此文,也是发发牢骚而已,一吐心中的烦闷。
如果大家在时间估算上有什么技巧的话,不妨相授彼人,不慎感激。
3、fillInStackTrace()
我们在前面也提到了这个方法。要说清楚这个方法,首先要讲一下捕获异常之后重新抛出的问题。在catch代码块中捕获到异常,打印栈轨迹,又重新throw出去。在上一级的方法调用中,再捕获这个异常并且打印出栈轨迹信息。这两个栈轨迹信息会一样吗?我们看一下代码:
public class TestPrintStackTrace { public static void f() throws Exception{ throw new Exception("出问题啦!"); } public static void g() throws Exception{ try { f(); }catch(Exception e) { e.printStackTrace(); throw e; } } public static void main(String[] args) { try { g(); }catch(Exception e) { e.printStackTrace(); } } } |
在main方法中捕获的异常,是在g()方法中抛出的,按理说这两个打印栈轨迹的信息应该不同,第二次打印的信息应该没有关于f的信息。但是事实上,两次打印栈轨迹信息是一样的。输出结果如下:
java.lang.Exception: 出问题啦! at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:7) at TestPrintStackTrace.main(TestPrintStackTrace.java:16) java.lang.Exception: 出问题啦! at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:7) at TestPrintStackTrace.main(TestPrintStackTrace.java:16) |
也就是说,捕获到异常又立即抛出,在上级方法调用中再次捕获这个异常,打印的栈轨迹信息是一样的。原因在于没有将当前线程当前状态下的轨迹栈的状态保存进Throwabe中。现在我们引入fillInStackTrace()方法。这个方法刚好做的就是这样的保存工作。我们看一下这个方法的原型:
public Throwable fillInStackTrace() |
这个方法是有返回值的。返回的是保存了当前栈轨迹信息的Throwable对象。我们看看使用fillInStackTrace()方法处理后,打印的栈轨迹信息有什么不同,代码如下:
public class TestPrintStackTrace { public static void f() throws Exception{ throw new Exception("出问题啦!"); } public static void g() throws Exception{ try { f(); }catch(Exception e) { e.printStackTrace(); //不要忘了强制类型转换 throw (Exception)e.fillInStackTrace(); } } public static void main(String[] args) { try { g(); }catch(Exception e) { e.printStackTrace(); } } } |
输出如下:
java.lang.Exception: 出问题啦! at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:7) at TestPrintStackTrace.main(TestPrintStackTrace.java:17) java.lang.Exception: 出问题啦! at TestPrintStackTrace.g(TestPrintStackTrace.java:11) at TestPrintStackTrace.main(TestPrintStackTrace.java:17) |
我们看到,在main方法中打印栈轨迹已经没有了f相关的信息了。
以上就是关于Java栈轨迹的一些我之前没有掌握的内容,记下来备忘。 捕获到异常时,往往需要进行一些处理。比较简单直接的方式就是打印异常栈轨迹Stack Trace。说起栈轨迹,可能很多人和我一样,第一反应就是printStackTrace()方法。其实除了这个方法,还有一些别的内容也是和栈轨迹有关的。
1、printStackTrace()
首先需要明确,这个方法并不是来自于Exception类。Exception类本身除了定义了几个构造器之外,所有的方法都是从其父类继承过来的。而和异常相关的方法都是从java.lang.Throwable类继承过来的。而printStackTrace()就是其中一个。
这个方法会将Throwable对象的栈轨迹信息打印到标准错误输出流上。输出的大体样子如下:
java.lang.NullPointerException at MyClass.mash(MyClass.java:9) at MyClass.crunch(MyClass.java:6) at MyClass.main(MyClass.java:3) |
输出的第一行是toString()方法的输出,后面几行的内容都是之前通过fillInStackTrace()方法保存的内容。关于这个方法,我们后面会讲。
下面看一个例子:
public class TestPrintStackTrace { public static void f() throws Exception{ throw new Exception("出问题啦!"); } public static void g() throws Exception{ f(); } public static void main(String[] args) { try { g(); }catch(Exception e) { e.printStackTrace(); } } } |
这个例子的输出如下:
java.lang.Exception: 出问题啦! at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:6) at TestPrintStackTrace.main(TestPrintStackTrace.java:10) |
在这个例子中,在方法f()中抛出异常,方法g()中调用方法f(),在main方法中捕获异常,并且打印栈轨迹信息。因此,输出依次展示了f—>g—>main的过程。
2、getStackTrace()方法
这个方法提供了对printStackTrace()方法所打印信息的编程访问。它会返回一个栈轨迹元素的数组。以上面的输出为例,输出的第2-4行每一行的内容对应一个栈轨迹元素。将这些栈轨迹元素保存在一个数组中。每个元素对应栈的一个栈帧。数组的第一个元素保存的是栈顶元素,也就是上面的f。最后一个元素保存的栈底元素。
下面是一个使用getStackTrace()访问这些轨迹栈元素并打印输出的例子:
public class TestPrintStackTrace { public static void f() throws Exception{ throw new Exception("出问题啦!"); } public static void g() throws Exception{ f(); } public static void main(String[] args) { try { g(); }catch(Exception e) { e.printStackTrace(); System.out.println("------------------------------"); for(StackTraceElement elem : e.getStackTrace()) { System.out.println(elem); } } } } |
这样的输出和printStackTrace()的输出基本上是一样的,如下:
java.lang.Exception: 出问题啦! at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:6) at TestPrintStackTrace.main(TestPrintStackTrace.java:10) TestPrintStackTrace.f(TestPrintStackTrace.java:3) TestPrintStackTrace.g(TestPrintStackTrace.java:6) TestPrintStackTrace.main(TestPrintStackTrace.java:10) |
数据库同步过程,最严格的指标,第一是效率,即每秒同步SQL条数;其次是一致性,即主库产生的数据,备库同步后是否一致;第三就是数据库同步的完整性如何保证,即当同步各个环节出现问题时,如何考虑出错处理,下面我们将分别进行讨论并进行合理性分析。
第一、效率
数据库同步过程主要分为三个阶段,即抽取、分析、装载。
抽取过程主要是实时读取数据库日志,这部分可以作到毫秒级别间隔,所以不存在效率问题,基本上可以作到实时抽取;
分析过程主要是分析SQL语句并把源日志转化为备库的可装载日志,这部分的主要时间是写文件时间,由于普通硬盘写入时间是50M/秒左右,故对于大交易量情况,如果每秒主库阵列产生日志量上300M/秒左右,那相比之下分析组件还是会有秒级延迟的,因为我们同步软件一般都不安装在主库,无法使用高速阵列的写入速度,所以秒级别延迟还是会产生的,但是只要不是持续高峰日志量的产生速度,再经过一段时间后数据会自行同步,如果要追求实时抽取的同时又要实时分析,那建议只能给同步服务器配置一个阵列了;
装载过程主要是根据分析组件的结果进行备库SQL语句的装载,所以并发装载是提高效率的唯一方法,不过对于备库服务器配置不是很高的情况,建议数据库长连接的数目需要能够合理配置,因为备库有时会作为查询统计的负载分担,所以如果备库的资源有限,对于查询统计分担的效果会大打折扣。
第二、一致性
如何能够保证备库的数据和主库一致,这个问题如果在业务层面提出来,大家肯定没什么好的办法,一个共同的回答就是“查看备库”,用应用去连,之后检查刚刚同步的数据是正确的就可以了,不过这样的抽查很有可能检查不出来特殊错误的数据,我想从几个机制方面来分析这个问题。
1、分析日志(Analysis Log)
就是即将装载到备库的SQL语句,这部分是装载正确的根本,这部分数据如果正确了,则保证了数据源的正确。
2、装载日志(Upload Log)
就是装载数据时是否出现问题,有时备库和主库表定义有不一致,那么在这个日志就会记录出错,根据此日志就能够检查出问题出现在什么地方。
通过以上两个日志基本能保证同步过程中的错误捕捉,同时再加上同步数据检查程序(此数据需要主、备库检查过程中不能更改数据)和应用程序。
连接备库抽查是两个辅助检查方式,同时备库作为查询统计分析进行实时提供服务也会把抽查变成常态,从而保证数据的一致性。
第三、完整性
数据库的完整性,主要从容错机制来考虑,例如出现下面错误情况时需要同步程序能够自动恢复:
1、源库断电或重起
2、源库SHUTDOWN
3、源库网络断
4、备库断电或重起
5、备库SHUTDOWN
6、备库网络断
7、数据库装载出错
针对上面主要几种情况,同步软件必须进行一一考虑断点的记录方式和位置,保证任何情况下同步程序能够续抽、续传,甚至对错误处理也可以通过人为参与后继续同步,同时还有两方面功能必须考虑:
1、不停机初始化
2、日志已经归档
3、自身程序停止的重起
4、同步服务器断电之后断点启动
数据库同步软件只有充分考虑了以上三个方面的指标,才能为行业客户提供优秀的、实时的、数据完整一致的同步产品,满足相关基于数据库同步的业务需求。
当我们插入一条数据的时候,我们很多时候都想立刻获取当前插入的主键值返回以做它用。我们通常的做法有如下几种:
1、先 select max(id) +1 ,然后将+1后的值作为主键插入数据库;
2、使用特定数据库的 auto_increment 特性,在插入数据完成后,使用 select max(id) 获取主键值;
3、对于Oracle,使用 sequence 获取值。
对于以上3种方法都无法绝对保证在高并发情况下的操作的原子性。
现记录以下几种获取数据库主键值方法:
1、数据库原生支持的sql方法:
SQLServer:
INSERT INTO table_name (.....) VALUES(......) SELECT @@IDENTITY AS aliasname; |
上面的语句相当于查询语句,从结果集中使用 getXXX(aliasname) 方法获取主键值。
Oracle:
INSERT INTO table_name(......) VALUES(......) RETURNING[primaryKey INTO]:aliasname; |
也是相当于查询语句,从结果集中使用 getXXX(aliasname) 方法获取主键值。
2、java.sql.Statement 返回键获取:
a: 使用JDBC 3.0提供的 getGeneratedKeys(推荐使用)
Statement stmt = ... ; stmt.executeUpdate("INSERT INTO table_name(......) VALUES(......)", Statement.RETURN_GENERATED_KEYS); ResultSet rs = stmt.getGeneratedKeys(); int keyValue = -1; if (rs.next()) { keyValue = rs.getInt(1); } |
b:使用特定数据库特有的SQL
Statement stmt = ... ; stmt.executeUpdate("INSERT INTO table_name(......) VALUES(......)", Statement.RETURN_GENERATED_KEYS); ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID()"); int keyValue = -1; if (rs.next()) { keyValue = rs.getInt(1); } |
那么现在我就一个例子来看一下原生的sql怎么能得到执行的返回结果
项目背景:数据库是oracle数据库,id生成规则是通过触发器插入数据的时候自动增长,所以在插入数据的时候在sql中就不需要指明id值。但是另外一张表需要引用这个id值作为外键,那么就必须获得被引用的这个表的ID,为了避免并发问题,我们只能在插入前面那张表的时候就获得他的ID,所以我使用了下面的方法来处理。
Connection con = DBConnector.getconecttion(); // 取得一个数据库连接 CallableStatement cst = null; con.setAutoCommit(false); String insertSql = "begin insert into TABLE (field_0,field_1) values (value_0,value_1) returning id into ?;end; "; try { cst = con.prepareCall(insertSql); //执行存储过程 cst.registerOutParameter(1, Types.INTEGER); //为存储过程设定返回值 int count = cst.executeUpdate(); //得到预编译语句更新记录或删除操作的结果 int id = cst.getInt(1); //得到返回值 System.out.println("成功执行了:" + count + "条数据,其ID值:" + id); } catch (SQLException e1) { con.rollback(); con.setAutoCommit(true); }finally{ con.commit(); con.close(); } |
与所有的关系型
数据库一样,
MySQL仿佛是一头让人难以琢磨的怪兽。它会随时停摆,让应用限于停滞,或者让你的业务处于危险之中。
事实上,许多最常见的错误都隐藏在MySQL性能问题的背后。为了确保你的MySQL服务器能够一直处于全速运行的状态,提供持续稳定的性能,杜绝这些错误是非常重要的。然而,这些错误又往往隐藏在工作负载和配置问题之中。
幸运的是,许多MySQL性能问题都有着相似的解决方案,这使得排除故障与调整MySQL成为了一项易于管理的任务。以下就是10个让MySQL发挥最佳性能的技巧。
1、分析工作负载
通过分析工作负载,你能够发现进一步调整中最昂贵的查询。在这种情况下,时间是最重要的东西。因为当你向服务器发出查询指令时,除了如何快速完成查询 外,你很少关注其他的东西。分析工作负载的最佳方式是,使用诸如MySQL Enterprise Monitor的查询分析器,或者Percona Toolkit的pt-query-digest等工具。
这些工具能够捕捉服务器所执行的查询,以降序的方式根据响应时间列出任务列 表。它们会将最昂贵的和最耗时的任务置顶,这样你就能知道自己需要重点关注哪些地方。工作负载分析工具将相似的查询汇聚在一行中,允许管理者查看速度慢的 查询,以及查看速度快但已多次执行的查询。
2、理解四个基本资源
功能性方面,一个数据库服务器需要四个基本资源:CPU、内存、硬盘和网络。如果这四个资源中任何一个性能弱、不稳定或超负载工作,那么就可能导致整个数据库服务器的性能低下。理解基本资源在两个特定的领域中至关重要:选择硬件和排除故障。
在为MySQL选择硬件时,应该确保全部选用性能优异的组件。这些组件相互匹配,彼此间能够实现合理平衡也很重要。通常情况下,企业会为服务器选择速度 快的CPU和硬盘,但是内存却严重不足。在一些案例中,大幅提升性能的最廉价方式是增加内存,尤其是对于那些受制于磁盘读取速度的工作负载。这似乎看起来 有点违背常理,但是在许多案例中,由于没有充足的内存以保存服务器正在使用的数据,因此导致了硬盘被过度使用。
关于获取这种平衡的另一 个例子是CPU。在许多案例中,如果CPU速度快,那么MySQL的性能就非常出色,因为每一个查询都是单线程运行,而无法在CPU间并行运行。在进行故 障排除时,应该检查这四个资源的性能和使用情况,关注它们是否性能低下或是超负荷工作。这方面的知识能够帮助你快速地解决问题。
3、不要将MySQL作为队列使用
队列以及与队列相似的访问方案会在你不知情的情况下悄悄地进入应用之中。例如,你设置了一个项目状态,以便在执行前,特定的Worker Process(工作进程)能够对其进行标记,那么你就等于在无意间创建了一个队列。例如,将电子邮件标记为未发送,然后发送它们,最后再将它们标记为已 发送。
队列会导致出现一些问题,这里面有两大主要原因:它们对工作负载进行了序列化,阻碍任务被并行处理。这导致正在处理中的任务和以前在工作中处理过的历史数据会被根据序列排列在一个表单中。这样一来既增加了应用的延时,也增加了MySQL的负载。
4、以最廉价的方式过滤结果
优化MySQL的最佳方式是首先要做廉价和不精确的工作,然后再小规模地做困难的精确工作,最后再生成数据集。
例如,假设你计算某一个地理坐标点给定半径内的面积。在许多程序员的工具箱里第一个工具就是球面半正矢公式,以计算出球面的长度。这一方法的问题是,该 方程式需要许多三角函数运算,需要拥有很强运算能力的CPU。球面半正矢计算不仅运行速度慢,而且会导致机器CPU的使用率飙升。在使用球面半正矢公式 前,你可以先分解计算。有些分解计算并不需要使用三角函数。
5、弄清两个扩展性死亡陷阱
扩展性可能并不像你认为的那样模糊。实际上,扩展性有着精确的数学定义,它们以方程式的形式被表示出来。这些方程式既指出了系统无法扩展的原因,同时也 指出了它们应该进行扩展的原因。通用扩展定律(Universal Scalability Law)揭示和量化了系统的扩展性特征。其通过两个基础性成本解释了扩展问题:即序列化与串扰(Crosstalk)。
并行处理要求必 须中止序列化,这就限制了它们的扩展性。同样的,如果并行处理需要始终进行彼此对话以协调工作,那么它就相互进行了限制。为了避免序列化与串扰,应用进行 了更好的扩展。这些在MySQL内部被翻译成了什么?结果不尽相同。不过,一些案例应该避免锁定在特定的行之中。就像第3个技巧中所提到的,队列扩展性差 的原因就是如此。
6、不要过分关注配置
数据库管理员会花费许多时间调整配置。调整的结果通常不会有很大的改善,相反有时候会带来损害。我发现许多经过“优化的”服务器,在进行强度稍微高一点的运算时常常出现崩溃、内存不足和性能低下等问题。
虽然MySQL在交付时的默认设置严重过时,但是你并不需要对每一项都进行配置。最好是根据需要,进行基本纠正与设置调整。有10个选项调整正 确,即可让服务器发挥95%的最大性能。在许多案例中,我们并不推荐所谓的调整工具,因为它们只是提供一个大概设置,对特定案例没有任何意义。有些工具甚 至包含有危险的和错误的设备代码。
7、注意分页查询
分页查询应用会使服务器性能大降。这些应用会在网页上显示搜索结果,然后通过链接跳转至相应网页上。通常这些应用无法使用索引进行聚合与分类, 而是使用LIMIT和OFFSET语句,这导致服务器工作负载大幅增加,并放弃行。 在用户界面上常常会发现优化选项。替代在结果中显示网页数量,以及分别与每个网页相连的链接。这样便可以仅显示至下一页的链接。你还可以阻止查询者浏览与 首页过远的网页。
8、保存统计数据,提高报警阀值
监控与报警必不可少,但是监控系统被怎么处理了呢?当它们发布假的报警信息时,系统管理员会设置电子邮件过滤规则,以停止这些噪音。很快你的监 控系统就彻底没用了。个人认为,应该以下面的两种方式进行监控:捕捉指标与报警。尽可能地捕捉与保存指标非常重要,因为在你试图搞明白系统中需要做哪些调 整时,你会庆幸之前保存了它们。如果某一天出现奇怪问题时,你会很高兴自己有能力绘制出服务器工作负载变化的图形。
9、了解索引的三大规则
索引可能是数据库中被误解最多的一项。因为它们的工作方式有许多种,这导致人们常常对索引如何工作,以及服务器如何使用它们感到困惑。要想彻底搞清楚它们需要花上很大一番功夫。在被正确设计时,索引在数据库中主要用于实现以下三个重要目的:
1)它们让服务器寻找相邻行群组,而不是单个行。许多人认为,索引的目的是寻找单个行,但是寻找单个行会导致随时磁盘操作,速度很慢。寻找行群组就要好许多,与一次寻找一个行相比,这更具吸引力。
2)它们让服务器避免以期望的读行顺序对检索结果排序,排序成本十分高昂。以期望的顺序读行速度将更快。
3)它们能够满足来自一个索引的所有查询,从根本上避免了访问表单的需求。这被称为覆盖索引或索引查询。
如果你能设计出符合这三个规则的索引与查询,那么你的查询速度将大幅提升。
10、利用同行的专业知识
不要孤军奋战。如果你在苦苦思考某个问题,并着手制订明智的解决方案,那么这非常不错。在20次中,有19次问题会被顺利解决。但是其中会有一次让你不知所措,导致耗费大量的资金和时间,准确地说,是因为你正在尝试的解决方案只是貌似合理。
创建一个MySQL相关资源网的意义远远大于工具集与故障排除指南。许多经验丰富的专业人员就隐藏在论坛、问答网站之中。会议、展览以及本地用户集体活动,都会为我们提供获得新见解的机会和与同行建立联系的机会,关键时刻这将对你很有帮助。
要想回答这个问题,首先要搞明白另外一个问题。那就是自动化是什么?
首先回答自动化是什么?常见的答案:自动化就是写代码。如果是写代码,那与软件开发有什么区别。要想回答这个问题前提是代码是什么。代码就是人的知识与逻辑思维的一种固化方式。软件本身就是人们为解决某一问题所需要知识与做事的处理流程的固化。而测试脚本是人们测试逻辑思维的固化。一旦把知识与逻辑思维固化下来后,就相当于建立一种制度。
自动化能提高效率吗,是不可以换一种方式问,制度能不能不效率?这样一问,大家自然也就明白了,制度不一定能提高效率。只有一个好的制度才能效率。因为有了制度之后,人们的就会受制于制度,缺乏了灵活度。就像上一篇文章的自动化测试三 个发展阶段:依赖工具阶段,依赖人的阶段,依赖架构阶段。过第一阶段之后,这种感觉越明显。严重的话,会出现测试绑架开发的情况。例如软件想进行重构,但 会引起接口的变化,而接口的改变,测试脚本就要跟着改了并且改动一般都不会是一比一关系,而是一比N(这个N有多大,就看测试case设计的合理性而定 了)。如果测试改动量特别大,可能会迫使软件放弃重构。就违背了做自动化的初衷了。
现在流行的敏捷开发模式,代码重构会贯穿于整个开发流程,同样自动测试是保证敏捷顺利进行一个不可或缺的基石。没有自动化,就不可能快速持续集成。
所以,成也自动化测试,败也自动化测试。是成是败就要看自动化框架的设计。
你强化过你的文件服务器了吗?按照以下方法,可以充分保护你的重要文件,阻止未经授权的入侵。
现在把你公司有价值的机密信息存放在一个或者多个windows文件服务器上,是一个非常安全的做法。可能不太明显的是,你不知道强化的程度和保护数据防止非法入侵的范围。
如果你不知道从哪入手的话,没关系只要按照以下通过实践得出的十个最佳方法去做就行了:
第一招:确保您的服务器在物理层面上是安全的。
如果入侵者可以物理访问你的服务器,那么你将会有被带走整个机器或者一个硬盘的风险。除了要确保物理安全之外,你还应该配置你的系统,让它只从硬盘内部来引导,防止入侵者从可移动的介质来启动系统。BIOS和引导加载程序,都应该设置一个强大的密码来进行保护。
第二招:加密你的驱动器。
使用类似于BitLocker系统来加密你的驱动器,这样即使你的硬盘被盗或者被替换后扔到不安全的地方,仍能确保你的文件是安全的。在你的服务器上使用可信赖平台模块(TPM)确保使用BitLocker在管理员和用户之间是公开透明的。
第三招:尽可能的让服务器远离网络。
由于大多数文件服务器都无法避免的要连接到互联网,所以使用防火墙限制外部访问你的局域网。
第四招:确保服务器更新了最新最全的补丁。
即使你的Windows服务器没有连接互联网,你仍然要保证软件的更新,通过在你网络上的另一个服务器运行Windows服务器更新服务(WSUS)来 完成。如果让你的文件服务器,不联网是不实际的话,那么你应该确保Windows更新设置为自动下载并应用补丁 - 除非你已经有了一套下载和手动测试补丁的程序。
还有一个容易遗漏的地方就是IE浏览器的增强安全配置,因为很少会用到IE浏览器所以IE浏览器的安全往往会被忽略。你可以从控制面板查看互联网增强的安全配置选项,添加Windows部分组件。
第五招:不要忘了防病毒软件。
即使你有网关的安全保护,也运行了个人的防病毒软件,但你仍应该运行企业级的防病毒软件在你的文件服务器上。大多数企业的产品,允许你从本地服务器更新 病毒数据(甚至是从你网络上其他用户运行的软件上),但如果你的文件服务器没有联网的话,那么你可能无法充分利用基于网络提供的额外保护。
第六招:去掉不必要的软件。
在你服务器上的那些肯定不需要的软件如Flash,Silverlight,或Java。安装这些软件只会给黑客增加攻击的机会。你可以从服务器中删除没用的控制面板。
第七招:停止不必要的服务。
在Windows中,除非你特别需要这些(像远程管理),否则你应该停止像传真服务,Messenger、IIS Admin、SMTP、任务调度器、Telnet、远程桌面服务、万维网发布服务等。
第八招:控制文件的访问。
您可以使用NTFS安全限制文件和文件夹访问特定的组或个人用户。你可以通过查看一个文件或文件夹的属性,选择“安全选项卡”,然后在“高级”里改变权限。
第九招:使用审计功能。
确保你设置了审计,这样你可以看到是谁曾尝试读取、写入或删除你的机密文件或文件夹。你可以通过查看一个文件或文件夹的属性,选择“安全选项卡”,然后在“高级”设置里选择“审核”选项卡来完成。
第十招:使用最少的特权执行管理任务。
尽可能的避开使用管理员特权。同样,确保具有管理员权限的所有帐户,即使有密码策略也要强制执行强密码保护。
1、现状分析 如今,国内浏览器市场竞争激烈,国外优秀的浏览器如Microsoft的Internet Explorer(下简称:IE)、Mozilla的Firefox、Google的Chrome、基于Apple Mac OS的Safari,以及号称世界最快浏览器的挪威Opera等,占大量的国内市场份额。如IE浏览器,由于在国内引进互联网初期就被大众熟悉,且很多银行、游戏类应用均需要其内核的支持,因此仍拥有大批热衷者;Firefox、Chrome和Opera,由于其独特的分页浏览和极具个性的定制设置,也吸引了大量用户;Safari更是由于Apple系列产品的风靡全球被大家熟知和使用。
国产浏览器如Sogou、遨游Maxthon、世界之窗TheWorld,百度浏 览器、360安全浏览器等,虽然近年来发展迅猛,并且更符合国人的使用特点,逐渐被大众接受,但是市场份额仍然很低,距国内权威的流量统计技术服务提供商 CNZZ最新统计,国产浏览器市场份额仍不足40%。因此,大力发展国产浏览器,着重提高其标准支持和性能的能力,逐渐掌握市场主动权仍然是国产浏览器厂 商需要迫切解决的问题。
2、测试依据
本文基于某核高基重大专项课题验收要求中的部分内容,对某互联网公司自行开发的浏览器的性能测试方法进行了研究(为避免引起不必要的纠纷,课题名称及承担单位名称在此均未描述,待测试的浏览器下文简称A浏览器),通过测试考察其实际运行性能,并与主流的浏览器IE、Firefox和Chrome进行了性能对比。
本次测试是在实验室模拟环境下展开的。为保证测试执行过程的公平、公正,本次测试的外部条件是一致的,这包括环境和输入条件一致。每款浏览器测试完成后,直接更换部署下一套浏览器产品,测试设备、网络环境、操作系统版本和设置均保持一致。
3、测试内容
本次浏览器性能对比测试,需要考察浏览器的启动、资源消耗、门户网站访问、大页面加载速度等,主要与测试设备硬件CPU、内存、操作系统以及浏览器自身 的版本和设置有关,与网速、Flash插件等无关。选择的版本分别是:IE8.0、Firefox9.0.1、Chrome17.0.963.6和A浏览 器1.4。
3.1 资源占用
资源争用常常是导致应用性能降低的重要因素,浏览器 对资源的控制将严重影响用户的访问速度体验,因此需要考察各浏览器安装完成后,在默认配置下初次冷启动不加载页面运行时,消耗测试设备CPU、内存和磁盘 空间大小的情况。由于内存消耗值的是动态变化的,在实际测试中采用3次启停测试设备,通过测试进行信息提取,再统计3次取值的平均值获得。由于CPU消耗 情况均小于1%,因此仅列出内存和磁盘测试对比结果。
从测试结果可以看出,国产A浏览器在内存和磁盘消耗测试中,均排名第3,但是内存的消耗和默认加载的控件有关,磁盘的消耗和程序包的大小有关,因此仍有提升的空间。
3.2 启动测试
启动测试项主要考察冷启动和热启动模式下打开浏览器访问保存在本地的带有文字、图片和Flash的测试页面的响应时间。
冷启动指无缓存情况下开机后第一次打开浏览器进行访问,而热启动指测试设备启动后至少运行过一次浏览器访问操作,再次打开浏览器进行访问。
在测试过程中,为方便统计响应时间,采用了功能测试工具QuickTestPeofesstional来协助完成。通过测试工具录制打开浏览器访问本地测试文件的操作,然后循环执行十次取平均值获得操作执行的响应时间。脚本主要内容如下:
…… Services.StartTransaction "click" //定义一个事务点开始 Window("A浏览器").WinObject("Aricheditcontrol").Click 85,10 //打开浏览器主窗口 For i=1 to 10 //设置10次循环 Window("A浏览器").WinObject("WebViewWindowClass").Type “localhost:8001/test.html” //键入本地文件访问地址 wait(5) // 设置5秒等待时间 Window("A浏览器").WinObject("WebViewWindowClass").Click 1225,252 //打开网页中的连接 Window("A浏览器").WinObject("WebViewWindowClass").Click 1265,248 //打开网页中的图片 Window("A浏览器”).WinObject(“WebViewWindowClass”). Check CheckPoint("WebViewWindowClass") //设置检查点 Services.EndTransaction "click" //定义一个事务结束 Window("A浏览器").Activate Window("A浏览器").Click 1415,7 //关闭浏览器 Next |
测试结果如下:
从测试结果对比图可以看出,国产A浏览器在冷启动和热启动测试中,均排名第二,表现出了不错的启动速度,IE浏览器由于与操作系统同出一家的关系,排名第一;而Firefox和Chrome由于与较多的控件进行绑定,因此启动速度较慢。
3.3 标签页载入速度测试
本项内容主要考察浏览器载入主流的门户网站、搜索引擎网站等用户访问率高的网站时的速度,访问时间的记录主要通过秒表的方式进行统计,为避免结果失真,均采用取3次测试结果平均值的方式获得。测试结果如下:
总体来看,Firefox和Chrome浏览器访问门户网站时速度占优,A浏览器居后,IE8.0则响应较慢。
3.4 标准页面加载测试
本项采用权威的网站http://nontroppo.org/timer/进行测试,主要考核指标如下:
First Access:第一次加载并显示Dom元素的时间;
Doc load:文本加载的时间;
Doc+Image Load:包括Css、JavaScript以及11张图片的加载时间;
以上加载时间均越小代表浏览器处理越快,测试结果如下:
字体: 小 中 大 | 上一篇 下一篇 | 打印 | 我要投稿
3.5 硬件加速
许多浏览器为加快2D、3D的渲染,采用具有多线程能力的GPU的缓存合成技术来处理图像合成、缩放、三维特效处理 等操作,这种在显示芯片内的处理提高了网页的访问速度。本项测试采用著名的“海底世界”测试工具来完成,考察设置显示的鱼的条数为1、10、50、100 和500时,浏览器的硬件加速能力,通过每秒帧数来能量测试结果,帧越大,硬件加速能力越强。以下图表中的结果均是在测试过程中测试工具在平稳阶段显示的 每秒帧数。由于IE8.0不支持硬件加速功能,因此仅对Firefox、Firefox和A浏览器进行测试。
从测试结果得知,A浏览器在5项测试中均获得头名,但其硬件加速的能力相比Firefox和Chrome优势较小,还需继续改进,提升优势。
4、测试总结
相比于世界著名的浏览器产品,国产A浏览器由于刚起步不久,用户群较少,但是其性能表现在本次测试中并未完全处于下风,仍有许多值得称赞的地方。相信随着用户群的增长,会加速A浏览器的发展和优化,最终能和世界知名的浏览器相抗衡。
另外需说明,本次测试是在实验室环境下进行,不同的平台环境和其它因素会导致测试结果大不相同,因此本次测试的结果数据仅用作参考,不作其它用途。
在最近的统计中,
苹果应用商店中共有超过500,000种应用,而且
Android市场也有超过了300,000种应用,这些还不包括其他平台上的应用,像RIM Playbook、Microsoft
Windows Phone和Windows Mobile。此外,每一个平台都可以为各种设备出售各种
操作系统版本。开发应用需要在这些各种型号和操作系统版本的组合上
测试和验证程序。自动化移动应用测试是唯一的发布时间表可以维持的方式。下面,我们探讨一下
自动化测试移动应用程序所面临的挑战。
下面是移动应用的自动化测试挑战:
自动化脚本需求:自动化脚本需求在一个应用程序发布、正在被使用,和随后需要推出更新时更为紧迫。所有现存的特点需要每次推出更新时被测试,要确保在升级代码的时候没有回归误差。同时,各种各样的造型和模型,特别是像Android平台、自动化脚本、测试就不可避免。
多种语言和环境脚本:企业中通常采用将测试脚本可能需要综合回到语言和测试环境中,像JUnit、QTP、PERL或者Python。
分布式测试:越来越多的移动测试外包出去,甚至是海外外包。开发人员和测试人员可能地理上是分离的。测试环境下可能需要处理全世界许多地方的多个时区,或者使用不同的当地电信服务供应商。测试环境可能需要24/7/365和互联网/浏览器访问可用。
发布自动化错误和崩溃跟踪:一两个崩溃之后,用户就会放弃移动应用,甚至可能将其删除。移动应用可能需要在内部测试模式一段时期后,才第一次在应用商店发布。自动化测试工具可能需要监测和跟踪错误和崩溃,这些可能在正式的测试时遗漏掉了,即使在一个正式的发布之后。
测试设备登记管理:测试设备登记,特别是对于iOS设备,是一件苦差事,个人电话ID可能需要在苹果网站上注册。安装包需要以电子邮件的形式发送给测试人员进行安装和测试。自动化测试工具平稳并自动化地管理注册,让这个过程高效和有效。
多个电话模型可用性:打开移动操作系统,如:Android有一大批制造商直销运行着不同版本操作系统的移动设备。在这种情况下,移动应用测试要求种类繁多的设备制造商和模型可用,用以完成可靠的验证和认证。
模拟器处理器缺陷:手机模拟器,用笔记本电脑或者台式电脑运行时可以使用其他的处理器,移动设备上只能使用一个处理器。为了完成可靠的测试,自动化测试需要在实际的电话上操作,而不只是模拟器。
远程响应测试:移动应用在手机上可以独立的,或者通过后端服务器在执行期间频繁访问。后者中,从多个地理位置进行远程测试可能需要成为自动化测试的一部分。这是为了确保应用不论在哪里使用,其响应时间是合理的。