qileilove

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

测试驱动开发TDD(1)

 TDD
  今儿接到一需求如下:
  比如一个给定的数字2975,让你去猜。6次机会。如果第一次输入2509,系统会提示 1A2B:其中数字“2”位置猜对&&数字也猜对。称为1A,而“9”和“5”数字猜对了但是位置没有猜对。称为2B。。如果输入2975那么就是4个数字都猜对了并且位置也是对的系统提示4A0B。民间俗称猜数字游戏:百度百科传送门:http://baike.baidu.com/view/358630.htm。
  做个简单分析。客户端输入一个数字,经过游戏内部的猜测,返回一个结果给客户端。嗯,还好,不算难。由于准备做TDD实践。所以我们Test First.Why? 如果您对TDD不是很了解。就跟我一起做下去,显然我也是新手。我们的目标是“没有蛀牙!”。
  准备工作:VS任意一个版本(C#)、任意一款测试工具、纸、笔(真彩0.5的)。
  第一步:笔和纸拿出来。思考思考如何把这个小游戏拆分了。然后我们一步一步去完成它。写一个To-Do-List。
  To-Do-List:
  猜测数字
  输入验证
  生成答案
  输入次数
  输出猜测结果
  ...............
  暂时想起这么多。比如还有选择游戏难度、输入日志、重新开始游戏、中途退出等等。
  今天我要完成这个游戏的核心功能(猜测数字),我称它为Guesser。传入一个数字,返回一个结果。分析一下它可能输出的几种情况:4a0b(全对)、 0a4b(数字全对,位置全错)、2a2b(一半一半)、0a0b(全错)。这4个CASE应该Cover了所有情况了。如果有补充,请Follow。
  今天的TO-DO-LIST:
  假设我们这局游戏的答案是2975。
  输入“2975” 输出4a0b。
  输入“2957” 输出2a2b。
  输入“9257” 输出0a4b。
  输入“1348” 输出0a0b。
  完成Guesser类.
  新建一个TEST 写测试。
  开始第一个CASE:输入2975 与答案正匹配,输出4a0b 。
[TestMethod]
public void Test1()
{
var inputNumber = "2975";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("4a0b", actual);
}
  这个测试方法的命名一眼好像看不出它要测什么。单独看测试的名字很是迷茫。我们修改一下让它看起来很整洁。一眼看上去就知道是啥意思。要测试什么。
[TestMethod]
public void should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right()
{
var inputNumber = "2975";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("4a0b", actual);
}
  修改完之后在看这个方法的命名。 是不是清晰了很多。看到方法的命名应该就能够猜测到此方法是在什么情况下测试什么功能。
  OK。我们的第一个CASE搞定了。Run一下。
  编译不通过!因为没有Guesser类。没有Guess方法。
  为了让CASE过。我们必须创建Guesser类以及Guess方法。
public class Guesser
{
public string Guess(string inputNumber)
{
throw new System.NotImplementedException();
}
}
  现在编译没错误了。在Run。
  有异常:System.NotImplementedException: The method or operation is not implemented.
  闹心。为了不闹心。Guess方法里简单实现。最简单的就是直接返回"4a0b"。这里还是简单的实现实现。
public class Guesser
{
private const string AnswerNumber = "2975";
public string Guess(string inputNumber)
{
var ACount = 0;
var BCount = 0;
for (var index = 0; index < AnswerNumber.Length; index++)
{
if (AnswerNumber[index]==inputNumber[index])
{
ACount++;
}
}
return string.Format("{0}a{1}b", ACount, BCount);
}
}
  OK。但是我们内部实现如此简单。不知道是否满足第二个CASE呢。
  完成一个CASE要把它划掉。
  To-Do-List:
  输入“2975” 输出4a0b。
  输入“2957” 输出2a2b。
  输入“9257” 输出0a4b。
  输入“1348” 输出0a0b。
  完成Guesser类.
  来第二个CASE:输入9257与答案不匹配,但是所有数字都正确,输出0a4b 。
  有了第一个CASE的经验,这里我们也同样注意命名。
[TestMethod]
public void should_return_2a2b_when_input_numbers_all_figures_right_and_2_positions_right()
{
var inputNumber = "2957";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("2a2b", actual);
}
Run.....
  没有PASS:Assert.AreEqual failed. Expected:<2a2b>. Actual:<2a0b>.
  我们接着去改guess方法,保证第二个CASE PASS。
public class Guesser
{
private const string AnswerNumber = "2975";
public string Guess(string inputNumber)
{
var aCount = 0;
var bCount = 0;
for (var index = 0; index < AnswerNumber.Length; index++)
{
if (AnswerNumber[index]==inputNumber[index])
{
aCount++;
continue;
}
if (AnswerNumber.Contains(inputNumber[index].ToString()))
{
bCount++;
}
}
return string.Format("{0}a{1}b", aCount, bCount);
}
}
  运行所有CASE...pass.别忘记划掉To-Do-List
 接下来把剩下的两个CASE搞定。
[TestMethod]
public void should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right()
{
var inputNumber = "2975";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("4a0b", actual);
}
[TestMethod]
public void should_return_2a2b_when_input_numbers_all_figures_right_and_2_positions_right()
{
var inputNumber = "2957";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("2a2b", actual);
}
[TestMethod]
public void should_return_0a4b_when_input_numbers_all_figures_right_and_no_positions_right()
{
var inputNumber = "9257";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("0a4b", actual);
}
[TestMethod]
public void should_return_0a0b_when_input_number_all_figures_and_positions_wrong()
{
var inputNumber = "1348";
var actual = new Guesser().Guess(inputNumber);
Assert.AreEqual("0a0b", actual);
}
  运行所有CASE...
  不知不觉我们已经完成了今天的所有任务。
  To-Do-List:
  输入“2975” 输出4a0b。
  输入“2957” 输出2a2b。
  输入“9257” 输出0a4b。
  输入“1348” 输出0a0b。
  完成Guesser类.
  Go Home.然后别忘记把总的List划掉。
  今天的任务完成。今天收获是什么?
  (1)Test First。从用户角度去思考问题。在设计CASE之前。会把关注点放到需求上。只有足够透彻的了解需求。才能设计出正确全面的CASE。
  (2)命名。在最开始我们把Test1改成了‘should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right’。看到方法名,就相当于看到文档。很快速的知道当前方法测的是什么功能。而不需要去翻阅文档。维护起来也是相当清晰。不用花大把时间去维护文档。
  当然也有些疑问。
  (1)先写测试在写代码开发速度降低了。
  带着这些疑问。继续做下去。希望在这个系统实现完之后能解决我的疑问。
  最后Yuheng同学提出了一个问题。
  有4个分别是[风险高 价值高]、[风险高 价值低]、[风险低 价值高]、[风险低 价值低]的事情,你会优先做哪个?
  大家可以给出自己的答案。

posted @ 2014-01-16 11:38 顺其自然EVO 阅读(284) | 评论 (0)编辑 收藏

十分简单的redis使用说明及性能测试

  redis相比很多人都知道,是一个内存式的key-value数据库,存取速度极快,使用非常简单,支持多种语言。本文对其使用进行一个简要说明,并进行简单测试
  1.下载与编译
  可以从redis官网下载最新的源码包:http://www.redis.io/
  编译十分简单make既可。
  2.redis安装与配置
  实际上并不需要安装。redis编译后会在src目录下生成redis-server,它是一个可执行文件,即启动redis服务。不过它需要一个配置文件。配置文件写法网上很多了,这里直接给出一个示例:
daemonize yes
pidfile /tmp/redis/var/redis.pid
port 6379
timeout 300
loglevel debug
logfile /tmp/redis/var/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /tmp/redis/var/
appendonly no
appendfsync always
#glueoutputbuf yes
#shareobjects no
#shareobjectspoolsize 1024
  将其保存为redis.conf
  然后直接运行./redis-server redis.conf就可以启动redis服务了,是不是很方便呢?
  3.C/C++访问redis
  在redis源码目录下有一个deps目录,下面有一个hiredis目录。redis编译时会自动编译该目录生成libhiredis.a,通过引用hiredis.h 和 libhiredis.a就可以访问redis了。具体步骤如下:
  1)创建一个redisContext
  2)通过redisContext执行命令
  3)从返回redisReply中获取所需数据
  代码如下:
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_2_9509153" name="code" class="cpp">redisContext *  c = redisConnect((char *)"192.168.150.135",6379);
const char * pData = "this is a test";
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_2_9509153" name="code" class="cpp">redisReply *reply1 = (redisReply *)redisCommand(c,"SET 100 %s",pData);
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_2_9509153" name="code" class="cpp"><pre code_snippet_id="151033" snippet_file_name="blog_20140110_2_9509153" name="code" class="cpp"><pre code_snippet_id="151033" snippet_file_name="blog_20140110_2_9509153" name="code" class="cpp">freeReplyObject(reply1);</pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<p></p>
<pre></pre>
<pre></pre>
<br>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_3_730653" name="code" class="cpp"><pre code_snippet_id="151033" snippet_file_name="blog_20140110_3_730653" name="code" class="cpp"><pre code_snippet_id="151033" snippet_file_name="blog_20140110_3_730653" name="code" class="cpp">redisReply *reply2 = (redisReply *)redisCommand(c,"GET 100");</pre>
<pre></pre>
<pre></pre>
printf("%s\n",reply2->str);<br>
freeReplyObject(reply2);<br>
<pre></pre>
<pre></pre>
<pre></pre>
  是不是非常简单呢?
