qileilove

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

嵌入式linux的tftp安装配置及tftp命令用法

TFTP协议简介
  TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现。嵌入式linux的tftp开发环境包括两个方面:一是linux服务器端的tftp-server支持,二是嵌入式目标系统的tftp-client支持。因为u-boot本身内置支持tftp-client,所以嵌入式目标系统端就不用配置了。下面就详细介绍一下linux服务器端tftp-server的配置。
  1、安装tftp服务器
  需要安装xinetd、tftp和tftp-server 3个软件
  1)如果能上网,通过yum安装:
  sudo yum install xinetd
  sudo yum install tftp
  sudo yum install tftp-server
  2)如果不能上网,可以直接安装提供的rpm包:
  sudo rpm -ivh xinetd-2.3.14-18.fc9.i386.rpm
  sudo rpm -ivh tftp-0.48-3.fc9.i386.rpm
  sudo rpm -ivh tftp-server-0.48-3.fc9.i386.rpm
  2、配置tftp服务器
  修改/etc/xinetd.d/tftp文件,将其中的disable=yes改为disable=no。
  主要是设置TFTP服务器的根目录,开启服务。修改后的文件如下:
service tftp
{     socket_type            =dgram
protocol                  =udp
wait                        =yes
user                        =root
server                     =/usr/sbin/in.tftpd
server_args             =-s  /home/mike/tftpboot -c
disable                    =no
per_source             =11
cps                         =100 2
flags                       =IPv4
}
  说明:修改项server_args= -s     <path>    -c,其中<path>处可以改为你的tftp-server的根目录,参数-s指定chroot,-c指定了可以创建文件。
  3、启动tftp服务器并关闭防火墙
  /etc/init.d/iptables stop        //关闭防火墙
  sudo /sbin/service xinetd start
  或 service xinetd restart
  /etc/init.d/xinetd start
  看到启动[OK]就可以了
  4、查看tftp服务是否开启
  netstat -a | grep tftp
  显示结果为
  udp 0 0 *:tftp *:*
  表明服务已经开启,就表明tftp配置成功了。

 5、tftp使用
  复制一个文件到tftp服务器目录,然后在主机启动tftp软件,进行简单测试。
tftp 192.168.1.2
tftp>get <download file>
tftp>put <upload file>
tftp>q
  6、tftp命令用法如下
  tftp     your-ip-address
  【进入TFTP操作】
connect:连接到远程tftp服务器
mode:文件传输模式
put:上传文件
get:下载文件
quit:退出
verbose:显示详细的处理信息
tarce:显示包路径
status:显示当前状态信息
binary:二进制传输模式
ascii:ascii 传送模式
rexmt:设置包传输的超时时间
timeout:设置重传的超时时间
help:帮助信息
? :帮助信息
  7、如果老是出现“AVC Denial, click icon to view”的错误,并不能传输文件,需要作如下修改
  修改/etc/sysconfig/selinux,将SELINUX设定为disable
  使用命令setenforce 0让selinux配置文件生效
  8、Busybox中tftp命令的用法
  命令格式为:
  tftp [option] ... host [port]
  如果要下载或上传文件的话是一定要用这些option的。成都明诚科技。
  -g 表示下载文件 (get)
  -p 表示上传文件 (put)
  -l 表示本地文件名 (local file)
  -r 表示远程主机的文件名 (remote file)
  例如,要从远程主机192.168.1.2上下载 embedexpert,则应输入以下命令
  tftp -g  -r embedexpert 192.168.1.2

posted @ 2013-12-20 09:26 顺其自然EVO 阅读(625) | 评论 (0)编辑 收藏

如何做好测试分析

 以前在某公司离职时,老大建议我写一个测试分析方法的文档,当时时间比较近只是做了一个分析图和简单的描述,今天整理以前的文档拿出来和大家再次分享并完善了一下内容。
  上面这个测试分析图展示的在一个全新的项目开始准备测试时,如果进行测试分析的基本方法。
  在开始接手一个新项目时,按照基本的测试生命周期流程(编写测试计划-测试方案-准备测试环境-编写测试用例-编写测试脚本-执行测试-反馈缺陷-调整或完善测试用例-回归测试-收集测试结果-编写测试报告)
  在编写测试计划和测试方案前,应该还有个测试初始阶段-主要工作就是了解和分析系统,这是一个学习成本。在传统的开发方法和敏捷开发方法这个阶段的启动时间不同,在传统的开发方法中可能要等待需求说明书出来之后进行测试需求的分析,来确定测试范围,根据范围编写测试计划。 敏捷开发方法由于测试人员在需求讨论,那么了解和分析系统的事情在敏捷的需求讨论时就完成,而不在需要再等待需求说明书等需求文档。
  不管是传统或是敏捷的开发方法,测试初始阶段都是理解测试需求,根据理解的需求准备相关的测试工作。 那么如何理解需求并根据需求来编写测试计划和测试方案?这就是本文重点要阐述的一些方法:
  1、确定范围,任何产品的需求无非两种类型:功能需求和非功能需求
  测试需求范围确定按照测试不同阶段进行分层划分为:单元测试范围、集成测试范围、系统测试范围、验收测试范围;
  单元测试范围通常包括:单元功能正确性测试、单元功能容错性测试、单元代码结构性测试、单元测试代码性能测试
  集成测试范围包括:模块或服务功能正确性,模块或服务接口一致性、模块或服务容错性、模块或服务的性能等
  系统测试范围包括:系统可用性测试、系统稳定性测试、系统安全性测试、系统业务能力测试等等
  当然还有用户验收测试: 用户核心业务支持能力测试等等
  2、确定测试点,也就是确定测试具体内容:
  测试通常是有测试参照物,例如需求分析,概要设计,详细设计等。
  如何确定测试点,也就是如何分析测试需求并找出测试规则, 根据不同的系统对测试人员的技能也有不同的要求:
  例如:
  测试一个业务系统,在集成测试和系统测试、验收测试阶段的测试点分析和提取,测试人员需要充分的了解这个系统要支撑的业务规范或规则,例如保险系统,证券系统,ERP系统等等。 这类系统测试要求测试人员更偏重于业务的知识。举个证券的清算系统,测试它就要业务清算规则和流程。
  测试一个技术性系统,例如云计算的测试,BI系统的测试,中间件的测试,网关系统的测试, 这类系统的技术性比较强,他的测试点或测试规则对应的是技术规范或技术规则。比如多媒体消息网关系统的测试,需要多种消息的传递和路由规则。不同协议消息的构造和解析规则。 些测试对测试人员的技术要求更强。
