新建一个服务端项目:
1、定义一个接口如下:
/** * 定义webservices接口 * @author Administrator * */ @WebService public interface IHelloService { public String sayHello(String name); public User getUser(User user); } |
2.实现接口
/** * 实现webservices接口 * @author Administrator * */endpointInterface 实现的接口类 @WebService(endpointInterface="com.chni.webservies.IHelloService") public class HelloServiceImpl implements IHelloService { public User getUser(User user) { // TODO Auto-generated method stub return null; } public String sayHello(String name) { // TODO Auto-generated method stub return name; } } |
3、启动服务(执行下列main函数)
public class TestService { public static void main(String[] args) { //服务地址 String address="http://localhost:8989/u"; Endpoint.publish(address, new HelloServiceImpl()); } } |
4、在浏览器上输入:http://127.0.0.1:8989/u?wsdl 看到以下信息:
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><definitions targetNamespace="http://impl.webservies.chni.com/" name="HelloServiceImplService"><import namespace="http://webservies.chni.com/" location="http://127.0.0.1:8989/u?wsdl=1"/><binding name="HelloServiceImplPortBinding" type="ns1:IHelloService"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="getUser"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="sayHello"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation></binding><service name="HelloServiceImplService"><port name="HelloServiceImplPort" binding="tns:HelloServiceImplPortBinding"><soap:address location="http://127.0.0.1:8989/u"/></port></service></definitions> |
5、新建一个客户端项目
6、在dos命令中使用 如下:d:\ws>wsimport -s . -p com.test.service http://127.0.0.1:8989/u?wsdl 表示意思是:在d盘有个ws文件夹 使用wsimport命令 -s生成客户端源码 -p 指定包名为com.test.service 后面为service 服务地址
dos界面如下:
好了你现在去你的d盘ws文件夹下的com这个文件夹考到新建客户端项目的src目录下
7、新建一个java测试类如下:
public class TestMail { public static void main(String[] args) { //建立客户端(HelloServiceImplService 这个往什么地方来的去分析一下wsdl文件中有个service name=“new的这个HelloServiceImplService类”)建议还是去网上看看 IHelloService cilent=new HelloServiceImplService().getHelloServiceImplPort(); String abc=cilent.sayHello("XXX"); System.out.println(abc); } } |
输出的值为XXX 说明这个webservice搭建成功了 哈哈
一个良好的
自动化测试框架应该具备灵活的,与应用程序无关的,与技术无关和不过时的特点。本文强调的准则可以帮助开发者深层分析测试方案中的代码。这种能力已经被证明在多个自动化项目上是有效的。
“自动化框架”这个术语已经为
软件测试领域所熟知。尽管很多人都把它与应用在基于UI自动化的技术联系起来,但是它几乎总是被滥用于那些参与测试领域。这大部分的原因是由于大家对自动化框架的应用领域有误解。它应该不仅仅像Coded UI那样,只是一个单纯的UI技术。
现在,市场上有很多商业性的和开源的测试自动化框架。使用这些框架的主要问题在于调整他们的
学习曲线和满足自动化项目的要求的困难性。虽然有一些广泛应用的遗留框架,但是他们还是有很多缺点。
他们缺乏灵活性,再使用昂贵的第三方产品——或者,添加一个单纯的现有用户界面技术,但不提供额外的价值。
一个良好的自动化测试框架应该具备灵活的,与应用程序无关的,与技术无关和不过时的特点。它应该支持一个易于安装和使用的结构化和模块化的编程模型。说“易于使用”,我们是假设和期望用户是有经验的
软件开发人员。自动化是发展和正确的软件工程技能,对于计划和成功得实施一套自动化是有需要的。
开发一个基于UI功能自动化系统背后的想法是,运用这一框架来提高代码的可重用性、稳定性和可维护性。该代码应该是容易编写、调试、部署和运行,发生失败应该易于分析。不管你使用Ranorex,Coded UI,Telerik或
Selenium 作为底层自动化技术,设计和实现自动化的解决方案都应该是相同的。我们选择去建议和实施的范式和模式是任何开发项目的最佳实践,但他们对于UI自动化尤其有用。
我们已经在外面公司对几个不同的项目创建了自动化框架。在一些类似的模式中,我们可以提取其中的相同之处。这些项目的主要问题与方法和可重用性的不同相关。除此之外,不同的团队通过使用不同的自动化工具来测试应用程序功能,这也导致了整体的难度。
一般来说,一个自动化框架可以被定义为一套可以为自动化软件测试提供支持的假设、概念和工具。它有以下的功能:
﹒定义自动化测试脚本的方法
﹒提供建立联系机制SUT(测试系统)
﹒执行测试和报告结果
﹒减少自动化项目启动时间
﹒建立一个共同的标准
基本原则
让我们假设我们有一个具有丰富的用户界面和大量的控制的复杂的应用程序,但它只有两个屏幕。应用程序是复杂的事实可能意味着它可以有几十个手动
功能测试例子。所有这些使用相同的两个屏幕。那么,我们怎样才能增加这样的测试解决方案的可维护性
分层架构模式
把软件系统体系结构分解为单独的一层的想法是非常普遍的。第一个是逻辑展示层面,,第二个是业务逻辑层面,第三个层次是负责数据存储。使用这种模式可以降低应用程序的维护成本从每一层内的组件可以改变而不影响其他的水平。同样的方法可以应用于测试系统。
测试代码可以分为三层:
·为UI自动化工具访问被测系统的接口层
·逻辑功能层
每一层执行某项任务时都有一个降低测试的费用维护和促进创造一个新的测试的共同的目标。
图1:架构原型,测试系统的多层体系结构
Page Object
根据每个单独的测试案例来创建单独的测试逻辑、业务库和UI Map,为我们提供了特殊能力来修改当前测试用例。
让我们假设我们的应用程序是web邮件服务Gmail,并且两个屏幕之一是登录屏幕。登录流程被所有测试用例中所使用。(例如,为了得到第二个屏幕,您需要执行首先登录到应用程序)。
图2:谷歌邮件登录
让我们假定UI中有一些东西改变了,但是不合逻辑的。在我们的特定情况下,每个登录进入Gmail的现在需要输入验证码。
图3:谷歌邮件登录与验证码
这意味着每个测试案例现在应该更新为新的登录流程。但是一般来说,这只符合逻辑地更新一段代码。此时Page Object和功能方法模式的作用就显而易见。如果只有一个页面对象宣布登录屏幕和一个登录方法,只需要两个参数(即登录名和密码),然后只有身体的登录功能方法需要更新,以涵盖所有情况下与这种变化有关。
页面的无缝衔接
页面的无缝衔接的实现背后的想法是,在页面对象的所有方法返回另一个页面对象类实例(下一个SUT上下文页面)。例如,登录方法在我们的样例返回主应用程序默认的屏幕。它使一系列步骤的功能测试用例编写一个接一个,使这种用方法去链接。因此,业务方法本身就能够通过IDE的智能感知,为测试脚本的开发人员的代码提出建议。
面向切面编程
面向切面编程实现方面似乎是很有价值的,特别是如果你需要用特定方法到try-catch块,或写报告日志条目进入/退出方法。这种方式,包含面向切面实现方面有助于提高自动化代码,使它更具可读性和可以理解的。
构建/运行时验证
自动化框架也经常建议企业标准。大多数开发人员常将同样的自动化方案应用在不同的项目上,这是一个十分棘手的问题。所以,自动化框架可以提供一系列设施,去验证在商业程序库或者功能测试中的方法是否是最佳方案。
有不同的方法可进行验证:
·使用IDE扩展/插件等可能设置自定义构建的规则(例如:ReSharper, StyleCop for Visual Studio)
·编写自己的ID扩展名
·编写一个机制,可以验证测试是否包含预期的属性在运行,如果有什么不正确的在运行,它将因描述性的错误而失败。
以下提供一些可被验证的项目的简单列表:
·测试脚本的命名
·有适当的注释/描述
·业务方法的返回值/参数
·解决方案分层 (确认不会有交叉层次访问冲突在自动化代码中出现)。
·自动化测试框架的硬件支持
显然,该框架不能只包括最佳实践。没有人能够在没有任何基础设施来支持他们的情况下继续做下去。以下提供的是一些有助于更好的理解自动化框架实现的指引。
首先我们需要以某种方式运行测试。在大多数情况下,单元测试框架是用于运行功能测试和衡量结果。有了各种技术/语言的支持,能够为功能测试代码和持续集成(CI)系统完美的结合提供了多种选择的单元测试框架。
为测试运行加载配置
测试配置很大程度上取决于SUT域和测试细节。例如,在大多数测试流的所有配置(如参数、远程连接服务器等)可以只是在测试脚本中写死的。
在数据驱动的测试中, 当相同的测试可以使用不同的配置(例如,输入参数)多次运行的情况下,单元测试框架还提供从外部存储设备读取数据测试脚本。
因此,如果需要自定义配置加载的实现你的自动化框架的话,您需要仔细反复检查。
报告测试结果
报告测试结果/调试测试信息是自动化框架的最重要的功能之一。
有以下几个原因:
﹒报告分析简化了测试应用程序/故障排除,所以你的报告的信息越多,它提供的支持越好。
﹒报告是所有的项目经手人观察到的结果。
如果你想跟踪测试执行在一段时间内的一些动态变化,你应该运用额外的设备将测试结果永久地保存到数据库,这样就可以作比较。
别忘了把一些花俏的东西放进报告表示层(xml / html),如公司标志、结构化输出等。这些事情能够极大地改善你的管理。如果你提供一个“时间”报告,图表也需要高度重视。
验证
再者,大多数单元测试框架已经有一套支持在测试脚本中执行Assert/Verify的机制。这是一个很好创建自己的验证机制的实践,以便:
﹒从一个特定的单元测试框架中抽象用例断言
﹒为你的需求定制一套验证方法
﹒添加特定的逻辑到您的验证方法,让您的验证结果自动写入报告
切面
自动化测试解决方案在不同的项目中大多是类似的。所以为现有解决方案增加自动化框架工具应该是个简单的事情。如果你想为现有项目提供更多实用价值,使用框架来减少迁移工作是很重要的。
这方面确实很有帮助。只需添加一个方面属性定义到一个测试项目,一会儿你就会有一个广泛的报告机制在您的测试解决方案中激活!当然,它的实现需要一些高级方面,但这绝对是值得的。
关键词
你可能觉得有趣的是,我们在这篇文章中没有提及任何关键字驱动框架。关键字市场另一组可用的解决方案,包括商业的和开源的。可以肯定的是,已经有成百上千的自定义关键字驱动框架存在。但是,我们发现他们是并不完整的。原因如下:
﹒他们没有解决测试脚本的可维护性。他们中的大多数介绍是大量重复的。
﹒把关键字驱动框架紧密地绑定到特定的自动化工具(或者是一个UI自动化工具)的一部分,这使得在解决方案开发没有变化。
结论
在本文中,我们描述了我们在自动化框架的实现中的一些经验。这篇文章强调的一些原则可以提供在深度上分析测试方案的代码的能力,并被证明在多个自动化项目中是有效的。作为一个例子,其中一个我们已经开发了大约500个业务场景与110个测试用例,每个测试用例平均30步骤(请注意,一步也可以由几个业务方法调用)。所描述的方法使我们能够达到每一个业务场景36倍的平均可重用性。
这是由你来决定你的自动化项目使用什么框架。也许这将是一个简单的记录/回放页面工具与一群或者是一组关键字驱动脚本的表格。但是,当涉及到自动化的一百多的测试用例时,您需要证明较高的成熟度级别来实现您的测试解决方案的可维护性。
Oleksandr Reminnyi作为SoftServe Inc的软件工程师,SoftServe Inc是一家全球领先的外包产品和应用开发公司。Oleksandr Reminnyi负责为新的和现有的客户建立自动化项目和流程。他认为,成功和失败是完全取决于自动化建立过程是否设定正确的目标。他目前正在他的博士学位致力于研究自动化。
David Krauss拥有超过30年的应用经验和产品设计和交付,与广泛的编程和跨多个平台架构经验,技术,和语言。精通遗留资产现代化,全球协作开发过程,客户机/服务器和网络平台,测试自动化(一个专利自动化,自动化生成一个专利申请中)。二十多年专业从事自动化测试工具和范例,自动化框架和测试方法。
下载,安装,省略,直接上demo源码
===========linux运行gtest=================
----------------code.cpp------------------- #include "code.h" int f( int a ){ return a+1;} int b( int b ){ return b+2;} ----------------code_test.cpp------------------- #include "code.h" #include <gtest/gtest.h> TEST( TEST_A,NAME ){//TEST_A 是 测试用例名称, NAME 是测试名称 EXPECT_EQ( 2,f( 1 ) );//这个测试执行函数f,参数为1,查看返回值是不是2 EXPECT_EQ( 3,f( 2 ) ); } TEST( TEST_B,NAME ){ EXPECT_EQ( 4,b( 2 ) ); } ----------------main_test.cpp------------------- #include <gtest/gtest.h #include <iostream> int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ----------------运行-------------------------- gcc $(gtest-config --ldflags --libs) -o main_test code.cpp code_test.cpp main_test.cpp -I /home/sosotest/include -lgtest -L /home/sosotest/lib ----------------运行-------------------------- ./main_test [==========] Running 4 tests from 4 test cases. [----------] Global test environment set-up. [----------] 1 test from TEST_A [ RUN ] TEST_A.NAME [ OK ] TEST_A.NAME (0 ms) [----------] 1 test from TEST_A (0 ms total) [----------] 1 test from TEST_B [ RUN ] TEST_B.NAME [ OK ] TEST_B.NAME (0 ms) [----------] 1 test from TEST_B (0 ms total) [----------] Global test environment tear-down [==========] 2 tests from 2 test cases ran. (0 ms total) [ PASSED ] 2 tests. |
===========windows运行gtest=================
STEP1: 下载cygwin安装,默认在c:\cygwin
STEP2: 下载gtest1.6,解压并拷贝到cygwin的目录下,即c:\cygwin的某个子目录下
STEP3: hack src/gtest.cc:808行的gettimeofday(window没有这个函数,参考http://blog.chinaunix.net/uid-140978-id-3029195.html)
替换 :gettimeofday(&now, NULL);
替换成:
FILETIME ft;
long long *time64 = (long long *) &ft;
GetSystemTimeAsFileTime (&ft);
*time64 -= 116444736000000000LL;
*time64 /= 10;
now.tv_sec = *time64 / 1000000;
now.tv_usec = *time64 % 1000000;
STEP4: 进入make子目录,去掉Makefile中的最后一行的 -lpthread(window无pthread库)
STEP5: 执行make,生成并运行sample1_unittest.exe,截图略
如何创建存储过程
go create procedure testname(存储过程名称) @test1 int, @test2 nvarchar(50) as insert into testtable values(@test1,@test2) return //select * from users where truename like '%[王刘]%' //只能分词查询,查询姓刘和姓王的信息 2 如何使用 public string[] TestLogin(string uname, string upwd) { try { SqlCommand cmd = new SqlCommand(); cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "User_Login";//存储过程名 cmd.Connection = conn; cmd.Parameters.Clear(); cmd.Parameters.Add("@uname", SqlDbType.NVarChar, 100).Value = uname; cmd.Parameters.Add("@upwd", SqlDbType.NVarChar, 100).Value = upwd; string[] result = new string[3]; conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.Read()) { result[0] = dr["qx"].ToString(); result[1] = dr["tname"].ToString(); result[2] = dr["unitid"].ToString(); dr.Close(); return result; } else { return null; } } catch (Exception e) { throw e; } finally { conn.Close(); } } |
在 Java 程序的开发过程中,不可避免地会遇到内存使用、性能瓶颈等问题。Java Profiler 工具能帮助开发人员快速、有效地定位这些问题,因此成为了 Java 开发过程中的一个重要工具。目前市场上的 Java Profiler 工具种类繁多,本文将对目前比较常见的几种工具进行简要介绍,并从功能、性能等角度作比较,从而帮助 Java 程序员选择合适的 Java Profiler 工具。
本文主要分为三个部分:第一部分简要介绍 Java Profiler 工具的原理;第二部分对目前常见的 Java Profiler 工具 TPTP, CodePro Profiler, YourKit Java Profiler, JProfiler 进行简要介绍;第三部分对以上工具从不同的角度进行比较,帮助开发人员选择合适的工具。
相对于静态代码分析,Profiling 是通过收集程序运行时的信息来研究程序行为的动态分析方法。其目的在于定位程序需要被优化的部分,从而提高程序的运行速度或是内存使用效率。收集程序运行时信息的方法主要有以下三种:
事件方法:对于 Java,可以采用 JVMTI(JVM Tools Interface)API 来捕捉诸如方法调用、类载入、类卸载、进入 / 离开线程等事件,然后基于这些事件进行程序行为的分析。
统计抽样方法(sampling): 该方法每隔一段时间调用系统中断,然后收集当前的调用栈(call stack)信息,记录调用栈中出现的函数及这些函数的调用结构,基于这些信息得到函数的调用关系图及每个函数的 CPU 使用信息。由于调用栈的信息是每隔一段时间来获取的,因此不是非常精确的,但由于该方法对目标程序的干涉比较少,目标程序的运行速度几乎不受影响。
植入附加指令方法(BCI): 该方法在目标程序中插入指令代码,这些指令代码将记录 profiling 所需的信息,包括运行时间、计数器的值等,从而给出一个较为精确的内存使用情况、函数调用关系及函数的 CPU 使用信息。该方法对程序执行速度会有一定的影响,因此给出的程序执行时间有可能不准确。但是该方法在统计程序的运行轨迹方面有一定的优势。
目前市面上的 Java Profiler 工具采用的信息收集方法通常是以上三种方法的任意组合。
Profiler 工具功能简介
虽然市场上的 Java Profiler 工具有不少,但是基本功能大多相似,本节首先对这些基本功能进行介绍。
遥测(Telemetry):遥测是一种用来查看应用程序运行行为的最简单的方法。通常会有多个视图(View)分别实时地显示 CPU 使用情况、内存使用情况、线程状态以及其他一些有用的信息,以便用户能很快地发现问题的关键所在。
CPU Telemetry 视图一般用于显示整个应用程序的 CPU 使用情况,有些工具还能显示应用程序中每个线程的 CPU 使用情况。
Memory Telemetry 视图一般用于显示堆内存和非堆内存的分配和使用情况。
Garbage Collection Telemetry 视图显示了 JVM 中垃圾收集器的详细信息。
Threads Telemetry 视图一般用于显示当前运行线程的个数、守护进程的个数等信息。
Classes Telemetry 视图一般用于显示已经载入和还没有载入的类的数量。
快照(snapshot):应用程序启动后,profiler 工具开始收集各种执行数据,其中一些数据直接显示在遥测视图中,而另外大部分数据被保存在内部,直到用户要求获取快照,基于这些保存的数据的统计信息才被 显示出来。快照包含了应用程序在一段时间内的执行信息,通常有两种类型的快照:CPU 快照和内存快照。
CPU 快照主要包含了应用程序中函数的调用关系及运行时间,这些信息通常可以在 CPU 快照视图中进行查看。
内存快照则主要包含了内存的分配和使用情况、载入的所有类、存在的对象信息及对象间的引用关系。这些信息通常可以在内存快照视图中进行查看。
CPU Profiling:CPU Profiling 的主要目的是统计函数的调用情况及执行时间,或者更简单的情况就是统计应用程序的 CPU 使用情况。通常有两种方式来显示 CPU Profiling 结果:CPU 遥测和 CPU 快照。
内存 Profiling:内存 Profiling 的主要目的是通过统计内存使用情况检测可能存在的内存泄露问题及确定优化内存使用的方向。通常有两种方式来显示内存 Profiling 结果:内存遥测和内存快照
线程 Profiling:线程 Profiling 主要用于在多线程应用程序中确定内存的问题所在。 一般包括三个方面的信息:
某个线程的状态变化情况
死锁情况
某个线程在线程生命期内状态的分布情况
Profiling 的启动设置:类似于 eclipse 中 Run 和 Debug 的启动设置,进行 Profiling 之前也需要进行启动设置,包括:profiling 的模式 (CPU profiling 或内存 profiling),信息获取类型(遥测 , 抽样统计或者 BCI ) 等等。
Profiler Preference 设置:主要用于 Profiler 过滤器(选择需要关注的包、类)、取样间隔时间的设置等。
Java Profiler 工具介绍
本文接下来将对目前市场上常见的几种 Java Profiler 工具进行介绍。TPTP
TPTP(Test and Performance Tools Platform)是 eclipse 官方的 Profiling 工具插件。TPTP 提供了诸如测试,追踪(trace),性能测试,图形界面性能分析等功能。同时 TPTP 还是一个可扩展的开发平台框架,你可以对它加以扩展集成到你自己的产品中。TPTP 可以通过 Eclipse update Manager 或者是安装包进行安装,安装成功后会在 eclipse 中增加如下所示的按钮,另外一个专门的用于检查 TPTP profiling 结果的 perspective 也会添加进 eclipse 中,如下图所示:
CodePro Profiler
CodePro Profiler 是由 instantiations 公司推出的一款商用 eclipse 插件,它可以通过 Eclipse update Manager 进行安装或者是将安装包直接解压缩后保存在 eclipse 的指定目录下。与 TPTP 类似,安装成功后,有一个专门的用于查看 CodePro profiling 结果的 perspective 会添加进 eclipse 中,如下图所示:
YourKit Profiler
YourKit Java Profiler 也是一款商用软件,支持的操作系统包括:Windows, Linux, FreeBSD, Mac OS X, Solaris 以及 HP-UX;支持的 IDE 包括:Eclipse, JBuilder, JDeveloper, NetBeans 以及 Intellij IDEA。安装成功且首次启动 YourKit Java Profiler 后,会弹出一个对话框,让用户选择 YourKit Java Profiler 要集成进的 IDE,并指定该 IDE 的安装路径,点击”Install Plugin”按钮并集成成功之后,Eclipse 中会出现如下图标,用户就可以从 Eclipse 中启动 Profiling,但是 profiling 的结果需要在 YourKit Java Profiler 中进行查询,如下图所示:
JProfiler
JProfiler 是由 ej-technologies 推出的一款商用软件,支持的操作系统有:Windows, Linux, Mac OS X, FreeBSD, Solaris, AIX 以及 HP-UX;支持的 IDE 包括:Eclipse, NetBeans, Intellij IDEA, JBuiler 以及 JDeveloper。安装成功并首次启动 JProfiler 后,会弹出一个设置界面,当完成左栏所示的那些步骤后,Eclipse 中就会出现如下图标,用户就可以从 Eclipse 中启动 Profiling。与 YourKit Java Profiler 类似,profiling 的结果需要在 JProfiler 中进行查询,如下图所示:
Java Profiler 工具比较
本章节将从如下几个方面对上述工具进行比较:
与 Eclipse 的集成性
TPTP:是一款基于 Eclipse 开发的插件,因此与 eclipse 的集成性很好。安装成功后,对 TPTP 的一切设置与操控都可以在 eclipse 中完成;另外,profiling 的结果也可以在 eclipse 中进行查询。
CodePro Profiler: 与 TPTP 类似,CodePro Profiler 也是一款基于 eclipse 开发的插件,因此与 eclipse 的集成性很好好。用户在 eclipse 中就可以完成对 profiling 的所有操作。
YourKit Java Profiler: YourKit Java Profiler 可以说是一个比较独立的工具,安装成功后,用户可以直接在 eclipse 中启动 YourKit Java Profiler 并对 profiling 选项进行配置,但是用户必须在 YourKit Java Profiler 工具中对 Profiling preferrence 进行配置,而且 profiling 信息必须在 YourKit Java Profiler 中进行查看。因此和 Eclipse 的集成度一般。
JProfiler: JProfiler 也是一款比较独立的工具,安装成功后,用户可以直接在 eclipse 中启动 JProfiler,其他所有操作必须回到 JProfiler 工具中进行。因此和 Eclipse 的集成性不好。
TPTP
TPTP(Test and Performance Tools Platform)是 eclipse 官方的 Profiling 工具插件。TPTP 提供了诸如测试,追踪(trace),性能测试,图形界面性能分析等功能。同时 TPTP 还是一个可扩展的开发平台框架,你可以对它加以扩展集成到你自己的产品中。TPTP 可以通过 Eclipse update Manager 或者是安装包进行安装,安装成功后会在 eclipse 中增加如下所示的按钮,另外一个专门的用于检查 TPTP profiling 结果的 perspective 也会添加进 eclipse 中,如下图所示:
CodePro Profiler
CodePro Profiler 是由 instantiations 公司推出的一款商用 eclipse 插件,它可以通过 Eclipse update Manager 进行安装或者是将安装包直接解压缩后保存在 eclipse 的指定目录下。与 TPTP 类似,安装成功后,有一个专门的用于查看 CodePro profiling 结果的 perspective 会添加进 eclipse 中,如下图所示:
YourKit Profiler
YourKit Java Profiler 也是一款商用软件,支持的操作系统包括:Windows, Linux, FreeBSD, Mac OS X, Solaris 以及 HP-UX;支持的 IDE 包括:Eclipse, JBuilder, JDeveloper, NetBeans 以及 Intellij IDEA。安装成功且首次启动 YourKit Java Profiler 后,会弹出一个对话框,让用户选择 YourKit Java Profiler 要集成进的 IDE,并指定该 IDE 的安装路径,点击”Install Plugin”按钮并集成成功之后,Eclipse 中会出现如下图标,用户就可以从 Eclipse 中启动 Profiling,但是 profiling 的结果需要在 YourKit Java Profiler 中进行查询,如下图所示:
JProfiler
JProfiler 是由 ej-technologies 推出的一款商用软件,支持的操作系统有:Windows, Linux, Mac OS X, FreeBSD, Solaris, AIX 以及 HP-UX;支持的 IDE 包括:Eclipse, NetBeans, Intellij IDEA, JBuiler 以及 JDeveloper。安装成功并首次启动 JProfiler 后,会弹出一个设置界面,当完成左栏所示的那些步骤后,Eclipse 中就会出现如下图标,用户就可以从 Eclipse 中启动 Profiling。与 YourKit Java Profiler 类似,profiling 的结果需要在 JProfiler 中进行查询,如下图所示:
Java Profiler 工具比较
本章节将从如下几个方面对上述工具进行比较:
与 Eclipse 的集成性
TPTP:是一款基于 Eclipse 开发的插件,因此与 eclipse 的集成性很好。安装成功后,对 TPTP 的一切设置与操控都可以在 eclipse 中完成;另外,profiling 的结果也可以在 eclipse 中进行查询。
CodePro Profiler: 与 TPTP 类似,CodePro Profiler 也是一款基于 eclipse 开发的插件,因此与 eclipse 的集成性很好好。用户在 eclipse 中就可以完成对 profiling 的所有操作。
YourKit Java Profiler: YourKit Java Profiler 可以说是一个比较独立的工具,安装成功后,用户可以直接在 eclipse 中启动 YourKit Java Profiler 并对 profiling 选项进行配置,但是用户必须在 YourKit Java Profiler 工具中对 Profiling preferrence 进行配置,而且 profiling 信息必须在 YourKit Java Profiler 中进行查看。因此和 Eclipse 的集成度一般。
JProfiler: JProfiler 也是一款比较独立的工具,安装成功后,用户可以直接在 eclipse 中启动 JProfiler,其他所有操作必须回到 JProfiler 工具中进行。因此和 Eclipse 的集成性不好。.
遥测种类
TPTP:目前使用的 4.6.2 的版本只提供了线程 Telemetry。
CodePro Profiler: 总共有五个类型:CPU, 内存 , 线程 , 载入的类以及垃圾收集。
YourKit Java Profiler: 与 CodePro Profiler 相比,缺少载入类的监测。
JProfiler: 与 CodePro Profiler 一样,总共有五个类型的监测方法。
CPU 快照包含的统计数据类型
TPTP: CPU 快照包含的统计数据有:
包的组成关系,细化到包含的类及类中的方法。
方法的调用关系:以每个线程为根节点的方法调用信息,对于树中出现的代表方法的每个节点,列出了该方法的运行时间或运行时间百分比,以及该方法被调用的次数。
方法被调用情况:列出了直接调用某方法的其他方法,以及这些方法调用该方法的次数及相关运行时间。
热点列表:包含了 CPU 占用时间排列前十的方法、类或包。
CodePro Profiler: CPU 快照包含的统计数据类型有:
包的组成关系,细化到包含的类及类中的方法。
方法的调用关系。以树结构表示,根据根节点表示的对象的不同,分为三种类型:以每个线程为根节点的方法调用关系,以整个线程为根 节点的方法调用关系,以及以每个方法为根节点的方法调用关系。对于树中出现的代表方法的每个节点,列出了该方法的运行时间或运行时间百分比,以及由该方法 生成的对象个数和为这些对象分配的内存大小。
方法的被调用关系。该关系以树结构表示,其中根节点为某个指定的方法,每个节点的子节点为父节点的调用者。
热点列表:包含了 CPU 占用时间排前的一些方法。
YourKit Java Profiler:CPU 快照包含的统计数据类型与 CodePro Profiler 类似;
JProfiler:与 CodePro Profiler 相比,缺少以每个方法为根节点的方法调用关系。因此当要查看以某个方法为调用起点的调用关系时,需要到以线程为根的树结构当中去查找。另外,方法的被调用 关系不是以树结构来表示的,而是以图的方式来显示的,当调用关系比较复杂的时候,很难在一个屏幕中看到一个全局关系图。
内存快照包含的统计数据类型
TPTP:包含了类实例的内存分配情况,包括实例化的对象个数,以及这些对象的本身占用内存的大小。相对于其它 Java Profiler 工具,TPTP 的内存快照包含的统计数据类型比较少。
CodePro Profiler: 包含的统计数据有
类实例的内存分配情况,包括实例化的对象个数,以及这些对象的 shallow 和 retained 大小。(Shallow size 就是对象本身占用内存的大小,不包含对其他对象的引用;Retained size 是该对象自己的 shallow size,加上从该对象能直接或间接访问到的 shallow size 之和,即该对象被 GC 之后所能回收到内存的总和)。
最大对象列表:包含了 retained 大小排前的一些对象。
有可能存在内存泄漏的对象列表:包含了有可能存在内存泄漏的对象以及可能性大小。
YourKit Java Profiler:与 CodePro Profiler 相比,缺少内存泄露对象列表这一项。
JProfiler:与 CodePro Profiler 相比,缺少 retained size 统计数据及内存泄露对象列表。
源代码定位功能,即在快照中选中某个类、成员变量或者方法时,可以在源代码中定位到对应的定义。
TPTP:只能定位到某个类,无法定位到方法或其中的成员变量。
CodePro Profiler: 拥有该功能,但是只能定位到类及成员变量,无法定位到方法。
YourKit Java Profiler:可以定位到类、成员变量及方法。
JProfiler:与 CodePro Profiler 类似。
快照操作,主要从快照的获取、快照的保存及快照的比较这三方面进行比较。
TPTP:当应用程序启动后,用户可以选择在适当的时候进行快照获取;这些快照不会自动保存,因此当 eclipse 关闭后,这些快照数据将会消失,但是用户可以通过 export 的方式将需要的快照保存下来。
CodePro Profiler: 当应用程序启动后,用户可以选择在适当的时候进行快照获取;这些快照会被自动保存在 Eclipse Workspace 之外的一个临时的空间,当 eclipse 关闭后,这些快照将会消失,用户可以通过 export 的方式将需要的快照保存下来;CodePro Profiler 还提供了快照的比较功能,不过前提是这两个快照的类型必须相同(例如:都是以 sampling 模式或 BCI 模式运行的)。
YourKit Java Profiler:当应用程序启动后,用户可以选择在适当的时候进行快照获取,针对内存快照,YourKit Java Profiler 还提供了自动获取快照的功能;这些快照会被自动保存到一个临时的文件夹中,eclipse 关闭后,这些文件不会消失;另外,YourKit Java Profiler 也提供了快照比较功能。
JProfiler:工具会要求你指定一个目录来保存该 snapshot。
性能,在 sampling 模式下,这些工具的性能相差不大,这里主要比较在 BCI 模式下的性能。
TPTP:目前使用的 4.6.2 的版本没有 BCI 模式。
CodePro Profiler:当程序比较大的情况下,采用 BCI 模式进行 profiling 的速度比较慢;另外,在获取内存泄露候选者的时候,速度也是相当慢。(当程序代码量 5 万行时,用 CodePro Profiler 进行 Profiling 需要 5 分钟,在获取内存泄露候选者时,需要花费 20 分钟)
YourKit Java Profiler:BCI 模式下的运行速度还可以。(当程序代码量为 5 万行时,需要 1 分钟)
JProfiler:感觉不出程序运行速度受影响。(当程序代码量为 5 万行时,需要半分钟)
健壮性,采用 CodePro Profiler 对比较大的应用程序进行 profiling 时,很容易出现栈溢出的错误。
结论
TPTP 是一款基于 eclipse 的开源软件,且提供的功能比较简单,因此适用于基于 eclipse 开发的应用程序,且该应用程序比较简单的情况;Codepro Profiler 提供的功能相对来说比较丰富,且与 eclipse 的集成性很好,但是在性能方面有待改善,因此适用于基于 eclipse 开发的应用程序,且对性能要求不高的情况;YourKit Java Profiler,JProfiler 与 Eclipse 的集成性都属于一般,提供的功能也比较丰富,且性能不错,因此适用于对 eclipse 集成度要求不高,且对性能要求较高的情况。
同时创建一个规则(Qolicy)文件,添加[computer_name][computer_domain]行到/etc/hosts。
3.如何使用不同端口号
默认情况下,JMeter使用标准RMI端口号1099(这是可以改变的)。要想成功改变使用的端口号,需满足如下条件:
在远程服务器,启动Rmiregistry使用新端口号。
在远程服务器,启动JMeter并预先定义server_port属性。
在客户端,更新remote_hosts属性,在其中包含remote host:port设置。
从JMeter 2.1.1版本开始,jmeter-server脚本支持改变端口号。例如,假设
测试人员希望使用端口号1664(可能因为1099端口已经被其他应用程序占用了)。
C:\JMETER> SET SERVER_PORT=1664
C:\JMETER> JMETER-SERVER [other options]
UNIX系统:
$ SERVER_PORT=1664 jmeter-server [other options]
[N.B. use upper case for the environment variable]
在这两种情况下,脚本都会在指定端口上启动Rmiregistry,接着以远程服务器模式启动JMeter,并已经定义了"server_port"属性。
选定的端口号将会被记录到远程服务器的jmeter.log文件中(Rmiregistry不会创建一个日志文件)。
4.使用采样批次
测试计划中的监听器会把它们的结果返回到JMeter客户端,而JMeter客户端默认情况下会将这些结果写入到指定文件中,采样结果会在产生后立即发回JMeter客户端。这样就会对网络和JMeter客户端产生很大的压力。用户可以通过设置一些属性,来改变默认操作。
模式(Mode)(采样结果发送模式)默认是Standard。
Standard:在采样结果产生后立即发送。
Hold:将采样结果保存在一个数组中,直到测试结束。这可能会占用远程服务器的大量内存。
Batch:当计数器或者时间超过阈值之后,发送保存的采样结果。
Statistical:当计数器或者时间超过阈值之后,以概要的形式发送采样结果;采样结果以线程组(Thread Group)名称和采样标签(Sample Label)进行概要统计。积累的数据域包括:elapsed time、latency、bytes、sample count、error count,其他数据域将会被丢弃。
Stripped:将成功采样的响应数据移除。
StrippedBatch:将成功采样的响应数据移除,并批次发送。
Custom implementation:将模式参数设置为测试人员的客户化采样发送器的类名。该类必须实现接口SampleSender,并且类的构造函数只有一个RemoteSampleListener型的参数。
如下属性会影响Batch和Statistical模式。
num_sample_threshold:一个批次中的采样数目(默认为100)。
time_threshold:等待的毫秒数(默认为60秒)。
一:Dir()列出模块定义的标识符。标识符有函数、类和变量。如果不提供参数,它返回当
前模块中定义的名称列表。
>>> a=5 >>> dir() ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys'] >>> del a >>> dir() ['__builtins__', '__doc__', '__name__', '__package__', 'sys'] >>> |
二:list列表
列表中的项目应该包括在方括号中,一旦你创建了一
个列表,你可以添加、删除或是搜索列表中的项目。由于你可以增加或删除项目,我们说列表
是 可变的 数据类型,即这种类型是可以被改变的。
三:元组
元组和列表十分类似,只不过元组和字符串一样是 不可变的。元组通过圆
括号中用逗号分割的项目定义。我们可以通过一对方括号来指明某个项目的位置从而来访问元组中的项目,就像我们对列表的
用法一样。这被称作 索引 运算符。我们使用new_zoo[2]来访问new_zoo中的第三个项目。我们
使用new_zoo[2][2]来访问new_zoo元组的第三个项目的第三个项目。
四:字典
我们可以使用in操作符来检验一个键/值对是否存在,或者使用dict类的has_key方法。你可以使
用help(dict)来查看dict类的完整方法列表
flex与普通java类通信RemoteObject;
flex与服务器交互HTTPService;
flex与webservice交互WebService。
当大家尝试使用flex与普通java类通信时,一般用RemoteObject,具体的代码段如下:
package com.flex.demo;
/** *第一种 功能描述:该类用来实现flex与普通java类中的方法通信 * @author Administrator */ //以上是打头的功能描述,可以不写。 <!--flex 与普通java类通信--> <s:RemoteObject id=“serv“ destination=“myservice“ fault=“serv_faultHandler(event)“ result=“serv_resultHandler(event)“> <properties> <source>com.flex.demo.SimpleService</source> </properties> </s:RemoteObject> [js] view plaincopy <!--flex 与服务器交互HTTPService--> <!--servlet代码--> /** * 第二种 功能描述:该servlet用来与flex进行交互 * @author Administrator */ @SuppressWarnings(“serial“) public class SimpleServiceServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(“utf-8“); response.setCharacterEncoding(“utf-8“); response.getWriter().write(“我是服务器“); } } |
flex与服务器交互HTTPService,flex端代码
<!-- flex 与服务器交互--> <s:HTTPService id=“service“ fault=“service_faultHandler(event)“ result=“service_resultHandler(event)“ url=“http://localhost:8080/flexdemo/simpleServiceServlet“> </s:HTTPService> <!--第三种 flex与webservice交互WebService--> <!--flex与webservice交互这里调用一个天气预报的webservice--> <s:WebService id=“ws“ wsdl=“http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl“ fault=“ws_faultHandler(event)“ result=“ws_resultHandler(event)“ showBusyCursor=“true“> <!-- 调用webservice的方法<speration>--> |
另外,我想说一下的是,对于弹出框的代码段虽然是很简单的,但是也最好不要漏掉:
protected function service_faultHandler(event:FaultEvent):void{ Alert.show(“调用失败了:“+event.fault.message as String,“提示“); } protected function service_resultHandler(event:ResultEvent):void{ Alert.show(“调用成功了:“+event.result as String,“提示“); } <span style="font-family:Arial; background-color:#ffffff"></span> |
经常有人问如何才能得到涨薪或者叫拿到高薪,这是一个很宽泛的话题,如果要真正的讲明白,可能需要更专业的人更专业的数据和事实来阐述,简单点说就是让自己不可替代或者替代成本很高!我只是抛砖引玉说说我的理解,因为我也还在上下求索的漫漫道路上。往细点说的话,该话题涉及内容大致分为以下几个部分:
影响力
设定目标并按时达成
创新致胜
团队协作
主动出击把握机会
合理提出涨薪
影响力
就打工者而言,人与人之间的收益差距可以达到上百倍,不是因为高收入者能够以一抵百,干一百个低收入者的活儿,而在于影响到了多少人,受到影响的人都能在一个战线上齐心协力为组织贡献力量,创造更大的价值。作为
测试人员,如何提高影响力呢?单单说因为某人是测试部门负责人所以整个项目组都能受到他的影响,这显得非常片面,职位高能在威望上占一定优势,但是影响力却不只包括威望,还包括
工作的专业性,说服力,乐于分享,诚信等。对于测试工程师而言,良好的测试技能水平能帮助项目顺利交付并且质量达标,对各种突发事件和困难能得心应手的解决掉,让整个项目组受益,承诺的测试计划能够按时达成,那么他一定会是个有影响力的人,大家都觉得他靠谱,都会愿意与他同事。
设定目标并按时达成
懒懒散散过一天算一天,没有任何计划和目标的人很难有好的发展,而善于在工作中给自己或团队设定目标并克服困难努力达成的人,一直都在进步中,每一次目标的达成,都完成了一次超越。
创新致胜
维基百科这么定义创新:创新是指以现有的思维模式提出有别于常规或常人思路的见解为导向,利用现有的知识和物质,在特定的环境中,本着理想化需要或为满足社会需求,而改进或创造新的事物、方法、元素、路径、环境,并能获得一定有益效果的行为。所以并不单单指像电灯,
手机等等这样伟大的发明,也不是非要做过什么研究发表过学术论文并获得过专利,其实落实到我们日常工作中,可以简单理解为通过一定方法来提高工作效率的行为都是创新,包括一项新测试技术引入,测试工具的研发和推广,测试方法的改进,流程优化等等,都是为了让工作更高效,让测试工作更美好。
以前我有个同事就经常抱怨这个功能从进公司就在做,每次改版都是我来做,测试的都要吐了。如果是一个善于思考并敢于创新的人来做,一定是每一次测试都能有不同的体会,并且找到可以优化的测试方法,既然测试到要吐了,一定是有大量的简单重复手工测试,完全可以考虑进行自动化,包括数据准备自动化,测试回归自动化等等,在对这些技术学习过程中,提高了自己的开发技能,同时更加能从开发人员的角度来理解功能实现进行高效测试。所以我把这个叫做测试工作中的微创新,即使做同样一件事,都要反复思考琢磨是否有可以改进的地方,没有什么是完美的,总有值得我们去改进的。
团队协作
做技术的有少许人容易变成一个对技术狂热但是不太融入团队的人,当然的确有个别大公司是非常欢迎这样的技术大牛,这叫做个人英雄主义,能成为这样的人薪酬自然也不会少。但更多的人,没有这么强悍的技术,做不出非凡的技术创新,更多的工作是成为团队中的一员,只是在奉献一部分力量,没办法独当一面,团队协作就显得格外重要,如果你的性格没办法让你融入这个集体,迟早会被孤立被边缘化,自然也不会受到重视。就更别提加薪一事了。
总结及学习
总结其实不只是需要总结自己的过往,也可以去借鉴别人的经验,拿来主义简单快捷,少走弯路,能快速让自己得到提高,何乐而不为?!对于过往,不只是需要找到失败的原因,也要找到成功的原因,需要避免再次失败同时确保再次取得成功,就是不要在失败的道路上迷失,不要让成功变成侥幸。如果你想成为某某人,那就像那个人一样严格要求自己,没有谁会轻易成功。
主动出击把握机会
积极主动的人总能得到更多施展自己的机会,我个人觉得,评判一个人工作态度主要看两个时候:一个是特别忙压力很大的时候;一个是非常闲闲的蛋疼的时候。后者其实就是主动性,在份内工作完成之后(这个是前提)还愿意去承担更多的工作的人,始终都是上司喜欢的人,当然如果你看到有啥活接啥活结果干不成不行,还必须要有这个实力,机遇一定是给准备好了的人,不然到了你手里也是浪费,下次谁还敢交待给你这种任务。
合理提出涨薪
合理就包括合理的方式,合理的时机和合理的理由。
提出涨薪的方式不外乎当面提出来或者发邮件,我们做技术的比较含蓄,多是通过发邮件的方式,试想如果你是个销售人员,天天更客户打交道跟金钱打交道的人,发邮件的话,会不会被你老板大骂亏你还是做销售的呢!当面销售自己岂不是更好的方式?!
合理的时机,其实也不难理解,如果上司今天刚失恋了,本来心情就不好,你提出加薪的事情岂不是给人添乱,所以要看看脸色行事。再举个例子,一个电灯泡要是每天都亮着,主人无暇顾及永远不知道他的重要性,突然一天他没亮,这才觉得缺了他不行,这个电灯泡还是很重要的。如果这个电灯泡尝到了这个甜头,隔三岔五就灭一次,突然一天主人直接把它换掉了。这个故事也说明了要见机行事,也不能太过了过犹不及。
如果你提出的加薪理由是物价太高无法生活了,我想这是最糟糕的理由,没有哪个老板愿意为高物价而买单,你换种说法说用同样的钱是请不到我这样水平的人,如果请我这样水平的就需要开更高的工资,所以给你涨薪也是理所当然了,当然这个理由只能保证能涨薪,一定涨不了太多。要想再多涨点的话,那就列出你自己最近的成绩单,还有未来可以为企业再创造什么价值,聪明的老板一定会想办法留住你。要涨高薪的话,就从以上几点做起吧,做一个不可替代的人或替代成本很高的人,即使这家公司给不了你想要的薪水,别处也能如你所愿。
我们知道,只要有软件就会有bug。一者,再严格的
测试也只是抽样活动,总会有bug被遗留下来。再者,做软件也是一种商业行为,对质量的投入要看ROI。基于以上两种原因,软件或者系统发布时总会或多或少带点bug。对于这些bug,我们要看它的影响程度是什么样的。对于生命周期比较长的系统,这些bug只要产生了影响都是要修改的。在我上篇
文章《测试的最高境界是什么?》 中给出了软件不同周期中缺陷修复所需要的成本的一张示意图,要知道,bug的检测也是需要成本的,并且检测成本也会随着时间向后推移水涨船高。对于开发者来说,已发布版本的bug如何检测才能成本低且有效呢?显然已发布的软件会直面用户,从用户身上打主意是正途。 再鸡贼一些,如何让用户在发布前就参与测试呢?在IT行业蓬勃发展的几十年间,涌现了大量让用户帮助开发者做测试的方法。下面就让我们一一道来。
α测试和β测试
α测试和β测试是上个世纪较为流行的两种用户测试方法。两者都是请用户真实的来使用系统,并反馈错误。两者最大的不同是,前者是请用户到开发者的环境中做测试;后者是用户在自己的环境中做测试。由于不同的用户所有的软硬件环境千差万别,因此在β测试中可能发现更多的兼容性问题。另一个稍小的区别就是α测试有可能是开发公司内部人员(
微软流行的“吃你自己的狗食”),β测试则更倾向于外部的真实用户。β测试的测试成本较高,尤其是在
互联网普及以前。我中学时代就做过β测试,那时候某家软件厂商在《电脑报》上招聘测试人员,被选中后会把被测软件寄来,你把测试结果写信寄回去,测试几乎不会给钱。但是当时唯一吸引我的是:软件装在6张3.5寸软盘里,当时对于我可是笔客观的财富。但不这么做的成本会更高!在互联网能够几乎无成本分发软件之前,未经测试的软件需要以光盘或者软盘的形式发布,如果出现大错误,那损失可就大了。这错误就连伟大的暴雪公司也犯过,他们的游戏《魔兽争霸1》,没有经过很好的测试就在圣诞节发布了。由于兼容性等问题,很多客户拿到光盘后连装都装不上,这让暴雪赔了几百万美刀,差点丢了命。
吃自己的狗食
微软臭名昭著的有效做法。那自己或者自己的兄弟当小白鼠。内部人发现bug理应反馈,还不能拿酬劳,大家都是命运共同体嘛。这样,上班是员工,下班就变成了最终用户,甚至上班时候也变成了最终用户。原来有个同学在网易,有段时间
工作时间联系他只能用网易泡泡,据说QQ被强制卸载了(不过泡泡现在还活着么?)。
故障推送
互联网时代来了。用户报bug的成本低了,因为错误信息可以很方便的传回去。所以在非常多的软件中你可以在它们崩溃后得到一个提示框:“您愿意帮助我们改进产品么?您的反馈对我们非常重要blablabla。。。” 只要一点,调试信息就回传到开发者那里了。当然会有客户以在论坛,微博等平台上吐槽的形式推送bug。
A/B测试
发布特性、版本上有些许不同的软件给不同的用户。然后比较这些特性的造成的不同影响。A/B测试其实取自科学实验中的对照法。在实践中A/B测试的主要目的是为了改进软件特性、提高转化率等,发现bug反倒在其次了。想对A/B测试有跟深入了解可以google A/B测试的网站,或者买这本书。
灰度发布
灰度发布本质上是A/B测试的一种变种。其实施方法是:某个软件的新特性推出或者特性进行升级的时候不是一下子发布给所有用户,而是按照一定的策略,逐步发布给所有用户。例如:某电商网站的推荐算法升级,先发布到一个二级城市,然后比较这个城市的推荐转化率是否提高了。当然现在很多互联网公司利用灰度发布来快速发布软件,比如某游戏升级,先选取一定比例的ip,比如1%的ip发布。如果出现问题,客户很快会在平台上以各种形式反馈(包括在游戏大厅或者论坛内吐槽),这时候开发者就知道有问题了,马上进行修复,然后继续灰度发布。等功能或者性能稳定了以后,继续提高发布比率,直至100%。这样做的好处是:能够迅速得到真实用户的反馈,且如果出现问题,不会大面积影响用户。
生产引流
灰度发布是一种非常好的策略,但是它有时候也对少量用户造成了影响。有没有不影响用户,还能让用户做测试的方案么?这就是生产引流:从生产系统上将用户所有请求复制下来,引入到测试系统进行测试。这种方法尤其适合互联网软件,客户端越瘦,就越不用关注客户端的软硬件环境。生产引流可以用作
性能测试和
功能测试。现在性能测试用得比较广泛的是TCPCOPY,目前网易,
百度,阿里都有广泛应用。功能测试的实现手段根据被测系统的技术架构不同会有很大区别,根据被测系统的业务流程不同也会有很大区别,根据测试的意图也会有很大区别。后续我将举一个详细的例子来描述生产引流的测试方法。
黑暗部署
黑暗部署的词是facebook的工程团队起的,但其实很多团队早已经这么做了,只是没有总结出来而已。其主要思路是:把新开发的特性部署到生产系统上,并有一个开关来快速的控制这个特性是否让用户可见,在部署的初期,这个开关是关闭的。有人要问,这么做有啥用?其实可以结合生产引流配合测试,也可以查看新上的特性是否影响原有系统的正常运行。