<p></p>
<p>不过需要注意的是,redis接受的数据是字符串,对于二进制数据,可以通过base64编码来解决。具体可参看我的另一篇文章。</p>
<p></p>
<h1><a name="t3"></a>4.Java访问redis</h1>
<p>redis可以支持多种语言,当然也可以支持Java。</p>
<p>首先需要下载redis的java包。jedis.jar。这里提供一个下载地址:<a target="_blank" href="http://download.csdn.net/detail/jmppok/6834151">redis的Java客户端jedis</a></p>
<p>使用如下:</p>
<p></p>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_4_2824204" name="code" class="java">Jedis jedis = new Jedis("192.168.150.135");
jedis.set("100","this is a test");
String data = jedis.get("100");
</pre><br>
<br>
<p></p>
<h1><a name="t4"></a>5.性能测试</h1>
<p>测试方法:向redis写一个1M的数据,分别写10次,读10次,计算其耗时。分C++和Java两个版本进行测试。<br>
</p>
<h2><a name="t5"></a>C++测试代码</h2>
<p></p>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_5_8505805" name="code" class="cpp">#include <stdio.h>
#include "hiredis.h"
#include <string.h>
#include <time.h>
int main(int argc, char **argv)
{
printf("CLOCKS_PER_SEC:%d\n",CLOCKS_PER_SEC);
redisContext *c;
redisReply *reply;
c = redisConnect((char *)"one-60",6379);
char * pData;
reply = (redisReply *)redisCommand(c,"GET 0");
int size = strlen(reply->str);
pData = new char[size+1];
strcpy(pData,reply->str);
freeReplyObject(reply);
clock_t start, finish;
start = clock();
for(int i=0;i<10; i++)
{
reply = (redisReply *)redisCommand(c,"GET %d",i);
freeReplyObject(reply);
}
finish = clock();
double duration = (double)(finish - start) / CLOCKS_PER_SEC*1000;
printf("GET Time used:%f ms.\n",duration);
start = clock();
for(int i=0;i<10; i++)
{
reply = (redisReply *)redisCommand(c,"SET %d %s",i,pData);
freeReplyObject(reply);
}
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC*1000;
printf("SET Time used:%f ms.\n",duration);
delete []pData;
redisFree(c);
}
</pre>测试结果
<p></p>
<p></p>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_6_1363508" name="code" class="plain">CLOCKS_PER_SEC:1000000
GET Time used:190.000000 ms.
SET Time used:70.000000 ms.
</pre><br>
<br>
<p></p>
<h2><a name="t6"></a>Java测试代码<br>
</h2>
<p></p>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_7_633160" name="code" class="java">import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Date;
import redis.clients.jedis.Jedis;
public class JedisTest {
public static void main(String[] args)
{
Jedis jedis = new Jedis("10.100.211.232");
String f = "/tmp/e2.txt.backup";
try
{
File file = new File(f);
BufferedReader reader = new BufferedReader(new FileReader(file));
String data = reader.readLine();
reader.close();
Date start = new Date();
for(int i=0; i<10; i++)
{
jedis.set(i+"", data);
}
Date end = new Date();
System.out.println("Set used(ms):"+(end.getTime()-start.getTime()));
start = new Date();
for(int i=0; i<10; i++)
{
String v = jedis.get(i+"");
}
end = new Date();
System.out.println("Get used(ms):"+(end.getTime()-start.getTime()));
}catch (Exception e)
{
e.printStackTrace();
}
jedis.disconnect();
}
}</pre><br>
  测试结果