3、测试执行准备和场景设计时 ,也就是设计测试用例和测试场景时要充分考虑系统的技术特点。
  根据系统的设计和技术特点,来决定如何测试一个测试点或一个测试规则、一个场景。
  根据测试点和系统架构和技术输入,要有如下输入:
  1)测试上下文环境准备
  2)测试数据构造(测试数据按照类型分为,直接输入数据、规则数据、背景数据)
  3)测试调用方法
  4) 测试结果验证方法和测试结果截取方法
  4、确定工作量
  测试分析基本是由大到小,由外到里的分析方法
  确定大范围,规则细分,技术确认 最后就要估算测试工作量
  通常估算单个测试点的工作量再汇总的方式比较准确。
  小结: 测试分析能力是保证被测试系统被正确测试的保证, 测试分析就要确定测试范围和测试方法。 范围和方法决定了测试的正确性与否。 针对不同系统的测试分析时,对测试人员的技能有专向要求和知识储备。不要希望业务系统测试人员,能够做好云系统的测试。

posted @ 2013-12-20 09:24 顺其自然EVO 阅读(428) | 评论 (0)编辑 收藏

Android monkeyrunner自动化测试

 monkeyrunner测试主要是通过编写一个Python程序去安装一个Android应用程序或测试包,运行它,向它发送模拟击键,截取它的用户界面图片,并将截图存储于工作站上。由于SDK是旧版本,暂时无法获取自定义屏幕上的组件焦点,所以通过截取屏幕的方式获取组件的位置坐标,然后利用触摸的方式点击组件。
  关于monkeyrunner自动化测试网上的例子太多了,而且都是转载的,基本上都是对官方文档的翻译,所以遇到很多问题都无法解决。下面附上一些简单的例子。
#导入程序测试所需要的模块
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
#连接当前对象,返回一个MonkeyDevice对象
device = MonkeyRunner.waitForConnection()
#安装所要测试的android应用程序或测试包
device.installPackage('*******.apk')
#运行指定的Activity
device.startActivity(component='com.mzba.test.TestActivity')
#触摸自动登录复选框
device.touch(222,388,'DOWN_AND_UP')
#触摸记住密码复选框
device.touch(37,421,'DOWN_AND_UP')
#触摸登录按钮
device.touch(271,475,'DOWN_AND_UP')
#测试暂停3秒钟
MonkeyRunner.sleep(3.0)
#截取屏幕截图
result = device.takeSnapshot()
#将截图保存至文件
result.writeToFile('login.png','png')
  不过更新了sdk以后,发现press方法无法使用了,报错如下:
  device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')  TypeError: press: The 3rd argument is required
  所以要换成另一种方法:
device.press('KEYCODE_DPAD_DOWN', MonkeyDevice.DOWN_AND_UP)
更新了SDK的版本,增加了EasyMonkeyDevice的相关类,已经可以利用控件的id来进行交互。
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
from com.android.monkeyrunner.easy import EasyMonkeyDevice
from com.android.monkeyrunner.easy import By
device = MonkeyRunner.waitForConnection()
easy_device = EasyMonkeyDevice(device)
easy_device.startActivity(component='com.xuanwu.etion/.SplashActivity')
#输入用户名
device.type('mzba')
#触摸密码框,相当于获取焦点
easy_device.touch(By.id('id/login_edit_pwd'), MonkeyDevice.DOWN_AND_UP)
#输入密码
device.type('888888')
#按下返回键,相当于关闭输入法的弹出框
device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
#easy_device.touch(By.id('id/login_edit_account'), MonkeyDevice.DOWN_AND_UP)
#点击登录按钮
easy_device.touch(By.id('id/login_btn'), MonkeyDevice.DOWN_AND_UP)
  附上官方文档:
  http://develo...concepts.html

posted @ 2013-12-20 09:23 顺其自然EVO 阅读(324) | 评论 (0)编辑 收藏

Android测试驱动开发实践2

 在实际项目开发过程中,一般先实现核心功能,最后再做辅助性功能,这样可以尽快验证Idea的正确性,同时有助于让老板、投资人或客户看到可运行的产品,从而对产品充满信心,加大对项目的支持。
  但是对于我们这个项目而言,我们首先需要得到一个Android应用MVC的架构体系,因此我们首先来实现一些典型功能,但是可以完整体现MVC架构的功能。在此我们选择任何应用程序在启动时都会显示的Splash页面,通常这个页面会显示一个应用图片,过30秒左右再显示程序的主界面,应用在这段时间完成数据加载等准备工作
  在这里我们要稍微背离一下测试驱动开发的标准方法,原因是我们在进行Android应用开发,由于Android系统限制有很多方面是很难做单元测试的,硬做单元测试,除了理论上的有效性外,没有任何实际意义。
  在这里,我们采用验收测试驱动开发的理念,即我们开发足够功能来满足一个验收测试用例。这里我们选择的一个验收测试用例为:应用在开启时,先显示10秒应用图片,然后自动进入应用首页,也就是我们通常所看到的Splash屏幕功能。
  我们首先定义SplashActivity类,代码如下所示:
package com.bjcic.wkj;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.WindowManager;
public class SplashActivity extends Activity {
// 生命周期方法---开始
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//全屏
setContentView(R.layout.splash);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
appModel = (AppModel)getApplication();
appController = appModel.getAppController();
appController.postDelayed(new Runnable() {
/**
* 隔10秒钟启动主页面
*/
@Override
public void run() {
appController.processEvent(new AppEvent(SplashActivity.this, AppEvent.EVE_SPLASH_END, null));
}
}, AppKeys.SPLASH_DURATION);
// 启动异步任务准备应用数据
}
// 生命周期方法---结束
private AppController appController = null;
private AppModel appModel = null;
}
这个Activity所对应的布局文件为:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/splash">
</LinearLayout>
  布局文件就是定义了一下Splash屏幕的背景图。
  这里我们引入了AppController类,是应用的控制器类。Activity中用户的操作和系统的状态改变都会生成相应的事件,由AppController.processEvent来进行统一处理,同时异步任务、线程等产生的需要界面更新的操作,通过向AppController发送Message来实现(因为AppController继承了Handler类)。具体代码如下所示:
package com.bjcic.wkj;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class AppController extends Handler {
public AppController(AppModel appModel) {
super();
this.appModel = appModel;
}
/**
* Activity中会根据用户的操作或系统状态,产生对应的事件,发送给AppController进行统一处理。
* @param event
*/
public void processEvent(AppEvent event) {
switch (event.getEventId()) {
case AppEvent.EVE_SPLASH_END: // 从Splash界面显示主界面
showMainActivity((Activity)event.getContext(), event.getParams());
break;
default:
break;
}
}
/**
* 异步任务、线程、后台服务等需要更新界面时,向AppController发送消息即可
*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
/**
* 关闭Splash页面并打开应用主界面
* @param activity
* @param params
*/
private void showMainActivity(Activity activity, Bundle params) {
Log.d("wkj", "activity=" + activity + "; c=" + MainActivity.class + "!");
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
activity.finish();
}
private AppModel appModel = null;
}
 在上面的代码中,事件处理函数直接写在的应用总的Controller中,其实也可以写到具体的Controller中,为了代码的可维护性,最好还是将事件处理写到对应模块的Controller中比较好。
  下面就是AppEvent的定义:
package com.bjcic.wkj;
import android.content.Context;
import android.os.Bundle;
public class AppEvent {
public AppEvent(Context context, int eventId, Bundle params) {
this.context = context;
this.eventId = eventId;
this.params = params;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public Bundle getParams() {
return params;
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public final static int EVE_NONE = 0;
public final static int EVE_SPLASH_END = 1; // Splash界面显示时间到期
private Context context = null;
private int eventId = 0;
private Bundle params = null;
}
  在上面的事件定义中,事件中包含当前的Activity,事件ID和事件参数,这样AppController就可以直接对事件进行处理了。
  最后,我们在Splash页面停留10秒,这里需要定义一个常量,我们将应用中需要用到的重要常量,统一定义到AppKeys中,如下所示:
package com.bjcic.wkj;
public class AppKeys {
public final static long SPLASH_DURATION = 10 * 1000;
}
  好的,现在可以运行这个应用程序了,如果一切正常,应该可以看到一个Splash页面显示10秒钟后,进入到程序主界面中。至此我们的第一个验收测试用例就顺利通过了。
  这时,我们再回到WkjTest这个工程中,以Android Junit形式运行MainActivityTest,这时应该显示所有测试用例全部通过。
  注:大家也许注意到了,测试驱动开发是以一小步一小步的开发测试为基础的,在实际工作中,有一半愉上的程序员喜欢先把所有代码写好,然后在进行调试。当然也有一部分开发人员写一点调一点,这纯属于习惯性问题,不存在孰优孰劣的问题。但是采用测试驱动开发方法学,就要采用后面的工作方式。
  因此,测试驱动开发不一定适合所有人,对于喜欢一次性先把代码写好,然后进行调试的人来说,让他们接受测试驱动开发的工作方式是很困难的,这一点希望大家能够重视起来。
相关文章:

posted @ 2013-12-20 09:21 顺其自然EVO 阅读(221) | 评论 (0)编辑 收藏

Android测试驱动开发实践2

 在实际项目开发过程中,一般先实现核心功能,最后再做辅助性功能,这样可以尽快验证Idea的正确性,同时有助于让老板、投资人或客户看到可运行的产品,从而对产品充满信心,加大对项目的支持。
  但是对于我们这个项目而言,我们首先需要得到一个Android应用MVC的架构体系,因此我们首先来实现一些典型功能,但是可以完整体现MVC架构的功能。在此我们选择任何应用程序在启动时都会显示的Splash页面,通常这个页面会显示一个应用图片,过30秒左右再显示程序的主界面,应用在这段时间完成数据加载等准备工作
  在这里我们要稍微背离一下测试驱动开发的标准方法,原因是我们在进行Android应用开发,由于Android系统限制有很多方面是很难做单元测试的,硬做单元测试,除了理论上的有效性外,没有任何实际意义。
  在这里,我们采用验收测试驱动开发的理念,即我们开发足够功能来满足一个验收测试用例。这里我们选择的一个验收测试用例为:应用在开启时,先显示10秒应用图片,然后自动进入应用首页,也就是我们通常所看到的Splash屏幕功能。
  我们首先定义SplashActivity类,代码如下所示:
package com.bjcic.wkj;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.WindowManager;
public class SplashActivity extends Activity {
// 生命周期方法---开始
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//全屏
setContentView(R.layout.splash);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
appModel = (AppModel)getApplication();
appController = appModel.getAppController();
appController.postDelayed(new Runnable() {
/**
* 隔10秒钟启动主页面
*/
@Override
public void run() {
appController.processEvent(new AppEvent(SplashActivity.this, AppEvent.EVE_SPLASH_END, null));
}
}, AppKeys.SPLASH_DURATION);
// 启动异步任务准备应用数据
}
// 生命周期方法---结束
private AppController appController = null;
private AppModel appModel = null;
}
这个Activity所对应的布局文件为:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/splash">
</LinearLayout>
  布局文件就是定义了一下Splash屏幕的背景图。
  这里我们引入了AppController类,是应用的控制器类。Activity中用户的操作和系统的状态改变都会生成相应的事件,由AppController.processEvent来进行统一处理,同时异步任务、线程等产生的需要界面更新的操作,通过向AppController发送Message来实现(因为AppController继承了Handler类)。具体代码如下所示:
package com.bjcic.wkj;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class AppController extends Handler {
public AppController(AppModel appModel) {
super();
this.appModel = appModel;
}
/**
* Activity中会根据用户的操作或系统状态,产生对应的事件,发送给AppController进行统一处理。
* @param event
*/
public void processEvent(AppEvent event) {
switch (event.getEventId()) {
case AppEvent.EVE_SPLASH_END: // 从Splash界面显示主界面
showMainActivity((Activity)event.getContext(), event.getParams());
break;
default:
break;
}
}
/**
* 异步任务、线程、后台服务等需要更新界面时,向AppController发送消息即可
*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
/**
* 关闭Splash页面并打开应用主界面
* @param activity
* @param params
*/
private void showMainActivity(Activity activity, Bundle params) {
Log.d("wkj", "activity=" + activity + "; c=" + MainActivity.class + "!");
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
activity.finish();
}
private AppModel appModel = null;
}
 在上面的代码中,事件处理函数直接写在的应用总的Controller中,其实也可以写到具体的Controller中,为了代码的可维护性,最好还是将事件处理写到对应模块的Controller中比较好。
  下面就是AppEvent的定义:
package com.bjcic.wkj;
import android.content.Context;
import android.os.Bundle;
public class AppEvent {
public AppEvent(Context context, int eventId, Bundle params) {
this.context = context;
this.eventId = eventId;
this.params = params;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public Bundle getParams() {
return params;
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public final static int EVE_NONE = 0;
public final static int EVE_SPLASH_END = 1; // Splash界面显示时间到期
private Context context = null;
private int eventId = 0;
private Bundle params = null;
}
  在上面的事件定义中,事件中包含当前的Activity,事件ID和事件参数,这样AppController就可以直接对事件进行处理了。
  最后,我们在Splash页面停留10秒,这里需要定义一个常量,我们将应用中需要用到的重要常量,统一定义到AppKeys中,如下所示:
package com.bjcic.wkj;
public class AppKeys {
public final static long SPLASH_DURATION = 10 * 1000;
}
  好的,现在可以运行这个应用程序了,如果一切正常,应该可以看到一个Splash页面显示10秒钟后,进入到程序主界面中。至此我们的第一个验收测试用例就顺利通过了。
  这时,我们再回到WkjTest这个工程中,以Android Junit形式运行MainActivityTest,这时应该显示所有测试用例全部通过。
  注:大家也许注意到了,测试驱动开发是以一小步一小步的开发测试为基础的,在实际工作中,有一半愉上的程序员喜欢先把所有代码写好,然后在进行调试。当然也有一部分开发人员写一点调一点,这纯属于习惯性问题,不存在孰优孰劣的问题。但是采用测试驱动开发方法学,就要采用后面的工作方式。
  因此,测试驱动开发不一定适合所有人,对于喜欢一次性先把代码写好,然后进行调试的人来说,让他们接受测试驱动开发的工作方式是很困难的,这一点希望大家能够重视起来。
相关文章:

posted @ 2013-12-20 09:21 顺其自然EVO 阅读(201) | 评论 (0)编辑 收藏

Oracle从创建用户到创建数据库

  以Oracle 11g为例。
  很多时候我们经常使用第三方工具连接数据库,比如Navicat,这些工具图形化使用方便,但在数据库权限上可能带来无法预料的问题。现在遇到这样的问题:在Navicat中创建的用户SQL*PLUS中识别不到,对某表空间无权限等。这种操作在图形化工具中虽然可以勾选完成,但是权限管理大事还是用SQL语句来的更放心。
  下面将从创建用户开始到创建数据库,解决一些遇到的问题,Oracle实验版本为11g。创建用户的SQL语句为:
create user 用户名 identified by 密码 default tablespace 表空间名
  首先我们在创建用户时不使用默认表空间,看看会有什么情况发生。
  这个错误是在用户创建时留下的,如果使用图形化工具创建用户可能就会留下这种问题,在创建表的时候出现:ORA-01950:对表空间’USERS’无权限。这种问题,如果这种问题已经存在了,解决方法很简单,修改一下用户属性即可。执行下面这条语句:
alter user 用户名 quota unlimited on 表空间名



  这样就可以创建表了。当然在创建用户的时候就可以避免这个问题,方法也很简单,创建完用户时: create user 用户名 identified by 密码 default tablespace 表空间名;之后再给用户授权:
grant create session, create table to 用户名
  这样就可以创建表了。当然也可以如下授权:
grant connect, resource to 用户名
  这种方式的授权就是create user时忘记default tablespace也可创建表。connect只有create session权限,这是连接数据库的基本权限。resource是开发者权限,至于其中包含的内容可以查询系统表中的具体内容:

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

Java集合框架 Map和泛型

  Map集合
  1.特点:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
  2.常用方法:
  1.添加:v  put(k key , v value); 将数据以键值对的方式存进集合中。
  void putAll(Map<? extends k,? extends v> m) ;从指定映射中将所有映射关系复制到此映射中
  2.删除:void clear();  清空集合
  v remove(Object key); 将集合中的元素以键的形式移除。
  3.判断:containsKey(Object key) 判断集合中是否有key。如果有,则返回true。
  contaninValue(Object value) 判断集合中是否有value
  4.查询:get(Object key);
  size();
  values();
  entrySet();
  keySet();
  Map有三个常见子类:
  |---Hashtable:此类实现一个哈希表,该哈希表将映射到相应的值。任何非null对象都可以用作键或值。该集合是线程同步的。 Jdk1.0 效率低
  |--HashMap:底层是哈希表数据结构,允许使用null值和null键,该集合是不同步的。 Jdk1.2 效率高
  |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
  和Set很像。
  其实Set底层就是使用了Map集合。
  注:如果添加相同的键,那么后添加的值会覆盖原来键对应值。
  map集合的两种取出方式:
  1.keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所以可以用迭代的方式取出所有的键,在根据get方法。获取每一个键对应的值。
  Map集合的取出原理:将map集合转成set集合。再通过迭代器取出。
  2.Set<Map.Entry<k,v>>  entrySet:将map集合中德映射关系存入到了set集合中,而这个关系的数据类型就是:map.entry.
  Map.Entry  其实Entry也是一个接口,它是Map接口中的一个内部接口。
  为何要定义在其内部呢?
  原因:
  a.Map集合中存的是映射关系这样的两个数据,是先有Map这个集合,才可有映射关系的存在,而且此类关系是集合的内部事务。
  b.并且这个映射关系可以直接访问Map集合中的内部成员,所以定义在内部。
package Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;
public class HashMapDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
entrySetMethod();
}
//利用keySet这个方法取出map集合中的值。
public static void keySetMethod(){
//创建一个HashMap集合,并添加了泛型。键值都是String类型的。
HashMap<String,String> hm = new HashMap<String,String>();
hm.put("01","zhangsan01");
hm.put("02","zhangsan02");
hm.put("03","zhangsan03");
hm.put("04","zhangsan04");
Set<String> keyset = hm.keySet();
for(Iterator<String> it =keyset.iterator();it.hasNext();){
String key =it.next();
String value = hm.get(key);
System.out.println("key: "+key+" "+"value:"+value);
}
}
public static void entrySetMethod(){
HashMap<String,String> hm = new HashMap<String,String>();
hm.put("01","zhangsan01");
hm.put("02","zhangsan02");
hm.put("03","zhangsan03");
hm.put("04","zhangsan04");
Set<Entry<String, String>> entry=hm.entrySet();
for(Iterator<Entry<String, String>> it =entry.iterator();it.hasNext();){
Entry<String, String> en = it.next();
System.out.println(en.getKey()+"  "+en.getValue());
}
}
}