<p></p>
<p></p>
<pre code_snippet_id="151033" snippet_file_name="blog_20140110_8_8615272" name="code" class="plain">Set used(ms):1212
Get used(ms):1437</pre><br>
  6.总结
<p></p>
<p>redis效率还是非常高的,读写1M数据的数据,耗时都在10ms左右。<br>
</p>
<p><br>
</p>
<pre></pre>
<pre></pre>
</pre></pre></pre></pre></pre></pre>

posted @ 2014-01-16 11:38 顺其自然EVO 阅读(1271) | 评论 (0)编辑 收藏

2014年自动化的个人感想

自己在2014年写的自动化的感想和规划
  测试开发大势所趋
  1、互联网在深耕细作的发展阶段需要测试发挥更多的影响。
  2、技术在测试工作中的占比无限的趋近开发。
  3、建立学习型和成长型的测试团队。
  4、持续关注个人的成长,测试人员更注重价值体现。
  PPT解读: 1、互联网是快速发展的行业,时刻需要idea迅速的转化为生产力。频繁迭代的开发,追求建立快速的响应机制,要求测试的时效性。较短的测试排期需要加入技术成分从而替代手工回归测试所带来的工作量。
  2、测试是技术岗,测试环节的上游是代码产品,对上游环节的摸索和尝试是不可拒绝的。测试人员越来越了解和参与开发职位的工作既可以起到测试前置的作用也可以扩大测试的范围。测试和开发必将在未来融合。
  3、测试团队需要持续发展的节奏,技术成长是其中的重要一环。学习型的团队最具竞争力、战斗力和向心力。
  4、功能测试是互联网时代产物,也会随着时代的发展而消亡。测试人员普遍存在危机感,对于测试技术的学习和成长要求是迫切的。测试人员越来越不满足于手工测试所带来的成就感。
  自动化技术的应用场所
  1、功能回归测试、冒烟测试。
  2、数据精度要求高的测试,数据计算、比较、统计测试。
  3、简单重复的大批量测试,测试组合众多,需要测试覆盖。
  4、疲劳测试。
  5、接口、底层、代码测试。
  6、其他不便于进行手工的测试。
  PPT解读: 自动化测试是个较大的范畴,所有不用手工进行操作通过程序驱动的测试都可以理解为自动化测试。从技术层面来讲,但凡被技术实现的东西都可以被技术模拟和测试。在人们实践的过程中,自动化技术应用的领域会越来越广,测试也是一样,自动化本身不会去约束方式和行为,自动化能够做什么会超出我们的想象。
  POP的自动化领域
  1、平台SOA化
  2、大数据量和云计算
  3、数据挖掘
  4、移动互联网
  PPT解读: O2O做为2014年京东的战略在POP端会持续发酵。平台的发展需要模块化,越来越来可适配。公共模块直接会被底层服务化,而前端模块大量的被暴露数据接口,更多的测试要求在不可视化的情况下进行。POP的发展积累了庞大的历史数据和商家数据而且还在增长,对于海量数据进行迁移、计算、合并、修改和数据挖掘,需要精准的完成数据测试,需要倚赖自动化测试。虽然移动端未在POP中应用,但是商家说不定哪天就有在手机上管理商品的需要,移动端在POP的布局现在没影,但是需要的时候也会很迅猛,这些都需要我们未雨绸缪。
  为什么需要测试框架
  1、降低实现门槛。
  2、统一技术风格。
  3、量化测试成果。
  4、底层前端分离。
  PPT解读: 没有测试框架也可以实现自动化。每个测试人员技术背景不尽相同,擅长的语言、脚本、实施的技术水平参差不齐,没有框架约束技术实现和风格,他人的维护难度会很大,不利于大家朝同一个技术方向进行分享和交流。 框架本身已经封装了很多实际需要的接口和工具,测试人员不需要花费大量的精力再度开发,集中精力快速实现测试需求本身。统一的结构不仅多人可以同时维护一个项目,也便于测试结果的分析和汇总,众多项目的批量运行。框架和项目的分离,使双方各自影响的范围得到有效控制,便于项目单点维护和迁移。开发需要框架,同样测试开发作为一种开发活动也需要框架。
功能测试人员做自动化
  1、实践为主培训为辅
  2、差别化培养
  3、测试意识的转化
  4、触发危机意识
  5、考核标准
  PPT解读: 1、开展定期的技术培训,包括灌输测试理念,扩展测试思路,培训新的测试技术。培训更多的是了解和灌输理念。重点是实际的动手。培训只占个人成长的10%,需要制定挑战性的任务,让每个人主动亦或是被动的去动手完成,在动手的过程中发现问题解决问题。技术是练出来的,而不是培训出来的。
  2、功能测试人员中个人水平和意愿不尽相同,对有一定技术能力或者有强烈自动化愿望的人重点培训,开小灶,单独辅导,让他们成长的更快一些,对没有自信或者对自动化产生疑虑的人,起到示范带头的效果。
  3、功能测试人员需要在日常测试中转化意识,一个需求过来先考虑如何用自动化实现,当不能实现的时候再考虑手工测试,人们往往按照自己熟悉的方式进行,但是不一定是最好的方式,自动化做的多了,意识转化的也就越快。 4、测试行业本身的竞争很激烈,需要让测试人员意识到这一点。 5、放在KPI中进行考核,效果是不容小觑的。
  自动化效果体现
  1、测试前置效果体现
  2、测试范围效果体现
  3、Daily Test 和批量执行效果体现
  4、其他指标
  PPT解读: 1、接口和单测可以通过BUG数量进行衡量。这个阶段所发现的BUG含金量更高,修复的成本更低,更有价值。此外代码行数、用例数量、代码覆盖率也可以很好的统计测试实际的效果。
  2、自动化可以解决以往手工不能进行的测试,比如大数据量、中间件、随机数据等测试,可以列举由于引进自动化而增加的各种测试类型。
  3、100个用例执行一次体现不了什么,但是100个用例在后续的两个月里执行了100次,所替代的人工就是很可观的。自动化项目坚持每日BUILD,一方面可以及时发现问题,维护更新用例。另一个方面每日测试的汇总数据也是自动化测试效果的展示。可以通过邮件、报告进行测试项目和用例的数据汇总,如果达到一定的量级还是很震撼的。
  4、自动化还有代码行数,编译次数等指标。放在部署有平均部署时间,放在数据有平均一次生成数据量等。前端自动化不宜用BUG数量来衡量,因为主要选取的相对比较稳定的业务线和模块。
  自动化开展的步骤
  1、特殊测试需求响应
  2、重点业务线全局自动化
  3、其他业务线局部自动化
  4、流程性约束
  5、技术分享和外部推广
  PPT解读: 自动化的开展需要的有重点、分步骤的进行。既要保证效果,又要体现团队的技术提升,分成两条线,各不冲突。
  1、对于特殊的测试需求,比如大数据量、中间件、复杂的底层服务和技术接口、高性能组件等对技术能力要求较高的测试需求由专门的自动化组来承担。一方面集中优势力量可以快速完成任务,另一方面挑战性的任务可以实践和摸索新的测试方法,积累新的技术经验。
  2、重点业务线可以选择一个,偏中间件和接口,或者功能测试人员尚未覆盖的业务线,由自动化组承担。目前的人力来看,可以独立承担一个业务模块全部测试,避免混用投放功能测试人员和自动化测试人员。作为试验田从代码编写到最后的上线,由自动化全覆盖,进行整体流程的尝试和布局,方便快速产生短期效果。自动化人员也可以避免不会长期脱离业务线。
  3、其他业务线在统一培训之后,使用框架根据自己的业务特点在局部开展自动化,各自形成独立的项目。后续会尝试接入Matrix或者开发自己的平台和容器,进行整体项目群的维护和管理。随着自动化覆盖度的慢慢提升,长期效果将会展现。
  4、长期效果的展现的同时需要在测试流程上进行一些制约,比如测试报告上面增加自动化的选项和测试覆盖,比如开发提测前需要先进行自动化的冒烟测试等,保证自动化长期有效的实施。
  5、整个技术团队有了自动化显著提升,可以推广到其他团队,可以进行跨部门的技术交流。
  自动化目前还需要什么样的条件
  1、稳定的测试环境
  2、独立的业务线
  3、多样的技术测试人才
  4、团队共识 PPT解读: 1、测试环境的稳定是自动化成败的关键。不稳定环境会使效果大打折扣,掩盖本应该发现的很多功能问题,会使自动化的实施有很强挫败感。同时本地调试和远程批量运行,同样对环境的稳定性有较高的要求。如果有足够的条件,可以为自动化量身一套环境,测试数据相对独立,也避免和手工测试互相干扰。
  2、专门的自动化测试人员需要拥有独立的业务线,一方面防止长期脱离业务,闭门造车。另一方面可以在业务线上不受干扰的实施自己的思路。
  3、需要更多的测试人才。内部挖潜,从目前来看,难度很大,很多人在技术方面是一张白纸,也无法为技术测试提供更多的支持。如果有社招的机会,选才第一标准还是技术,标准定得高一些,好的技术人才还是非常难得的,相较业务也需要很长的时间才能培养出来。随着自然的新陈代谢,整个团队的技术水准也会有所提升。
  4、从领导到员工对自动化开展要尽量达成共识,大家有共同的努力方向。一个人的成功不算成功,团队提升才是最重要的。虽然每个人的水平有高有低,但是本着不抛弃不放弃的原则,希望带动每个人都有所成长。让周围人变的足够优秀,让测试快乐起来,才是我们做自动化的真正意义。