 Map练习
  1.描述学生。
  2.定义map容器。将学生作为键,地址作为值。存入。
  3.获取map集合中的元素。
package Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
entrySet();
}
//第一种取出方式keySet();
public static void keySet(){
HashMap<Students,String> hm   = new HashMap<Students,String>();
hm.put(new Students("lisi1",21), "beijing");
hm.put(new Students("lisi1",21), "tianjing");
hm.put(new Students("lisi4",33), "nanjing");
hm.put(new Students("lisi8",44), "ganzhou");
hm.put(new Students("lisi5",80), "hengyang");
Set<Students> keyset  =hm.keySet();
for(Iterator<Students> it = keyset.iterator();it.hasNext();){
Students key =it.next();
String addrv =hm.get(key);
System.out.println(key+":::"+addrv);
}
}
public static void entrySet(){
HashMap<Students,String> hm   = new HashMap<Students,String>();
hm.put(new Students("lisi1",21), "beijing");
hm.put(new Students("lisi1",21), "tianjing");
hm.put(new Students("lisi4",33), "nanjing");
hm.put(new Students("lisi8",44), "ganzhou");
hm.put(new Students("lisi5",80), "hengyang");
Set<Map.Entry<Students, String>> entryset = hm.entrySet();
for(Iterator<Map.Entry<Students, String>> it =entryset.iterator();it.hasNext();){
Map.Entry<Students, String> entry = it.next();
Students s = entry.getKey();
String addr = entry.getValue();
System.out.println(s+":::"+addr);
}
}
}
  泛型
  泛型概述
  在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
  类的后面跟着<E>这样的标识,如ArrayList<E>,这个<E>就代表泛型,E就是泛型类型,表示ArrayList集合里面只能存储E类型的元素。
  其本质就是实现参数化类型,也就是说所操作的数据类型被指定为一种类型。
  好处:
  1、将运行时期出现的问题ClassCastException转移到了编译时期,方便程序员解决,让运行时期问题减少。
  2、避免了强制转换麻烦。
  示例