本文出自 hanlingzhi 的51Testing软件测试博客:http://www.51testing.com/?547282
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。

posted @ 2014-01-16 11:36 顺其自然EVO 阅读(642) | 评论 (0)编辑 收藏

AndroidPN真机环境测试

  一:AndroidPN环境配置
  AndroidPN框架实现了从服务器到android移动平台的文本信息推送。下面是AndroidPN的环境配置
  1.先确保本机已经配置好了java环境
  2.下载androidpn-client-0.5.0.zip和androidpn-server-0.5.0-bin.zip
  网址:http://sourceforge.net/projects/androidpn/
  解压两个包,Eclipse导入client,配置好目标平台,打开raw/androidpn.properties文件,
  apiKey=1234567890
  xmppHost=10.0.2.2
  xmppPort=5222
  如果是模拟器来运行客户端程序,把xmppHost配置成10.0.2.2 (模拟器把10.0.2.2认为是所在主机的地址,127.0.0.1是模拟器本身的回环地址).
  如果是真机,配置成本机的IP地址 比如我在局域网内的IP是192.168.1.101
  xmppPort=5222 是服务器的xmpp服务监听端口(注意5222端口貌似是固定的,我改成其他端口就行了)
  二:运行测试
  从命令行运行androidpn-server-0.5.0\bin\run.bat启动服务器(有些朋友说会一闪而过启动不了,注意要从命令行进入该目录了在运行),从浏览器访问http://127.0.0.1:7070/index.do (androidPN Server有个轻量级的web服务器,在7070端口监听请求,接受用户输入的文本消息)
  运行客户端,客户端会向服务器发起连接请求,注册成功后,服务器能识别客户端,并维护和客户端的IP长连接
  进入Notifications界面,输入消息发送
  真机客户端接受到server推送来的消息
  最后,我把AndroidPN服务器配置的VPS进行测试,同样的测试成功!

这样AndroidPN的环境就搭好了。真机环境也测试通过
  问题:
  1.asmack的包太大,3百多K。
  2.只是完成Android的Push功能使用XMPP协议感觉很笨重。
  3.androidpn服务器端的负载很难控制,除非自己改写。
  第一个问题关系不大,毕竟一个软件多了300多K不算什么,如果自己来控制socket连接,我估计没有100K也很难控制好。
  第二个问题确实如此,使用XMPP的后果是带来了60%的信息冗余量
  第三个问题,负载的控制应该来说,用到socket都必须要考虑的,负载方面,androidpn用到了MINA这个socket框架,而在socket的处理方面,很多人都是用的socket来处理的。
  总的来说,源代码的开放是最大的优点,就算用到androidpn,无论如何也是要在原有的基础上进行修改的,照搬照抄肯定是不行的。但是比自己用socket来控制,在服务器和客户端之间建立一个网关,要来的容易。
  注意:需将lib 冲命名 改为libs,然后在build path里面导入libs这个包,否则会报类找不到的错误
  首先,基础中的基础,就是按照第一篇日志中所说,使用模拟器完成web推送。这一块非常简单,按照第一篇去做完全可行,可能出错的地方就是你忘记更改配置文件了。
  后来我下载了第二篇日志中博主提供的tomcat版本服务端,放在自己本机tomcat下,并且启动。用模拟器去测试发现无法推送,配置文件也没有错。检查后发现,原来自己tomcat的端口是8080,而server中配置的是7070。只要打开config.properties,修改admin.console.port=端口号,即可。
  再接着,用同一个局域网内其他机子的客户端模拟器进行测试,只要将androidpn.properties中的xmppHost=服务端所在内网IP就可以啦。比如192.168.1.150。
  用真机测试,其实和模拟器没啥区别,只要配置文件不写错,原则是不会出问题的。但是我测试的时候,还是出现无法推送成功的问题。仔细检查后,原因有二。
  1.客户端android版本太低,换个android4.0版本就可以。貌似是不兼容低版本。
  2.真机上其他的应用中,也有应用到这个androidpn的。其中,在androidpn.properties中,apikey默认是123456789。因为那个应用和我自己本机都选择了默认的,所以我将自己这里的apikey改掉了。切记!这里有一点需要注意的,客户端androidpn.properties中更改了apikey,服务端config.properties也要随之修改。!!
  OK,基本上单独的web推送就完成了。
  接下来就是整合到自己项目中,也就是从自己项目后台将数据推送到客户端,至于androidpn的server端,则作为中间的桥梁。
  这里需要注意一点,androidpn会在你本地数据库中新增一个表apn_user。如果你本地数据库有权限,拒绝的话,你最好自己先手动增加这么一张表。
  首先,我单独启动一个新的tomcat,将server端部署到这下面,修改配置文件config。properties,jdbc.properties。jdbc.properties这个文件是配置你本地数据库的参数的,不能有错。启动后,简单测试成功,在自己项目中使用http协议将数据POST到server端这个org.androidpn.server.console.controller.NotificationController类的send方法中。具体参数名称及获取参数的代码,可以修改server端。
  在这里插一句,不论时间多么紧张,至少你得追一边代码,尤其这个类。
  代码写好后可以执行,断点跟踪下,只要你代码正确,配置文件没错,是可以正常推送的。
  基本上,写到这里的话,应该可以满足项目需求了。如果你还需要将哪些用户在线的功能整合到你自己项目中。那你就得自己跟踪下代码了。
  我项目做到这里,基本上都是在windows环境下。将项目部署到linux环境下,又出问题了。
  路径问题比较容易坚决,按照后台日志中提示的地方,将路径修改下。
  关键是在linux下重启server端,会发现报错,5222端口被占用。因为时间限制,能力有限,没办法修改代码,只能每次重启时,都先用命令将5222端口杀掉。

posted @ 2014-01-16 11:35 顺其自然EVO 阅读(3592) | 评论 (2)编辑 收藏

Android手机自动化测试工具有哪几种?

 基于优秀的图像对比库opencv的测试工具,测试脚本使用Python编写,非常强大。如果你的app没有源码,可以选择它;或者你想做系统测试(跨app的测试),也可以选择它。其它的还是用下面说的那些个吧。
  我通过其核心包sikuli-script.jar实现了android的sikuli化,暂时不打算开源。其实原理挺简单的,认真看过sikuli源码的应该都能写出来。
  看lz的意思应该只是想问应用层的,我来说点应用层的
  先说说开源的吧:
  Robotium
  Monkeyrunner
  Robolectric
  CTS
  还有个新兴的测试工具,以前在GitHub看到,现在找不到了,好像是BDD类型的语法;现在还不成熟。
  另外基于web的测试也有基于Selenium Webdriver 的 Android WebDriver:
  有两种:
  基于Remote Server的:官方提供了java接口的,但是Python版的官方里面却没有。我非常喜欢Python,所以自己实现了并且开源到了GitHub:https://github.com/truebit... 有问题大家可以提到上面
  基于Instrumentation的:已经在Android SDK r14里面可以安装了
  不开源的就多了,不过我见过的一般是以下几种思路:
  1. 基于Android Java Instrumentation框架:
  基于Robotium,比如bitbar的产品:http://bitbar.com/products
  基于Instrumentation,那就海了去了,很多公司自家写的工具都基于这个;另外Robotium就是基于这个的
  2. 基于Android lib层的各种命令,比如sendevent,getevent, monkey, service这些,然后用各种语言封装
  MonkeyRunner还是很有前景的,Google自己弄的。现在最新的dev版本已经有支持UI的id操作的EasyMonkey了。可以git clone git://android.kernel.org/platform...看看

posted @ 2014-01-16 11:20 顺其自然EVO 阅读(1590) | 评论 (0)编辑 收藏

soapUI中多个TestCase之间传递参数

 SoapUI中可以定义一个个的测试用例TestCase,但是有些用例是依赖于之前的用例的,如果纯拷贝的话可能会导致用例比较臃肿而且不好维护,比如说存在如下两个TestCase:
  1)CreateUserTestCase:测试创建用户,通过发送Soap报文方式创建用户同时需要校验数据库中值是否正确
  2)ChangUserInfoTestCase:测试修改用户信息,通过发送Soap报文方式修改用户信息,需要校验修改前和修改后的用户信息
  ChangUserInfo之前必须得创建一个用户,纯拷贝肯定是不可取的,因为后续如果创建用户的接口稍有变动,则需要同时在ChangUserInfoTestCase和CreateUserTestCase修改请求报文。
  SoapUI在TestCase中提供Run TestCase的Step,可以直接调用指定的TestCase,但是需要前一个TestCase中将属性传递出来,步骤如下:
  1)在被调用TestCase中设置返回属性
  testRunner.testCase.setPropertyValue("属性名称",“属性值”)
  2)在调用TestCase中增加Run TestCase指向被调用TestCase
  3)在调用TestCase中的其它Test Step中获取属性
  例如:在CreateUserTestCase中将创建好的用户ID传给ChangUserInfoTestCase,则步骤如下:
  1)在CreateUserTestCase中通过Groovy Script. 设置返回属性:
  testRunner.testCase.setPropertyValue("UserID",context.getProperty("UserID"))
  2) 在ChangUserInfoTestCase中增加Run TestCase:RunNewUserTestCase指向CreateUserTestCase并指定UserID属性为输入值
  3)在ChangUserInfoTestCase中获取执行CreateUserTestCase得到的用户ID
def NewUserProperties = testRunner.testCase.getTestStepByName( "RunNewUserTestCase" );
log.info(NewUserProperties .getPropertyValue( "UserID" ))
本文出自 wendy-qian 的51Testing软件测试博客:http://www.51testing.com/?15017055

posted @ 2014-01-16 11:17 顺其自然EVO 阅读(3979) | 评论 (0)编辑 收藏

质量管理的十三项步骤和八项原则

 八项质量管理原则
  为了成功地领导和运作一个组织,需要采用一种系统和透明的方式进行管理。针对所有相关方的需求,实施并保持持续改进其业绩的管理体系,使组织获得成功。组织为实现质量目标,应遵循以下八项质量管理原则。
  原则1: 以顾客为中心
  组织依存于其顾客。因此,组织应理解顾客当前的和未来的需求,满足顾客要求并争取超越顾客期望。
  1、 组织实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则2: 领导作用
  领导将本组织的宗旨、方向和内部环境统一起来,并创造使员工能够充分参与实现组织目标的环境。
  1、 组织实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则3: 全员参与
  各级人员是组织之本。只有他们的充分参与,才能使他们的才干为组织带来最大的收益。
  1、 织实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则4: 过程方法
  将相关的资源和活动作为过程进行管理,可以更高效地得到期望的结果。
  过程方法的原则不仅适用于某些较简单的过程,也适用于由许多过程构成的过程网络。在应用于质量管理体系时,2000版ISO9000族标准建立了一个过程模式。此模式把管理职责、资源管理、产品实现、测量、分析与改进作为体系的四大主要过程,描述其相互关系,并以顾客要求为输入,提供给顾客的产品为输出,通过信息反馈来测定的顾客满意度,评价质量管理体系的业绩。
  1、 实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则5: 管理的系统方法
  针对设定的目标,识别、理解并管理一个由相互关连的过程所组成的体系,有助于提高组织的有效性和效率。
  ISO/DIS9000的3.3列出了建立和实施质量管理体系的十三个步骤:
  1、 实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则6: 持续改进
  持续改进是组织的一个永恒的目标。
  1、 实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现

  原则7: 基于事实的决策方法
  对数据和信息的逻辑分析或直觉判断是有效决策的基础。
  以事实为依据做决策,可防止决策失误。在对信息和资料做科学分析时,统计技术是最重要的工具之一。统计技术可以用来测量、分析和说明产品和过程的变异性。统计技术可以为持续改进的决策提供依据。
  1、 实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  原则8: 互利的供方关系
  通过互利的关系,增强组织及其供方创造价值的能力。
  供方提供的产品将对组织向顾客提供满意的产品可能产生重要的影响,一次处理好与供方的关系,影响到组织能否持续稳定地提供顾客满意地产品。对供方不能只讲控制,不讲合作互利。特别对关键供方,更要建立互利关系。这对组织和供方双方都是有利的。
  1、 实施本原则的主要利益
  2、 组织实施本原则时一般要采取的主要措施
  3、 本原则在标准中的体现
  十三个步骤