import java.util.*;
class GenericDemo{
public static void main(String[] args){
//定义了一个String类型的数组列表
ArrayList<String> al = new ArrayList<String>();
al.add("abc002");
al.add("abc013");
al.add("abc256");
al.add("abc028");
//al.add(4);//al.add(new Integer(5));
//迭代器要使用泛型
Iterator<String> it = al.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
/*
结果
abc002
abc013
abc256
abc028
*/

泛型使用
  泛型格式:通过<>来定义要操作的引用数据类型。
  在使用java提供的对象时,什么时候使用泛型呢?
  通常在集合框架中创建,只要见到<>就要定义泛型。
  其实<>就是用来接收类型的,当使用集合时,
  将集合中要存储的数据类型作为参数传递到<>中即可。
  示例
import java.util.*;
class TreeSetTest{
public static void main(String[] args){
TreeSet<String> ts = new TreeSet<String>(new LenComparator());
ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("z");
ts.add("a");
ts.add("sdcvrt");
Iterator<String> it = ts.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
//自定义比较器,实现Comparator接口并使用泛型
class LenComparator implements Comparator<String> {
public int compare(String s1,String s2){
/*
//升序
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
*/
//降序
int num = new Integer(s2.length()).compareTo(new Integer(s1.length()));
if(num==0)
return s2.compareTo(s1);
return num;
}
}
/*
结果
sdcvrt
abcd
cba
cc
z
a
*/
  泛型类
  什么时候定义泛型类?
  当类中要操作的引用数据类型不确定的时候,
  早期定义Object来完成扩展。
  现在定义泛型来扩展。
class Worker{}
class Student{}
//泛型以前的做法
class Tool{
private Object obj;
public void setObject(Object obj){
this.obj = obj;
}
public Object getObject(){
return obj;
}
}
//泛型类
class Utils<QQ>{
private QQ q;
public void setObject(QQ q){
this.q = q;
}
public QQ getObject(){
return q;
}
}
class GenericDemo{
public static void main(String[] args){
Utils<Worker> u = new Utils<Worker>();
u.setObject(new Worker());
Worker w = u.getObject();
/*
Tool t = new Tool();
t.setObject(new Worker());
Worker w = (Worker)t.getObject();
*/
}
}
  泛型方法
  为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将
  泛型定义在方法上。
class Demo{
//类型定义在方法上
public <T> void show(T t){
System.out.println("show:"+t);
}
public <Q> void print(Q q){
System.out.println("print:"+q);
}
}
class  GenericDemo{
public static void main(String[] args){
Demo d = new Demo();
d.show(5);
d.show(new Integer(5));
d.show("haha");
d.print(8);
d.print(new Integer(5));
d.print("heihei");
}
}
/*
结果
show:5
show:5
show:haha
print:8
print:5
print:heihei
*/

posted @ 2013-12-19 11:12 顺其自然EVO 阅读(5199) | 评论 (0)编辑 收藏

LoadRunner通过验证码并实现成功登录的方法

 需要安装的软件
  1、安装ImageMagick安装完成后,将其安装路径添加到环境变量path中
  2、安装Tesseract-OCR
#define MAX_NAME_LEN 4 //定义验证码字符串的长度,这里是4位
int flen;        //定义一个整型变量保存获得文件的大小
long filedes;
long filedess;    //保存文件句柄
char file[256]="c:\\test1.jpg";  //保存文件路径及文件名
char result[4];//定义用于从文件中读取验证码的数组
web_set_max_html_param_len("2000000");
//设置页面接收最大的字节数,该设置应大于下载文件的大小
//下载含有验证码的网页元素,并将其保存到参数中
web_reg_save_param_ex(
"ParamName=pic",
"LB=",
"RB=",
SEARCH_FILTERS,
"Scope=Body",
"RequestUrl=*/action/ValidateCodeServlet*",
LAST);
//关联登录时与服务器产生的会话ID
web_reg_save_param_ex(
"ParamName=CorrelationParameter_1",
"LB=Set-Cookie: JSESSIONID=",
"RB=; Path",
SEARCH_FILTERS,
"Scope=All",
"RequestUrl=*/192.168.12.1:8080/*",
LAST);
//访问测试网站
web_url("192.168.12.1:8080",
"URL=http://192.168.12.1:8080/",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTML",
EXTRARES,
"Url=/images/login_screenbg.jpg", ENDITEM,
"Url=/images/login_midbg.jpg",ENDITEM,
"Url=/images/login_contentbg.jpg", ENDITEM,
"Url=/images/login_btn.png", ENDITEM,
"Url=/images/login_input1.png",ENDITEM,
"Url=/images/login_input2.png",ENDITEM,
"Url=/images/reset_btn.png",ENDITEM,
LAST);
flen = web_get_int_property(HTTP_INFO_DOWNLOAD_SIZE);
//获得下载图片的文件大小
if(flen > 0)
{
if((filedes = fopen(file,"wb")) == NULL)
{
lr_output_message("oh cloud your Open File Failed!");
return -1;
}
fwrite( lr_eval_string("{pic}"),flen,1, filedes );
fclose( filedes );
}
system( "c:\\test1.bat" );    //在CMD命令行中运行OCR命令
/*
在C盘根目录下创建批处理文件test1.bat:
#进入到含有验证码图片的目录
c:
cd\
#转换下载的JPG文件为TIF
convert.exe -compress none -depth 8 -alpha offtest1.jpg test1.tif
#调用tesseract转换图片中的文件并保存到test1.txt文件中
tesseract.exe test1.tif test1
#执行完成后,自动退出命令行
exit
*/
if((filedess = fopen("c:\\test1.txt","rt")) == NULL)
{
lr_output_message("oh,cloud your Open File Failed!");
return -1;
}
fread( result,4,1,filedess );//从文件中读取验证码
fclose( filedess );
lr_output_message("result: %s", result); //打印出读取后的数据
lr_save_var(result,MAX_NAME_LEN,0,"VC" );
//保存指定位数的数据到变量中
web_submit_data("UserAction",
"Action=http://192.168.12.1:8080/action/UserAction",
"Method=POST",
"RecContentType=text/html",
"Referer=http://192.168.12.1:8080/",
"Snapshot=t2.inf",
"Mode=HTML",
ITEMDATA,
"Name=method","Value=login", ENDITEM,
"Name=goPage","Value=/index.html", ENDITEM,
"Name=currentPage","Value=/", ENDITEM,
"Name=username","Value=admin", ENDITEM,
"Name=password","Value=123456", ENDITEM,
"Name=ValidateCode","Value={VC}", ENDITEM, //输入获取的验证码
"Name=loginSubmit", "Value=登录", ENDITEM,
EXTRARES,
...
LAST);

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

QTP中DataTable用法整理

 DataTable的操作包括:
DataTable.GetSheet(dtSheet)
DataTable.GetSheetCount
DataTable.[GetSheet.]GetRowCount
DataTable.[GetSheet.]GetParameterCount
DataTable.GetSheet(sSheetName).GetParameter(“ColumName”).ValueByName(iRowNumber)
DataTable.[GetSheet.]GetCurrentRow
DataTable.[GetSheet.]SetCurrentRow(RowNumber)
DataTable.Value(ParameterID [, SheetID]) or DataTable (ParameterID [, SheetID])
DataTable.AddSheet(SheetName)
DataTable.DeleteSheet(SheetName)
DataTable.Export(filename)
DataTable.ExportSheet(filename,SheetName)
DataTable.Import(FileName)
DataTable.ImportSheet(FileName, SheetSource, SheetDest)
  1.得到datatable总行数的命令:GetRowCount
  描述:返回运行时数据表的第一个工作表(用于测试的全局表或用于业务组件的业务组件表)中最长的列中的总行数。
  语法:DataTable.GetRowCount
  返回值:数字
  示例:
  以下示例使用 GetRowCount 方法查找 MySheet 运行时数据表中最长的列中的总行数,并将其写入报告。
  rowcount = DataTable.GetSheet("MySheet").GetRowCount
  Reporter.ReportEvent 2, "数据工作表中有 " &rowcount, "行。
  2.得到datatable运行时的动态列数:GetParameterCount
  语法:DTSheet.GetParameterCount
  例: paramcount = DataTable.GetSheet("MySheet").GetParameterCount
  3.GetCurrentRow方法
  描述:返回运行时数据表的第一个工作表(用于测试的全局表或用于业务组件的业务组件表)中的当前(活动)行。
  语法:DataTable.GetCurrentRow
  返回值:数字
  示例:
  以下示例使用 GetCurrentRow 方法检索当前在运行时数据表中使用的行,并将其写入报告。
  row = DataTable.GetCurrentRow
  Reporter.ReportEvent 1, "行号", row
  4. 设置当前active的行数(第一行为1):SetCurrentRow
  语法:DataTable.SetCurrentRow(RowNumber)
  例: DataTable.SetCurrentRow(tb_i+1)
  DataTable.GetSheet("Action1"). SetCurrentRow(tb_i+1)
  '注:此命令可在循环运行中不断指向下一行数据
  你也可以用GetCurrentRow来获取Action1的行,然后再用SetCurrentRow来保持两个Action的当前行一致:
  CurrRow = DataTable.GetSheet("Action1").GetCurrentRow
  DataTable.GetSheet("Action2").SetCurrentRow(CurrRow)
 5.查询、设置datatable的数值:
  语法:To find the value:
  DataTable.Value(ParameterID [, SheetID])
  or : DataTable(ParameterID [, SheetID])
  To set the value:
  DataTable.Value(ParameterID [, SheetID])=NewValue
  or : DataTable(ParameterID [, SheetID]) =NewValue5
  DataTable("Col", "Action2") 就是读取Action2的Col列。
  同样,表也可以用数字代替:
  DataTable(1, 2) 这样就是读取第二个Action表的第一列
  还有一种写法:
  DataTable(1, "Action2") 这样就是读取Action2的第一列,不管第一列叫什么名字,都能读
  还有一种赋值方法
  aParam2=DataTable(“AccountsNumber”,dtGlobalSheet)
  还有一种赋值方法,但是有一个前提就是:必须只能是测试只包含一个操作的情况:
  aParam3=DataTable(“AccountsNumber”,dtLocalSheet)
  例: DataTable.Value("Destination", "ActionA")="New York"
  DataTable.Value(2,3)="New York"
  DataTable("Destination", dtlocalSheet)="New York"
  Call_date= DataTable.Value("Date","add Conference Call") '为Call_date赋值
  6. 取datatable特定行的数据:
  DataTable.GetSheet("Action1").GetParameter("test\").ValueByRow(4)
  7 AddSheet 方法
  描述:向运行时数据表中添加指定工作表并返回该工作表,以便可以直接在同一语句中设置新工作表的属性。
  语法:DataTable.AddSheet(SheetName)
  示例:
  以下示例先使用 AddSheet 方法在运行时数据表中新建工作表"MySheet",然后向新工作表中添加参数。
  Dim Variable
  Variable=DataTable.AddSheet ("MySheet").AddParameter("Time", "8:00")
  8 DeleteSheet方法
  描述:从运行时数据表中删除指定工作表。
  语法:DataTable.DeleteSheet SheetID
  示例:
  以下示例使用 DeleteSheet 方法从运行时数据表中删除工作表"MySheet"。
  DataTable.DeleteSheet "MySheet"
  9 Export方法
  描述:在指定位置保存运行时数据表的副本。
  语法:DataTable.Export(FileName)
  示例:
  以下示例使用 Export 方法将测试的数据表副本保存在 C:\flights.xls 中。
  DataTable.Export ("C:\flights.xls")
  10 ExportSheet方法
  描述:将运行时数据表的指定工作表导出到指定文件中。
  如果指定文件不存在,则将创建一个新文件并保存指定工作表。
  如果当前文件存在,但是该文件不包含具有指定工作表名称的工作表,则将插入该工作表作为文件的最后一个工作表。
  如果当前文件存在且包含指定工作表,则导出的工作表将覆盖现有工作表。
  语法:DataTable.ExportSheet(FileName, DTSheet)
  DTSheet 变量要导出的运行时数据表工作表的名称或索引。索引值从 1 开始。
  示例:
  以下示例使用 ExportSheet 方法将运行时数据表的第一个工作表保存到 name.xls 文件中。
  DataTable.ExportSheet "C:\name.xls" ,1
  DataTable.ExportSheet "C:\name.xls" , " MySheet "
  11 GetSheet方法
  描述:返回运行时数据表中的指定工作表。
  语法:DataTable.GetSheet(SheetID)
  SheetID 变量标识要返回的工作表。SheetID 可以是工作表名称或索引。
  索引值从 1 开始。
  返回值:DTSheet 对象
  示例:
  以下示例使用 GetSheet 方法返回运行时数据表的"MySheet"工作表,以便向其中添加参数。
  MyParam=DataTable.GetSheet ("MySheet").AddParameter("Time", "8:00")
  您还可以使用该方法向"MySheet"本地表中添加参数(注意,不会返回值)。
  DataTable.GetSheet ("MySheet").AddParameter "Time", "8:00"

 12 GetSheetCount方法
  描述:返回运行时数据表中的总工作表数。
  语法:DataTable.GetSheetCount
  返回值:数字
  示例:
  以下示例使用 GetSheetCount 方法查找运行时数据表中的总工作表数,并将其写入报告。
  sheetcount = DataTable.GetSheetCount
  Reporter.ReportEvent 0, "工作表编号", "数据表中有" & sheetcount & "个工作表。
  13 Import方法
  描述:将指定的 Microsoft Excel 文件导入运行时数据表。
  注意:
  导入的表必须与测试或组件匹配。列名必须与测试或组件中的参数匹配,并且工作表名称(用于测试)必须与操作名匹配。
  如果导入的 Excel 表包含组合框或列表单元格、条件格式或其他特殊单元格格式,则不会导入这些格式,并且单元格在数据表中显示时包含固定值。
  语法:DataTable.Import(FileName)
  FileName 字符串型 要导入的 Excel 表的完整路径。
  示例:
  导入的表将替换现有运行时数据表(包括所有数据表)中的所有数据。
  以下示例使用 Import 方法将 flights.xls 表导入运行时数据表。
  DataTable.Import ("C:\flights.xls")
  14 ImportSheet方法
  描述:将指定文件的工作表导入运行时数据表的指定工作表。导入的工作表中的数据将替换目标工作表中的数据(请参阅 SheetDest 参数)。
  注意:
  导入的工作表中的列标题必须与工作表导入操作中的数据表参数名匹配。否则,测试或组件可能会失败。
  导入的工作表会自动采用它所替换的工作表的名称。
  如果导入的 Excel 工作表包含组合框或列表单元格、条件格式或其他特殊单元格格式,则不会导入这些格式,并且单元格在数据表中显示时包含固定值。
  语法:DataTable.ImportSheet(FileName, SheetSource, SheetDest)
  FileName 字符串型要从中导入工作表的 Excel 表的完整路径。
  SheetSource 变量 要从文件导入的工作表的名称或索引。索引值从 1 开始。
  SheetDest 变量数据表中要用 SheetSource 替换的工作表的名称或索引。索引值从 1 开始。
  示例:
  以下示例使用 ImportSheet 方法将 name.xls 表的第一个工作表导入测试的运行时数据表中的Action1工作表。
  DataTable.ImportSheet "C:\name.xls" ,1 ," Action1"
  DataTable.ImportSheet "C:\name.xls" ,1 ," Global"
  Qtp中不要使用Global表,会出现死循环现象

posted @ 2013-12-19 11:08 顺其自然EVO 阅读(2890) | 评论 (0)编辑 收藏

Appium 自动化测试演示

 经验就是:
  每两次操作之间,一定要间隔几秒,不然可能会由于加载不完全,导致操作异常
  初始隐藏的控件,要判断状态,等显示后再操作
  最后输出:
  测试截图的相似度百分比(之前某一次结果),用来做正确性验证,基本上相似度小余90%的都有点问题
  http://v.youku.com/v_show/id_XNjM0ODIxNTUy.html
  密码:testerhome.com
  PS:原来不支持嵌入视频啊
  相似度计算是看的 http://blog.csdn.net/gzlaiyonghao/article/details/2325027
  现在搞不太清楚的就是怎么判断当前的位置,是在什么窗口下面,和如何打印出当前位置的所有控件
# coding:utf8
import logging
import histsimilar
import traceback
import time
import os
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, WebDriverException
logging.basicConfig(filename='log.txt',level=logging.INFO)
success = True
desired_caps = dict()
desired_caps['browserName'] = 'iOS'
desired_caps['platform'] = 'Mac'
desired_caps['version'] = '6.1'
desired_caps['app'] = os.path.abspath('测试app的位置')
#def is_alert_present(wd):
#    try:
#        wd.switch_to_alert().text
#        return True
#    except:
#        return False
def click(element):
element.click()
time.sleep(3)
logging.info(str(c) + ' time click ' + wd.page_source)
screenshot()
def send_keys(element, keys):
element.send_keys(keys)
time.sleep(3)
logging.info(str(c) + ' time click ' + wd.page_source)
screenshot()
def execute_script(script, args):
wd.execute_script(script, args)
time.sleep(3)
screenshot()
def mk_new_dir():
global path, base
base = '截图存放的位置'
if not os.path.isdir(base):
path = base + '0/'
os.mkdir(path)
return
path = base + str(len(os.listdir(base))) + '/'
c = 0
def screenshot():
global c, path
if not os.path.isdir(path):
os.mkdir(path)
wd.get_screenshot_as_file(path + str(c) + '.png')
c += 1
def compare():
dirs = list()
for dirname in os.listdir(base):
if os.path.isdir(base + dirname):
dirs.append((os.path.getmtime(base + dirname), dirname))
if len(dirs) < 3:
return
dirs.sort()
new = dirs[len(dirs) - 1][1]
previous = dirs[len(dirs) - 2][1]
names = [(os.path.getmtime(base + new + '/' + filename), filename) for filename in
os.listdir(base + new)]
names.sort()
for n in names:
if n[1].startswith('.'):
continue
if os.path.exists(base + previous + '/' + n[1]):
print n[1] + ' similarity : ' + str(
int(histsimilar.calc_similar_by_path(base + new + '/' + n[1],
base + previous + '/' + n[1]) * 100)) + '%'
try:
mk_new_dir()
wd = webdriver.Remote('http://0.0.0.0:4723/wd/hub', desired_caps)
wd.implicitly_wait(5)
try:
button = wd.find_element_by_name('点击开启')
while not button.is_displayed():
#screenshot()
time.sleep(1)
time.sleep(3)
click(button)
except WebDriverException, NoSuchElementException:
logging.info('没有开机动画')
click(wd.find_element_by_xpath("//window[1]/tableview[1]/cell[1]/button[1]"))
click(wd.find_element_by_name(" 返回"))
click(wd.find_element_by_xpath("//window[1]/tableview[1]/cell[1]/button[2]"))
click(wd.find_element_by_name(" 返回"))
click(wd.find_element_by_name("游记"))
click(wd.find_element_by_name("qunar login"))
send_keys(wd.find_element_by_xpath("//window[1]/image[2]/textfield[1]"), "lvtu@yopmail.com")
send_keys(wd.find_element_by_xpath("//window[1]/image[3]/secure[1]"), "lvtu@yopmail.com")
click(wd.find_element_by_name("登录"))
try:
click(wd.find_element_by_xpath("//window[1]/button[3]"))
except:
logging.info('没上传提示')
click(wd.find_element_by_xpath("//window[1]/tableview[1]/cell[1]/text[1]"))
click(wd.find_element_by_xpath("//window[1]/tableview[1]/cell[1]"))
execute_script("mobile: swipe",
{"touchCount": 1, "startX": 157, "startY": 529, "endX": 156, "endY": 102, "duration": 0.5})
click(wd.find_element_by_name(" 返回"))
click(wd.find_element_by_name(" 返回"))
click(wd.find_element_by_xpath("//window[1]/button[1]"))
except:
traceback.print_exc()
success = False
finally:
if success:
#raise Exception("Test failed.")
compare()
wd.quit()



 计算图片相似度部分
# -*- coding: utf-8 -*-
import Image
def make_regalur_image(img, size=(256, 256)):
return img.resize(size).convert('RGB')
def split_image(img, part_size=(64, 64)):
w, h = img.size
pw, ph = part_size
assert w % pw == h % ph == 0
return [img.crop((i, j, i + pw, j + ph)).copy() \
for i in xrange(0, w, pw) \
for j in xrange(0, h, ph)]
def hist_similar(lh, rh):
assert len(lh) == len(rh)
return sum(1 - (0 if l == r else float(abs(l - r)) / max(l, r)) for l, r in zip(lh, rh)) / len(lh)
def calc_similar(li, ri):
#   return hist_similar(li.histogram(), ri.histogram())
return sum(hist_similar(l.histogram(), r.histogram()) for l, r in zip(split_image(li), split_image(ri))) / 16.0
def calc_similar_by_path(lf, rf):
li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
return calc_similar(li, ri)
def make_doc_data(lf, rf):
li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
li.save(lf + '_regalur.png')
ri.save(rf + '_regalur.png')
fd = open('stat.csv', 'w')
fd.write('\n'.join(l + ',' + r for l, r in zip(map(str, li.histogram()), map(str, ri.histogram()))))
#   print >>fd, '\n'
#   fd.write(','.join(map(str, ri.histogram())))
fd.close()
import ImageDraw
li = li.convert('RGB')
draw = ImageDraw.Draw(li)
for i in xrange(0, 256, 64):
draw.line((0, i, 256, i), fill='#ff0000')
draw.line((i, 0, i, 256), fill='#ff0000')
li.save(lf + '_lines.png')

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

仅列出标题
共394页: First 上一页 168 169 170 171 172 173 174 175 176 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