posted @ 2014-01-16 11:16 顺其自然EVO 阅读(258) | 评论 (0)编辑 收藏

SQL Server还原数据库操作详细步骤

 还原数据库
  企业管理器
  --右键"数据库"
  --所有任务
  --还原数据库
  --"还原为数据库库"中输入还原后的数据库名
  --还原选择"从设备"--选择设备--添加--添加你的备份文件--确定,回到数据库还原的界面
  --备份号--选择内容--选择你要恢复那次备份的内容
  --选项--将"移至物理文件名"中的物理文件名修改为你的数据文件要存放的文件名
  --如果要还原的数据库已经存在,选择"在现有数据库上qz还原"-
  -确定
  --或用SQL语句:
  restore database 数据库 from disk='c:\你的备份文件名'
  还原数据库
  企业管理器中的操作:
  1.进行完整恢复
  企业管理器--右键"数据库"--所有任务--还原数据库
  --"还原为数据库库"中输入还原后的数据库名,设为:test
  --还原选择"从设备"--选择设备--添加--添加你的备份文件
  --确定,回到数据库还原的界面
  --"还原备份集",选择"数据库--完全"
  --选项--将"移至物理文件名"中的物理文件名修改为你的数据文件要存放的文件名
  --如果要还原的数据库已经存在,选择"在现有数据库上qz还原"
  --"恢复完成状态",选择"使数据库不再运行,但能还原其它事务日志"
  --确定
  --或用SQL语句:
  restore database 数据库 from disk='c:\你的完全备份文件名' with norecovery
  2.进行差异恢复
  企业管理器--右键"数据库"--所有任务--还原数据库
  --"还原为数据库库"中选择数据库名:test
  --还原选择"从设备"--选择设备--添加--添加你的备份文件
  --确定,回到数据库还原的界面
  --"还原备份集",选择"数据库--差异"
  --"恢复完成状态",选择"使数据库不再运行,但能还原其它事务日志"
  --确定
  --或用SQL语句:
  restore database 数据库 from disk='c:\你的差异备份文件名' with norecovery
  3.进行日志恢复
  企业管理器--右键"数据库"--所有任务--还原数据库
  --"还原为数据库库"中选择数据库名:test
  --还原选择"从设备"--选择设备--添加--添加你的备份文件
  --确定,回到数据库还原的界面
  --"还原备份集",选择"事务日志"
  --"恢复完成状态",选择"使数据库可以继续运行,但无法还原其它事务日志"
  --确定
  --或用SQL语句:
  restore log 数据库 from disk='c:\你的日志备份文件名' with recovery
  --解决还原数据库目录不对的详细步骤:
  1.企业管理器中的方法:
  --右键"数据库"
  --所有任务
  --还原数据库
  --"还原为数据库库"中输入还原后的数据库名
  --还原选择"从设备"--选择设备--添加--添加你的备份文件--确定,回到数据库还原的界面
  --备份号--选择内容--选择你要恢复那次备份的内容
  --选项--将"移至物理文件名"中的物理文件名修改为你的数据文件要存放的文件名
  --如果要还原的数据库已经存在,选择"在现有数据库上qz还原"-
  -确定2.用SQL语句的方法(假设你的备份文件名为: c:\xx.bak
  --列出备份文件中的逻辑文件名
  restore filelistonly from disk='c:\xx.bak'
  --用语句恢复,根据上面列出的逻辑文件名使用move选项
  restore database 恢复后的数据库名
  from disk='c:\xx.bak'
  with move '逻辑数据文件名1' to 'c:\物理数据文件名1'
  ,move '逻辑数据文件名2' to 'c:\物理数据文件名2'
  ...
  ,move '逻辑数据文件名n' to 'c:\物理数据文件名n'
  没有什么要特别注意的,和企业版之间的备份/还原要注意的东西一样:
  1.要注意备份时的设置问题,不要指定多个备份文件,否则还原时也要指定多个备份文件
  2.要注意备份的媒体处理方式问题,用重写,而不是追加,否则还原的时候要指定备份号
  3.要注意备份的方式,用完全备份,而不是其他备份方式,否则还原时还要其他备份文件支持

posted @ 2014-01-16 11:14 顺其自然EVO 阅读(797) | 评论 (0)编辑 收藏

Linux环境下oracle client安装和配置

 oracle客户端的安装是非常简单的,关键在tns配置,我这里使用的rpm安装包,oracle本身就不是开源,那使用rpm安装时最简单的。
  1.要远程使用oracle,先下载下面三个文件,注意版本最好一致。
oracle-instantclient-basic-10.2.0.4-1.i386.rpm
oracle-instantclient-sqlplus-10.2.0.4-1.i386.rpm
oracle-instantclient-devel-10.2.0.4-1.i386.rpm
  2.PM安装
oracle-instantclient-basic-10.2.0.4-1.i386.rpm是基本的动态库、jar包,默认安装路径是:/usr/lib/oracle/10.2.0.4/client
oracle-instantclient-sqlplus-10.2.0.4-1.i386.rpm是客户端sqlplus安装包, 默认安装路径是:/usr/lib/oracle/10.2.0.4/client
oracle-instantclient-devel-10.2.0.4-1.i386.rpm是api接口文件,默认安装路径是:/usr/include/oracle/10.2.0.4/client
  这里不需要修改默认路径,直接安装即可:
sudo rpm-avi oracle-instantclient-basic-10.2.0.4-1.i386.rpm
sudo rpm-avi oracle-instantclient-sqlplus-10.2.0.4-1.i386.rpm
sudo rpm-avi oracle-instantclient-devel-10.2.0.4-1.i386.rpm
  3.配置环境变量
vi /etc/profile
export ORACLE_HOME=/usr/lib/oracle/10.2.0.4
export TNS_ADMIN=$ORACLE_HOME/network/admin
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
exportLD_LIBRARY_PATH=$ORACLE_HOME/client/lib:$LD_LIBRARY_PATH
exportOCI_HEADERS_HOME=/usr/include/oracle/10.2.0.4/client
export OCI_LIBS_HOME=$ORACLE_HOME/client/lib
  后面两项是为了我们的程序程序编译时使用方便,编译时直接加入选项:
  -I$( OCI_HEADERS_HOME) –L$( OCI_LIBS_HOME) –l occi
  4.配置监听器和网络环境
[huangxw@ubuntu admin]$
cat/usr/lib/oracle/10.2.0.4/network/admin/tnsnames.ora
test_base=
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = *.*.*.*)(PORT = ****))
)
(CONNECT_DATA =
(SERVICE_NAME = tt4adol)
)
)
  5.测试连接
[huangxw@ubuntu bin]$./sqlplus USERNAME/PASSWD@test_base
SQL*Plus: Release 10.2.0.4.0 - Production onMon Jan 13 10:09:31 2014
Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining andReal Application Testing options
SQL> select * from USERNAME.TABLENAME  where accountid = 8401428;
ACCOUNTID   INVTA     SNDA    RAINA   INSB    SPEN    REMN
---------- ---------- ---------- -------------------- ---------- ----------
INVTC     SPDC    REIN
---------- ---------- ----------
8401428          0          0    100000          0          0          0
0          0          0

posted @ 2014-01-16 11:11 顺其自然EVO 阅读(1389) | 评论 (0)编辑 收藏

LoadRunner监控Windows资源

1.监控准备:
  监控方:
  1)安装tcp/ip协议下的netbios
  2)用administrator登录
  被监控方:
  1)被监控的Windows开启两个服务:
  Remote ProcedureCall(RPC)和Remote Registry Service
  开启位置:右键“我的电脑”->管理->服务和应用程序->服务
  2)被监控的Windows中要有C$共享文件夹
  查看位置:右键“我的电脑”->管理->共享文件夹->共享,在这里面要有C$这个共享文件夹,要是没有自己手动加
  3)被监控的Windows有管理员的权限,包括用户名和密码
  4)修改网络安全设置:
  (组策略gpedit.msc windows设置-安全设置-本地策略-安全选项-右侧网络访问-本地帐户的共享和安全模式->修改为“经典”,默认是“仅来宾”,这个对应注册表键值:”forceguest”=dword:00000000;
  注:这一步可以先不操作,如果在LR添加Windows监控,会报错时再操作,你可以自己形成一个.reg文件如test.reg,然后双击修改对应注册表的值。test.reg.reg具体输入内容为:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa]
“forceguest”=dword:00000000
  或者采用手动修改的方式实现
  5)验证是否可以连接:
  在安装LR的机器上使用运行.输入被监视机器IPC$,如192.168.133.99C$然后输入管理员帐号和密码,如果能看到被监视机器的C盘了,就说明你得到了那台机器的管理员权限,可以使用LR去连接了,不过这步有可能提示“找不到网络路径”,可以先不管,在LR上面尝试添加监控,看看效果,可以的话就OK了
  2.用LR监视windows资源
  这个比较简单,直接添加度量即可,如果有弹出windows资源选择对象的窗口即成功了:
  鼠标选择windows资源监视窗口,点击右键弹出菜单中选择“ADDMeasurements..”
  点“添加”把监视的服务器ip地址输入,点确定
  如果可以正常联机到服务器,则在资源度量中会显示全部计数器,此时如果点“确定”则系统默认全部选中,在监视窗口中会显示所有性能曲线,无法单独过滤显示某条曲线,如果选中某个计数器后点“添加”则弹出该项目下的其它性能指标,选择需要的计数器后点“添加”
  此时要注意,你登陆客户端(也就是你装有loadrunner机器)的用户应该是管理员身份,同时还要保证该用户在被监视的服务器上也是管理员身份。这样选择虽然监视窗口中仍会显示所有性能曲线,但是可以通过鼠标右键弹出菜单,选中你指定的某条曲线单独显示。方法是双击监视窗口放大显示,然后右键选择“仅显示指定图”监视窗口还可以互相叠加等操作,功能强大,通过右键菜单选择可以进行复杂显示操作。常用的还有web程序服务器图、数据库服务器资源图等,添加方法雷同。 3. Windows资源监控参数分析

posted @ 2014-01-15 10:28 顺其自然EVO 阅读(1910) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 159 160 161 162 163 164 165 166 167 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