qileilove

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

Android自动化追本溯源系列(2):在控件上执行操作

上回说到,在Android自动化测试时,通过反射机制,我们能获得页面的所有控件。来看一个简单的应用例子:

ArrayList<View> views = getAllViews();
for(View view : views)

    Log.d("Views On Activity:", view.getClass().getName());
}

  这样在LogCat里我们就可以打印出所有的View了:

-27 22:24:52.369: D/Views On Activity:(2123): android.widget.LinearLayout
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.widget.ActionBarContainer
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.widget.ActionBarView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.LinearLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.ImageView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.LinearLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.widget.ActionBarView$HomeView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.ImageView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.ImageView
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.view.menu.ActionMenuView
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.widget.ActionBarContextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.FrameLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.RelativeLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.RelativeLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.ImageView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.ImageView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.RelativeLayout
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.TextView
-27 22:24:52.369: D/Views On Activity:(2123): android.widget.Button
-27 22:24:52.369: D/Views On Activity:(2123): com.android.internal.policy.impl.PhoneWindow$DecorView

  我们看到这里罗列了所有的控件,有Layout, TextView, Button 等等。而获得了这些控件,对我们有什么用呢?

  Yes,有了这些控件,我们就可以执行相应的操作了!

  比如:

  1、有了Button,我们可以执行Click On Button操作

  2、有了TextView,我们就可以得到页面的所有Text,去验证Message或者做Localization Testing

  3、同样有了ImageView,我们可以执行Click操作,甚至可以得到页面显示的图片

  4、.......

  下面分享一些我们项目中用到的关于这些操作的典型片断:

  ● Click 操作

public void clickOnView(int id)
    {
        View view = solo.getView(id);
        if(view != null)
        {
            solo.clickOnView(view);
        }
    }
● 等待操作

public boolean isViewGone(int id, long timeout)
    {
        final long endtime = SystemClock.uptimeMillis() + timeout;
       
        while(SystemClock.uptimeMillis() < endtime)
        {
            if(solo.getView(id).hasFocusable())
            {
                solo.sleep(10);
            }
            else
            {
                return true;
            }
        }
       
        return false;
    }

  ● 获取页面图片

public Bitmap getSourceIcon()
{
    BitmapDrawable drawable = (BitmapDrawable) sourceImageView.getDrawable();
    return  drawable.getBitmap();
}

  这里的sourceImageView变量,就是一个ImageView的实例。

  为了方便,我们在项目中使用了Robotium框架,但是如果追本溯源的话,我们不禁要问:

  这些操作是如何实现的?我们自己能不能写?

  我们知道Robotium框架是基于Instrumentation,并且市面上大多数的Android测试框架都是基于 Instrumentation的,而Instrumentation就是我们做自动化的基石,一层层的跟进Robotium的Click方法,我们会看 到最终它是调用Instrumentation的:

  public void sendPointerSync (MotionEvent event)

  来实现Click操作。

  For Example:Solo.clickOnView(View view) 会调用 clicker.clickOnScreen(view) 跟进去我们会看到下面的代码:

public void clickOnScreen(float x, float y) {
        long downTime = SystemClock.uptimeMillis();
        long eventTime = SystemClock.uptimeMillis();
        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_DOWN, x, y, 0);
        MotionEvent event2 = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_UP, x, y, 0);
        try{
            inst.sendPointerSync(event);
            inst.sendPointerSync(event2);
            sleeper.sleep(MINISLEEP);
        }catch(SecurityException e){
            Assert.assertTrue("Click can not be completed!", false);
        }
    }

  这样我们就明白了,原来在Android automation testing,Click的操作是这么实现的!

  总结

  要是我们自己来写Android自动化测试框架,我们也可以提供这样一个方法嘛~

相关链接:

Android自动化追本溯源系列(1):获取页面元素

posted @ 2013-05-20 10:16 顺其自然EVO 阅读(701) | 评论 (0)编辑 收藏

接口测试自动化实践指南

 什么是接口测试

   引用牛人定义的接口测试概念——接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测 试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。由于刚刚接触接口测试,暂时定义成系统外部接口测试,内部及各个子系 统之间逐个引入。

  为什么做接口测试呢?

  1、系统越做越大,越做越复杂,子系统的数量也逐步增长;

  2、客户技术能力也不断地提升;

  3、原有的测试方法不能有效地发现bug;

  接口测试的目的是什么?

  以保证系统的正确和稳定为核心,以持续集成为手段,提高测试效率,提升用户体验,降低产品研发成本。关注持续集成是接口测试的灵魂,否则接口测试带来工作量会成指数增长。

  接口测试的摸索

  1、尝试使用各种脚本、框架和流程规范,找到适合自己团队的最优方案,采用perl脚本直接模拟接口协议完成测试,特点灵活多变,适应性较强,缺点:维护成本过大,推广比较缓慢(大部分测试人员的开发基础相对开发人员较低)

  2、考虑测试部大部分成员不太了解开发技术,所以直接采用脚本开发接口测试很难实现,借鉴测试部自动化成功经验,接口测试引入Robot framework,让做过自动化测试的成员较快地接受。接口测试被所有测试人员和开发人员所接收,每一个成员都能快速地完成接口测试用例,最大程度地提高软件质量的稳定性。

  接口测试自动化的实现

  1、由于使用robot framework框架,所以选择python脚本语言能更好地应用到robot framework框架

  2、Smpp协议接口驱动模拟器——采用twisted框架完成网络通信,采用smpp.pdu模块完成协议解析。

  3、已Smpp协议接口驱动为基础,编写适合robot framework框架的关键字,并引入框架,完成接口自动化测试用例。

  为什么选择python和robot framework呢?

  1、Python脚本语言支持面向对象开发,复用程度较高,有相当成熟的网络开发框架twisted,能够快速地搭建一个网络应用(外部子系统模拟器)。

  2、Python脚本语言与C++、java等语言结合的比较好,robot framework框架使用python实现的,能够方便地应用到框架中去。

  3、Robot framework框架有一套完成用例组织、调试和产生报告功能,并支持远程接口调用,在完成接口自动化测试过程中,无须考虑这些。

  接口测试的未来

  实现一个框架,通过简单的配置虚拟出各种接口,并将被测试系统运行在虚拟机中,自动完成内部代码、内存检测、数据校验与逻辑检测。

posted @ 2013-05-17 10:23 顺其自然EVO 阅读(512) | 评论 (0)编辑 收藏

Android自动化追本溯源系列(1):获取页面元素

  本系列旨在阐述Android自动化的原理,让大家明白如何在Android平台上做自动化,甚至开发出自己的自动化工具来。

  什么是Android自动化?

  相信对于测试同 学,这个问题就很简单了。自动化的目的就是做好回归测试,以达到版本控制,并节省人力。而Android自动化就是在Android平台上做测试自动化, 相信随着Android开发的日趋盛行,其测试自动化的需求也会逐渐增强,知其然,固然是好,但如能知其所以然,必将锦上添花。

  目前我所知道的做Android自动化的工具有:

  ● Ranorex 支持录制回放功能,但是不太好用,需要在开发代码中注入一段测试代码,并且它是收费的。

  ● Robotium 开源的黑盒测试框架,使用时需要引入一个JAR包,需要测试人员有一定的编码功底,才能编写Test Case。

  ● Monkeyrunner Google随SDK发布的测试工具,功能简单,不是很好用。

  因为是想研究自动化原理,所以这里主要参考Robotium以及Android源码。

  如何识别页面元素?

  做过自动化的同学应该都知道,我们在写涉及UI的自动化case时,其基本思路就是找到某元素—>执行操作,这里的操作要么是动作,要么是是验证。仔细想想,其实道理就是这样。所以说如果我们想开发自己的自动化测试工具时,首要解决的问题就是,如何在测试时,找到页面的元素。

  而在Android中,思路也是一样。

   如何大家研究过Android的窗口机制的话,应该看到过这样的说法,真正实现WindowManager窗口机制的是 WindowManagerImpl类,它会把DecorView添加到mViews数组,创建对应的ViewRoot,而DecorView是何物呢? 参考我上篇博客:http://www.cnblogs.com/jinsdu/archive/2013/01/03/2840565.html 知道,实际上DecorView是页面最顶层的View,而如果能够获取到它,我们就可以将其转换成ViewGroup,然后遍历其所有子节点从而得到所 有的页面元素了。而运用java的反射机制,正好可以在运行时,获取类的属性和方法:

  于是在运行时,获得WindowManagerImpl类:

private static Class<?> windowManager;
    static{
        try {
            String windowManagerClassName = "android.view.WindowManagerImpl";
             windowManager = Class.forName(windowManagerClassName);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

  然后获得页面的DecorView:

private View[] getWindowDecorViews()
    {

        Field viewsField;
        Field instanceField;
        try {
            viewsField = windowManager.getDeclaredField("mViews");
            instanceField = windowManager.getDeclaredField("sWindowManager");
            viewsField.setAccessible(true);
            instanceField.setAccessible(true);
            Object instance = instanceField.get(null);
            return (View[]) viewsField.get(instance);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

 如此我们就获得了页面的DecorView了,转换成ViewGroup,遍历其所有子元素,我们就能获得页面的所有元素:

public ArrayList<View> getAllViews() {
        final View[] views = getWindowDecorViews();
        final ArrayList<View> allViews = new ArrayList<View>();

        if (views != null && views.length > 0) {
            View view;
            for (int i = 0; i < views.length; i++) {
                view = views[i];
          allViews.add(view);
                getAllChildren(allViews, (ViewGroup) view);
            }
        }
        return allViews;
    }

    private void getAllChildren(ArrayList<View> allViews, ViewGroup viewGroup) {
        if (viewGroup != null) {
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                allViews.add(child);
                if (child instanceof ViewGroup) {
                    getAllChildren(allViews, (ViewGroup) child);
                }
            }
        }
    }

  而获得了页面的元素,就基本上完成了我们UI Automation两步走的第一步 —> 找到页面元素。试想一下,如果我们的Android自动化框架有上面类似的功能,那么我们的自动化框架就能在运行时获得页面的所有元素,而我们在写 case时,也许只要传给自动化框架一个控件ID,我们就可以获得这个元素了。有了这个元素我们就可以向我们的第二步迈进了—>在控件上执行操作, 或者取其属性进行Expected验证。当然我会在接下来的文章中,一一阐述这些内容。

  总结

  研究Android自动化原理,要涉及到很多知识,尤其对Android的窗口机制要更加明确,像页面是如何加载,如何通信,都不是一言半语可 以说清的,我也是正在研究中。对于WindowManagerImpl类的源码,有兴趣的同学,可以研究下:http://grepcode.com /file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/view/WindowManagerImpl.java#WindowManagerImpl

  最后,欲知后事如何,且听下回分解。

posted @ 2013-05-17 10:20 顺其自然EVO 阅读(406) | 评论 (1)编辑 收藏

软件测试管理中的问题

 测试负责人做什么

  存在的现状:

  测试项目负责人都是在执行测试

  带来的问题:

  ● 有些成员的缺陷质量不合格;

  ● 开发人员修改不及时,系统某些功能发生严重问题导致部分功能无法测试等等。

  正确的做法:

  ● 测试用例执行情况;

  ● 测试员提交的缺陷情况;

  ● 测试中发生的突发事件。

  测试中的版本控制

  存在的现状:

  测试小组版本管理不规范,造成测试对象不可控制。

  带来的问题:

  ● 需求频繁变化,难以应对;

  ● 维护测试用例工作量大;

  ● 测试质量低下。

  正确的做法:(专人负责!)

  ● 测试需求的版本控制;

  ● 测试用例的版本控制;

  ● 测试对象的版本控制。

  提交的缺陷质量差

  存在的现状:

  提交的缺陷引起测试人员与开发人员的争议。

  带来的问题:

  ● 开发的成本高;

  ● 回归测试的成本高;

  ● 交流的成本高。

  正确的做法:

  ● 一个缺陷至少描述清楚概要描述、详细描述、重现步骤三方面的内容;

  ● 采用交叉测试的方法,测试工程师之间互相验证彼此提交的缺陷。

 需要怎样的测试人员

  存在的现状:

  ● 忽视测试团队,当要实施测试时,临时找几个程序员充当测试人员

  ● 安排一些毫无开发经验的新手去做测试工作

  带来的问题:

  ● 测试质量低下;

  ● 测试效率低下;

  ● 测试人员觉得测试工作索然无味。

  正确的做法:

  ● 一名资深的测试领域专家;

  ● 多名具备一技之长的成员;

  ● 多名测试执行人员(包括新手);

  ● 兼职测试团队(包括同行专家)。

  测试中最难克服的现象

  存在的现状:

  在回归测试时,之前由于进行过认真的测试,往往会认为某些功能是可靠,只要验证一些以前发现的缺陷是否修改完成就可以了。

  带来的问题:

  开发人员在修改缺陷时往往会引入新的缺陷,测试人员的疏于防范就会把这些缺陷带到用户那里。

  正确的做法:

  ● 最好在最后一次回归测试时执行一次全部的测试用例;

  ● 测试工程师在回归测试时互相交换任务,反复测试某一功能的机会大大减少,从而也就不会“主观的”认为某些功能没有缺陷。

  用来测试时间总是不够

  存在的现状:

  一旦整体进度不能向后延迟,习惯的做法就是缩减测试时间。尤其在功能还没有开发完成的情况下,这种现象更为突出。

  带来的问题:

  ● 测试质量不满足要求;

  ● 项目经理受到指责。

  正确的做法:

  ● 按照测试任务的轻重缓急,尽最大努力完成测试任务;

  ● 在实际工作中和开发人员共同配合,达到最佳效果;

  ● 采用平时积累的自动化测试方法;

  ● 不要抱怨,积极面对问题。

 公司不重视测试怎么办

  存在的现状:

  尽管很多公司在意识上已经开始重视测试,但是在具体工作中,往往由于追赶进度、节省资源等方面原因而忽略测试工作。

  带来的问题:

  测试负责人仍要对软件质量负主要责任!

  正确的做法:

  ● 要主动去配合开发人员完成工作;

  ● 逐渐显出测试工作的重要性,然后再逐步健全测试体系;

  ● 只有测试工作的业绩逐步表现出来,人们才会真正的注意到测试的重要性

  管理者需要是技术专家吗

  存在的现状:

  在实际工作中,由于测试人员的短缺,测试管理者常常做为测试员来执行具体的测试任务。尤其在规模较小的测试团队,测试管理者的日常工作通常以具体的测试执行工作为主。

  带来的问题:

  测试管理没做好!

  正确的做法:

  ● 管理者主要任务是制定测试策略,落实管理测试计划,为测试项目的进行创造良好的执行环境以及调动员工的创造性;

  ● 技术方面的背景知识对测试管理者是十分有益的。例如:分配工作任务、做进度预算,以及一些具体的执行工作,都需要一定的背景知识。

  评估测试人员的绩效

  存在的现状:

  仅从提交的问题单数量、测试执行用例数量来判断测试人员的好坏。

  带来的问题:

  这种做法明显缺乏全面性。问题单的数量只是评估测试质量的一个方面。

  正确的做法:

  我们更需要看中实际的测试质量。这就需要考察问题单的质量、测试的难度、问题单的级别。

  存在的现状:

  对测试人员发现的问题的价值没有进行评估。

  现实情况是:

  发现1个系统架构设计方面存在的缺陷和隐患,远比发现几个普通界面的显示问题要有价值的多。

  存在的现状:

  不重视测试文档的质量。

  现实情况是:

  只有对系统进行了充分的、深入测试的测试人员才能写出高质量测试报告,说明测试的全面性和测试过程的质量。

  存在的现状:

  不重视测试人员的综合能力。

  现实情况是:

  需要关心测试人员的工作积极性,积极工作的态度不仅能带来很高的测试质量,还能提高整个团队的积极向上的风气。

posted @ 2013-05-17 10:17 顺其自然EVO 阅读(222) | 评论 (0)编辑 收藏

缺陷管理工具TD使用说明

TestDirector介绍

  Test Director:是Mercury Interactive 公司推出的基于WEB 的测试管理工具,在本文档中我们简称为TD。

  其中包括的内容有:

  1、需求定义(Specify Requirements):

  分析应用程序并确定测试需求。

  2、测试计划(Plan Tests):

  基于测试需求,建立测试计划。

  3、测试执行(Execute Tests):

  创建测试集(Test Set)并执行测试。

  4、缺陷跟踪(Track Defects):

  报告程序中产生的缺陷并跟踪缺陷修复的全过程。

  TD的缺陷跟踪功能

  1、公司部署的TD访问地址:

  http://td.teacher.it/tdbin/start_a.htm;也可以从http://dev.teacher.it/中访问.

  2、用户名及密码设置:

  用户名为姓名的字母全拼,

  如:姓名:李翠霞,用户名为:licuixia,

  初始密码为空,用户登录后在TOOLS中修改密码。

  3、项目选择:teacher-1

  可参考下面的图片:

4、角色权限设置:

  ----QA人员:

  发现并提交BUG,在开发人员修复完成时验证BUG状态。

  ----项目经理:

  如果是BUG:打开BUG并分配给相关的开发人员,同时选择BUG的优先级。

  如果不是BUG或此BUG描述不清:选择拒绝修复,同时在注释中写明拒绝修复的原因。

  ----开发人员:

  如果是BUG:打开BUG把BUG状态置为:已修复,修复完成后在开发注释中写明BUG出现的原因。

  如果不是BUG或此BUG描述不清:选择拒绝修复,同时在开发注释中写明拒绝修复的原因。

  可参考下面的图片:

必要操作步骤:

  (1)选择BUG状态,

  项目经理可以选择: OPEN/REJECTED

  开发人员选择为:FIXED/REJECTED

  测试人员选择为:REOPEN/CLOSED

  (2) 分配并发邮件给具体的开发人员

字体:        | 上一篇 下一篇 | 打印  | 我要投稿 

  开发人员处理BUG

  第一步:修改BUG状态:

  如果确定是BUG,而此BUG需要修复的时间花费较长,BUG状态就

  为OPEN,

  直到BUG修复改完成后,再到TD工具中把BUG状态修改为FIXED。

  同时在TD中选择测试人员,发邮件通知。

  第二步:选择修改日期:

  选择开始修改BUG的日期。

  QA 人员在处理BUG时:

  一:当验证后此BUG已不存在,把BUG状态置为 CLOSED,到现在此BUG的生命周期完成。

  二:当验证后此BUG还存在,把BUG状态置为REOPEN,同时会发邮件给相关的开发人中。开发人员要重新修复此BUG。




posted @ 2013-05-17 10:16 顺其自然EVO 阅读(658) | 评论 (0)编辑 收藏

手机知识与手机性能测试

一、手机术语简介

  手机

  手机也叫蜂窝电话,起源于一个基站辐射电波的有效区域形状是一个正六边形,无数个基站连在一块,就象一个蜂窝一样。而基站辐射电波的有效区也叫小区。

  分辨率

  指的是屏幕上所显现出来的像素数目,它由两部分来计算,分别是水平行的点数和垂直行的点数。举个例子,如果分辨率为800x600,那就是说这幅图像由800个水平点和600个垂直点组成。更高的分辨率可以在同样面积屏幕上显示更多的东西。

  色深

  色深决定屏幕上每个像素由多少种颜色控制。通常色深可以设定为4位(256色),8位(4096色),16位(65536色),24位(26w色),当然色深的位数越高,你所能够得到的颜色就越多,屏幕上的图像质量就越好。

  摄像头

   手机数码相机可以变焦,调节亮度,还有闪光灯,摄录等功能。CMOS CIF:手机数码相机分辨率的一种,最大可拍下352x288像素的照片。(11w摄像头)CMOS VGA:手机数码相机分辨率的一种,最大可拍下640x480像素的照片。(30w摄像头)CMOS SXGA:手机数码相机分辨率的一种,最大可拍下1280x960像素的照片。(120w摄像头)

  像素

   像素(pixel)是picture element的简写,数字图像是由按一定间隔排列的亮度不同的像点构成的,形成像点的单位称“像素”,也就是说,组成图像的最小单位是像素,像素是图像 的最小因素。它代表每一个彩色屏幕的小点,虽然它们小到你无法看见,但是彩色屏幕上显示的任何资料内容,影像,均是由这些小点所构成。屏幕上像素的数量是 由屏幕的分辨率来决定的,并不是由屏幕的大小来决定。

  MMS

  MMS是 Multimedia Messaging Service的缩写,中文译为多媒体信息服务,也称“彩信”。它最大的特色就是支持多媒体功能,可以在GPRS,CDMA 1X,3G,EDGE的支持下,以WAP无线应用协议为载体传送视频短片,图片,声音和文字,传送方式除了在手机间传送外,还可以是手机与电脑之间的传 送。具有MMS功能的移动电话的独特之处在于其内置的媒体编辑器,使用户可以很方便地编写多媒体信息。如果安装上一个内置或外置的摄像头,用户还可以制作 出powerpoint格式的信息或电子明信片,并把它们传送给朋友或同事。目前,这一应用服务已走向成熟,逐渐成为主流的短信格式。

  EMS

   EMS(Enhanced Message Service)增强型信息服务,SMS新版本。EMS的优势是除了可以像SMS那样发送文本短信息之外,还可以发简单的图像,声音和动画等信息,而且仍 然可以运行在原有SMS运行的网络上,发送途径和操作也没有差别。不同品牌的手机只要支持EMS,都能互相传递EMS图片铃声。

  SMS

   SMS(short messaging service)即短信服务。是最早的短信息业务,也是现在普及率最高的一种短信息业务,通过它,移动电话之间可以互相收发短信,内容以文本,数字或二进 制非文本数据为主,目前SMS只是在手机内建立一段文字后再发送给朋友,简单方便易用,这种短信的长度被限定在140字节之内。

  WAP

  WAP(wireless application protocol)无线应用协议是一个开放式标准协议,利用它可以把网络上的信息传送到移动电话或其他无线通讯终端上。WAP是由摩托罗拉(MOTOROLA),诺基亚(NOKIA),爱立信(ERICSSON)等通讯巨头在1997年成立的无线应用论坛(PForum)中所制定的,它使用一种类似于HTML的标记式语言WML(wireless markup language),并可通过WAP Gateway直接访问一般的网页。

  WAP将internet和移动电话技术结合起来,使随时随地访问丰富的互联网络资源成为现实,但目前除少数PDA手机外,手机都不能访问这些WEB网站,而只能访问WAP网站。

  如,用户可以通过手机访问:http://wap.monternet.com,但无法访问(A768i/A760可以)http://www.monternet.com

  GPRS

   GPRS是General packet Radio Service的英文简称,通用无线分组业务,是一种基于GSM系统的无线分组交换技术,提供端到端的,广域的无线IP连接。通俗的讲,GPRS是一项高 速数据处理的科技,方法是以“分组”的形式传送资料到用户手上。GPRS属于2.5代移动通信技术,是中国移动GSM网络走向3G的主流技术。相对原来 GSM的拨号方式的电路交换数据传送方式,GPRS是分组交换技术,具有“实时在线”,“按流量计费”,“快捷登录”,“高速传输”,“自如切换”的优 点。

  2.5G

  目前已经进行商业应用的2.5G移动通信技术是从2G走向3G的衔 接性技术,突破了2G电路交换技术对使数据传输数率的制约,引入了分组交换技术,从而使数据传输速率有了质的突破,是一种介于2G与3G之间的过渡技术。 由于3G是个相当浩大的工程,所以牵扯的层面多且复杂,要从目前的2G迈向3G不可能以下就衔接得上,因此出现了介于2G和 3G之间的2.5G.

  GPRS,HSCSD,WAP,EDGE,蓝牙(Bluetooth),EPOC等技术都是2.5G技术。

 3G

  3G是英文3rd Generation的缩写,指第三代移动通信技术。相对第一代模拟制式手机(1G)和第二代GSM,TDMA等数字手机(2G)第三代手机一般地讲,是 指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。它能够处理图像,音乐,视频流等多种媒体形式,提供包括网页浏览,电话会议,电子商务等 多种信息服务。为了提供这种服务,无限网络必须能够支持不同的数据传输速度,也就是说在室内,室外和行车的环境中能够分别支持至少2Mbps(兆字节/每 秒),384Kbps(千字节/每秒)以及144Kbps的传输速度。

  目前2G网络提供的宽带是9.6Kpbs。2.5G增加到56Kpbs。3G将具有更宽的带宽,其传输速度将达到100-300Kbps,不仅能传输话音,还能传输数据,从而提供快捷,方便的无线应用,如无线接入Internet。

  手机的频段

  如同我们的固定电话有电话线一样,手机也有自己的“电话线”--信道。每个蜂窝式移动通信系统都有自己固定的频段,如800MHz, 900MHz频段等。如中国和欧洲的GSM网络采用900MHz和1800MHz两个频段,而美国GSM则使用1900MHz频段。

  智能手机

  智能手机(Smart Phone)也叫电脑手机,也就是电脑和手机的结合体。当电脑将它既有的强大多媒体功能和开放式操作系统注入了手机“肌体”之时,手机即变得无所不能,普通手机所不能解决得难题,都将在一瞬间“迎刃而解”。

  就目前看来,智能手机还没有一个准确得界限,通常所说的智能手机一般具有以下几个特点:有较强的PDA,商务,多媒体功能。具有很强的扩展性,集移动通信,移动办公和移动多媒体于一身。

  智能手机的操作系统

  现在智能手机的操作系统有三大阵营,分别是传统桌面系统的老大微软公司的Windows Mobile系统(多普达696)和Symbian公司研制多年的Symbian OS(Nokia6600,SEP908等),后者是现在最为流行的手机操作系统,还有后起之秀--Linux(MotoA760/A768).。

  和弦铃声

  和弦本是声学理论的一个专有名词,指的是一定音程关系的一组声音,后被手机厂家借用于手机铃声中,特指铃声音乐的复音数。因此手机中的和弦也叫复音,多音(Polyphony),是指Midi中各个通道的发音数之和,与乐理中的和弦已是不同的概念。

  和弦铃声比以往的单音铃声音色更丰富,具有强烈的立体感,目前流行的有16和弦,32和弦与40和弦等。

  蓝牙(Bluetooth)

  蓝牙(Bluetooth)是一种传输范围约为10米左右的短距离无线通信标准,用来设计在便携式计算机,移动电话以及其他的移动设备之间建立 起的一种小型,经济,短距离的无线链路。由于运行在统一频段,无线数据传输速率可达到720bps 到1Mbps,包含一套完整的加密和认证机制,因此具有很强的安全性。蓝牙的传输距离决定了它可以作为一种小型局域网的终端设备来与其他室内或随身的无线 设备交换数据。

  K-Java程序

  Java是 sun公司开发的一种较新的计算机编程语言,K-Java即J2ME(Java 2 Micro Edition),是专门用于嵌入式设备的Java软件。

  摩托罗拉率先在手机上预装了K-Java软件平台。随着K-Java技术的不断完善与发展,发展商们将对具有K-Java功能的手机用户提供更 多更全面的业务。如:互动游戏,互动新闻,增强手机连接到无线网络后进行数据交换的安全性,下载以Java语言写成的程序遥控家用电器。

  PIN码

  手机PIN码(Personal Identification Number)码的主要作用是防止SIM卡UIM卡遗失而被盗打设定的,当手机设置了“锁卡”功能时,打开手机电源,将提示输入PIN码,只有正确输入PIN码,手机才能登记入网,否则,不能使用。

  二、手机的主要功能

  通话功能

  对拨入拨出电话的管理

  对通话记录的管理

  呼叫转接、呼叫等待、通话计时计费等方便用户使用的功能

  消息功能

  文字短消息(SMS)的编辑、发送、接收、转发和存储等;

  多媒体短消息(MMS)的编辑、发送、接收、转发、存储和配置;

  电话本

  名片的管理

  存在SIM卡上的名片

  存在手机内存中的名片

  一个名字多项内容(如传真、固话、手机、Email等)

  名片的新建、修改、拷贝、转存、删除

  名片以红外或短消息形式发送给其它手机

  单键拨号(Speed Dialing)

  号码分组(Caller Groups)

  增值服务

  Business cards 的管理 (如发送和接收: 通过红外线或SMS. )

  书签的管理 (如发送和接收: 通过红外线或SMS或书签形式.  以及编辑,存储,新增和进入.)

  服务信箱 (自动存储服务信息. 服务信息有点播铃声,下载彩色图片和COD文件等.)

  服务设置 ( GPRS上网设置,WAP服务设置.)

  多模式浏览器  ( GPRS上网,WAP服务.)

  OTA待机图片 (通过无线下载待机图片)

  OTA铃声

  V-calendar

  XHML

  移动梦网

  动感地带

  其他功能

  闹钟(Alarm)

  日历(Calendar)

  计算器(Calculator)

  定时器(Count Down Timer)

  屏保(Screen Saver)

  待办事项(To-Do List)

  游戏(Games)

  为特定语言定做的功能

  中文输入(拼音/笔划)

  中文菜单

  农历(Lunar Calendar)

 附件

  充电器(Charger)

  耳机(Headset)

  车载免提(Car Kit)

  摄像头(Camera)

  数据连通

  GPRS 应用程序

  同步应用程序 (同步应用, 同步设置)

  红外线应用程序

  数据线

  手机Flash程序

  Trace Log

  JAVA 程序

  电子邮件

  QQ程序

  应用程序

  游戏程序

  三、手机性能测试

  时间有关

  长时间待机、长时间通话、长时间上网、长时间应用业务(mp3、mp4、摄像、游戏等)。

  效率:开机时间、关机时间、搜网时间、小区重选时间、小区切换时间。

  次数有关

  开关机成功率、主叫/被叫成功率、上网成功率。

  并发测试

  多业务 如:mp3+上网,通话+查询。

  终端性能测试

  射频性能(发射信号)

  音频性能(通话质量,在复杂环境下的性能)

  耗电性能(待机电流、通话电流)

posted @ 2013-05-17 10:10 顺其自然EVO 阅读(270) | 评论 (0)编辑 收藏

Loadrunner测试数据库性能

 Loadrunner测试数据库性能,测试SQL语句性能的脚本例子

  此代码为Loadrunner 8 通过C API类型的Vuser 测试MySQL性能,或者测试sql语句性能的脚本。

  这东西很少有人用,网上资料很少,一般测试B/S的很多。

view plaincopy to clipboardprint?
/*需要的表结构如下
CREATE TABLE `test_data` (
`order_id` BIGINT UNSIGNED NOT NULL COMMENT 'Order numbers. Must be unique.',
`status` BOOL NOT NULL DEFAULT '0' COMMENT 'Whether data has been used or not. A value of 0 means FALSE.',
`date_used` DATETIME NULL COMMENT 'Date/time that the data was used.',
UNIQUE (
    `order_id`
)
) ENGINE = innodb COMMENT = 'LoadRunner test data';
*/
Action()  
{  
int rc;   
int db_connection; // 数据库连接  
int query_result; // 查询结果集 MYSQL_RES  
char** result_row; // 查询的数据衕  
   
char *server = "localhost";  
char *user = "root";  
char *password = "123456";  
char *database = "test";  
int port = 3306;  
int unix_socket = NULL;   
int flags = 0;   
   
// 找到libmysql.dll的所在位置.  
rc = lr_load_dll("C:\\Program Files\\MySQL\\MySQL Server 5.1\\bin\\libmysql.dll");  
if (rc != 0) {  
    lr_error_message("Could not load libmysql.dll");  
    lr_abort();  
}  
   
// 创建MySQL对象  
db_connection = mysql_init(NULL);  
if (db_connection == NULL) {  
    lr_error_message("Insufficient memory");  
    lr_abort();  
}  
   
// 连接到MySQL数据库  
rc = mysql_real_connect(db_connection, server, user, password, database, port, unix_socket, flags);  
if (rc == NULL) {  
    lr_error_message("%s", mysql_error(db_connection));  
    mysql_close(db_connection);  
    lr_abort();  
}  
   
// 向数据库插入数据  
// 此处的 {ORDER_ID} 是一个参数,简单测试时可以用一个常数代替  
lr_save_string (lr_eval_string("INSERT INTO test_data (order_id) VALUES ({ORDER_ID})"),"paramInsertQuery");   
rc = mysql_query(db_connection, lr_eval_string("{paramInsertQuery}"));  
if (rc != 0) {  
    lr_error_message("%s", mysql_error(db_connection));  
    mysql_close(db_connection);  
    lr_abort();  
}

// 从数据库读取一个数据并显示  
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");  
if (rc != 0) {  
    lr_error_message("%s", mysql_error(db_connection));  
    mysql_close(db_connection);  
    lr_abort();  
}



query_result = mysql_use_result(db_connection);   
if (query_result == NULL) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}   
// 如果结果集包含多行数据,需要多次调用 mysql_fetch_row 直到返回NULL   
result_row = (char **)mysql_fetch_row(query_result);    
if (result_row == NULL) {   
    lr_error_message("Did not expect the result set to be empty");   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}   
// 保存参数,用于删除这行数据   
lr_save_string(result_row[0], "paramOrderID");   
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));   
mysql_free_result(query_result);   
    
// 在事务里更新一行数据,需要用InnoDB引擎   
rc = mysql_query(db_connection, "BEGIN"); //启动事务   
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}   
// 使用 "FOR UPDATE" 锁住要更新的数据行   
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1 FOR UPDATE");    
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}   
query_result = mysql_use_result(db_connection);   
if (query_result == NULL) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}   
result_row = (char **)mysql_fetch_row(query_result);    
if (result_row == NULL) {   
    lr_error_message("没有查询到结果");   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}   
lr_save_string(result_row[0], "paramOrderID");   
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));   
mysql_free_result(query_result);   
lr_save_string(lr_eval_string("UPDATE test_data SET status=TRUE, date_used=NOW() WHERE order_id='{paramOrderID}'"),"paramUpdateQuery");   
rc = mysql_query(db_connection, lr_eval_string("{paramUpdateQuery}"));   
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}   
rc = mysql_query(db_connection, "COMMIT"); // 提交事务   
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}

// 再次查找数据,应该为空了,因为前面的事务更新了标志   
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");   
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}   
query_result = mysql_use_result(db_connection);   
if (query_result == NULL) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}   
result_row = (char **)mysql_fetch_row(query_result);   
if (result_row == NULL) {   
    lr_output_message("Result set is empty as expected");   
    mysql_free_result(query_result);   
} else {   
    lr_error_message("Did not expect the result set to contain any rows");   
    mysql_free_result(query_result);   
    mysql_close(db_connection);   
    lr_abort();   
}


// 删除数据   
lr_save_string(lr_eval_string("DELETE FROM test_data WHERE order_id = '{paramOrderID}'"),"paramDeleteQuery");   
rc = mysql_query(db_connection, lr_eval_string("{paramDeleteQuery}"));   
if (rc != 0) {   
    lr_error_message("%s", mysql_error(db_connection));   
    mysql_close(db_connection);   
    lr_abort();   
}   
    
// 释放MySQL资源   
mysql_close(db_connection);   
    return 0;   

/*需要的表结构如下
CREATE TABLE `test_data` (
`order_id` BIGINT UNSIGNED NOT NULL COMMENT 'Order numbers. Must be unique.',
`status` BOOL NOT NULL DEFAULT '0' COMMENT 'Whether data has been used or not. A value of 0 means FALSE.',
`date_used` DATETIME NULL COMMENT 'Date/time that the data was used.',
UNIQUE (
    `order_id`
)
) ENGINE = innodb COMMENT = 'LoadRunner test data';
*/
Action()
{
int rc; 
int db_connection; // 数据库连接
int query_result; // 查询结果集 MYSQL_RES
char** result_row; // 查询的数据衕

char *server = "localhost";
char *user = "root";
char *password = "123456";
char *database = "test";
int port = 3306;
int unix_socket = NULL; 
int flags = 0;

// 找到libmysql.dll的所在位置.
rc = lr_load_dll("C:\\Program Files\\MySQL\\MySQL Server 5.1\\bin\\libmysql.dll");
if (rc != 0) {
    lr_error_message("Could not load libmysql.dll");
    lr_abort();
}

// 创建MySQL对象
db_connection = mysql_init(NULL);
if (db_connection == NULL) {
    lr_error_message("Insufficient memory");
    lr_abort();
}

// 连接到MySQL数据库
rc = mysql_real_connect(db_connection, server, user, password, database, port, unix_socket, flags);
if (rc == NULL) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}

// 向数据库插入数据
// 此处的 {ORDER_ID} 是一个参数,简单测试时可以用一个常数代替
lr_save_string (lr_eval_string("INSERT INTO test_data (order_id) VALUES ({ORDER_ID})"),"paramInsertQuery"); 
rc = mysql_query(db_connection, lr_eval_string("{paramInsertQuery}"));
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}


// 从数据库读取一个数据并显示
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}
// 如果结果集包含多行数据,需要多次调用 mysql_fetch_row 直到返回NULL
result_row = (char **)mysql_fetch_row(query_result); 
if (result_row == NULL) {
    lr_error_message("Did not expect the result set to be empty");
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}
// 保存参数,用于删除这行数据
lr_save_string(result_row[0], "paramOrderID");
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));
mysql_free_result(query_result);

// 在事务里更新一行数据,需要用InnoDB引擎
rc = mysql_query(db_connection, "BEGIN"); //启动事务
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}
// 使用 "FOR UPDATE" 锁住要更新的数据行
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1 FOR UPDATE"); 
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}
result_row = (char **)mysql_fetch_row(query_result); 
if (result_row == NULL) {
    lr_error_message("没有查询到结果");
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}
lr_save_string(result_row[0], "paramOrderID");
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));
mysql_free_result(query_result);
lr_save_string(lr_eval_string("UPDATE test_data SET status=TRUE, date_used=NOW() WHERE order_id='{paramOrderID}'"),"paramUpdateQuery");
rc = mysql_query(db_connection, lr_eval_string("{paramUpdateQuery}"));
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}
rc = mysql_query(db_connection, "COMMIT"); // 提交事务
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}



// 再次查找数据,应该为空了,因为前面的事务更新了标志
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}
result_row = (char **)mysql_fetch_row(query_result);
if (result_row == NULL) {
    lr_output_message("Result set is empty as expected");
    mysql_free_result(query_result);
} else {
    lr_error_message("Did not expect the result set to contain any rows");
    mysql_free_result(query_result);
    mysql_close(db_connection);
    lr_abort();
}

// 删除数据
lr_save_string(lr_eval_string("DELETE FROM test_data WHERE order_id = '{paramOrderID}'"),"paramDeleteQuery");
rc = mysql_query(db_connection, lr_eval_string("{paramDeleteQuery}"));
if (rc != 0) {
    lr_error_message("%s", mysql_error(db_connection));
    mysql_close(db_connection);
    lr_abort();
}

// 释放MySQL资源
mysql_close(db_connection);
return 0;
}














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

软件测试基本流程与要求

 1、目标

  制定完整且具体的测试路线和流程,为快速、高效和高质量的软件测试提供基础流程框架。

  最终目标是实现软件测试规范化,标准化。

  2、测试流程说明

  3、测试需求分析

  测试需求是整个测试过程的基础;确定测试对象以及测试工作的范围和作用。用来确定整个测试工作(如安排时间表、测试设计等)并作为测试覆盖的基础。而且被确定的测试需求项必须是可核实的。即,它们必须有一个可观察、可评测的结果。无法核实的需求不是测试需求。所以我现在的理解是测试需求是一个比较大的概念,它是在整个测试计划文档中体现出来的,不是类似的一个用例或者其他.

  ·测试需求是制订测试计划的基本依据,确定了测试需求能够为测试计划提供客观依据;

  ·测试需求是设计测试用例的指导,确定了要测什么、测哪些方面后才能有针对性的设计测试用例;

  ·测试需求是计算测试覆盖的分母,没有测试需求就无法有效地进行测试覆盖;

  3.1、测试方法与规范

  3.1.1、测试方法

  随着软件技术发展,项目类型越来越多样化。根据项目类型应选用针对性强的测试方法,合适的测试方法可以让我们事半功倍。以下是针对目前项目工程可以参考的测试方法:

  --β测试(beta测试)--非程序员、测试人员

  β测试,英文是Betatesting。又称Beta测试,用户验收测试(UAT)。

  β测试是软件的多个用户在一个或多个用户的实际使用环境下进行的测试。开发者通常不在测试现场,Beta测试不能由程序员或测试员完成。

  当开发和测试根本完成时所做的测试,而最终的错误和问题需要在最终发行前找到。这种测试一般由最终用户或其他人员完成,不能由程序员或测试员完成。

  --α测试(Alpha测试)--非程序员、测试人员

  α测试,英文是Alphatesting。又称Alpha测试.

  Alpha测试是由一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的受控测试,Alpha测试不能由该系统的程序员或测试员完成。

  在系统开发接近完成时对应用系统的测试;测试后,仍然会有少量的设计变更。这种测试一般由最终用户或其他人员来完成,不能由程序员或测试员完成。

  --兼容性测试--测试人员

  兼容性测试是指测试软件是否可以成功移植到指定的硬件或者软件环境中,例如在B/S项目中各个不同浏览器之间的测试。

--用户界面测试-UI测试  --测试人员

  用户界面测试,英文是User interface testing。又称UI测试。

  用户界面,英文是User interface。是指软件中的可见外观及其底层与用户交互的部分(菜单、对话框、窗口和其它控件)。

  用户界面测试是指测试用户界面的风格是否满足客户要求,文字是否正确,页面是否美观,文字,图 片组合是否完美,操作是否友好等等。UI 测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。确保用户界面符合公司或行业的标准。包括用户友好性、人性化、易操作性 测试。

  用户界面测试用户分析软件用户界面的设计是否合乎用户期望或要求。它常常包括菜单,对话框及对 话框上所有按钮,文字,出错提示,帮助信息 (Menu 和Help content)等方面的测试。比如,测试Microsoft Excel中插入符号功能所用的对话框的大小,所有按钮是否对齐,字符串字体大小,出错信息内容和字体大小,工具栏位置/图标等等。


  --冒烟测试--版本编译者

  冒烟测试,英文是Smoketesting。

  冒烟测试的名称可以理解为该种测试耗时短,仅用一袋烟功夫足够了。也有人认为是形象地类比新电路板功基本功能检查。任何新电路板焊好后,先通电检查,如果存在设计缺陷,电路板可能会短路,板子冒烟了。

  冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员。

  --随机测试--测试人员

  随机测试,英文是Adhoctesting。

  随机测试没有书面测试用例、记录期望结果、检查列表、脚本或指令的测试。主要是根据测试者的经验对软件进行功能和性能抽查。随机测试是根据测试说明书执行用例测试的重要补充手段,是保证测试覆盖完整性的有效方式和过程。

  随机测试主要是对被测软件的一些重要功能进行复测,也包括测试那些当前的测试样例(TestCase)没有覆盖到的部分。另外,对于软件更新和新增加的功能要重点测试。重点对一些特殊点情况点、特殊的使用环境、并发性、进行检查。尤其对以前测试发现的重大Bug,进行再次测试,可以结合回归测试(Regressivetesting)一起进行。

  --黑盒测试(功能测试)--测试人员

  黑盒测试,英文是BlackBoxTesting。又称功能测试或者数据驱动测试。

  黑盒测试是根据软件的规格对软件进行的测试,这类测试不考虑软件内部的运作原理,因此软件对用户来说就像一个黑盒子。

  软件测试人员以用户的角度,通过各种输入和观察软件的各种输出结果来发现软件存在的缺陷,而不关心程序具体如何实现的一种软件测试方法。

  --性能测试

  性能测试,英文是PerformanceTesting。

  性能测试是在交替进行负荷和强迫测试时常用的术语。理想的"性能测试"(和其他类型的测试)应在需求文档或质量保证、测试计划中定义。性能测试一般包括负载测试和压力测试。

  通常验证软件的性能在正常环境和系统条件下重复使用是否还能满足性能指标。或者执行同样任务时新版本不比旧版本慢。一般还检查系统记忆容量在运行程序时会不会流失(memoryleak)。比如,验证程序保存一个巨大的文件新版本不比旧版本慢。

  3.1.2、测试规范

  测试规范是根据开发规范而制定的测试标准,测试规范也是后期测试用例编写的重要依据。因为开发规范因公司而异,因产品而异,所以测试规范的标准程度每个公司都不一样。

  从理论到方法到各类流程到各类报告模版,都属于测试规范的范畴,当一整套规范形成之后,可使得测试工作进行更加稳健,所有问题有据可查。

  3.2、软件需求规格说明书

  软件需求规格说明书是软件达到的各项功能的目标。是测试人员各项工作的依据,没有需求就无法判断测试结果是正确的。

  3.3、软件设计说明(概要与详细设计)

  设计说明书包含软件的一些框架、字段、数据库设计等。软件设计说明对测试工作开展有很大影响,没有软件设计说明很多问题将无法溯源,测试准备的前期工作也是根据软件设计说明来制定的。


--用户界面测试-UI测试  --测试人员

  用户界面测试,英文是User interface testing。又称UI测试。

  用户界面,英文是User interface。是指软件中的可见外观及其底层与用户交互的部分(菜单、对话框、窗口和其它控件)。

  用户界面测试是指测试用户界面的风格是否满足客户要求,文字是否正确,页面是否美观,文字,图 片组合是否完美,操作是否友好等等。UI 测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。确保用户界面符合公司或行业的标准。包括用户友好性、人性化、易操作性 测试。

  用户界面测试用户分析软件用户界面的设计是否合乎用户期望或要求。它常常包括菜单,对话框及对 话框上所有按钮,文字,出错提示,帮助信息 (Menu 和Help content)等方面的测试。比如,测试Microsoft Excel中插入符号功能所用的对话框的大小,所有按钮是否对齐,字符串字体大小,出错信息内容和字体大小,工具栏位置/图标等等。


  --冒烟测试--版本编译者

  冒烟测试,英文是Smoketesting。

  冒烟测试的名称可以理解为该种测试耗时短,仅用一袋烟功夫足够了。也有人认为是形象地类比新电路板功基本功能检查。任何新电路板焊好后,先通电检查,如果存在设计缺陷,电路板可能会短路,板子冒烟了。

  冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员。

  --随机测试--测试人员

  随机测试,英文是Adhoctesting。

  随机测试没有书面测试用例、记录期望结果、检查列表、脚本或指令的测试。主要是根据测试者的经验对软件进行功能和性能抽查。随机测试是根据测试说明书执行用例测试的重要补充手段,是保证测试覆盖完整性的有效方式和过程。

  随机测试主要是对被测软件的一些重要功能进行复测,也包括测试那些当前的测试样例(TestCase)没有覆盖到的部分。另外,对于软件更新和新增加的功能要重点测试。重点对一些特殊点情况点、特殊的使用环境、并发性、进行检查。尤其对以前测试发现的重大Bug,进行再次测试,可以结合回归测试(Regressivetesting)一起进行。

  --黑盒测试(功能测试)--测试人员

  黑盒测试,英文是BlackBoxTesting。又称功能测试或者数据驱动测试。

  黑盒测试是根据软件的规格对软件进行的测试,这类测试不考虑软件内部的运作原理,因此软件对用户来说就像一个黑盒子。

  软件测试人员以用户的角度,通过各种输入和观察软件的各种输出结果来发现软件存在的缺陷,而不关心程序具体如何实现的一种软件测试方法。

  --性能测试

  性能测试,英文是PerformanceTesting。

  性能测试是在交替进行负荷和强迫测试时常用的术语。理想的"性能测试"(和其他类型的测试)应在需求文档或质量保证、测试计划中定义。性能测试一般包括负载测试和压力测试。

  通常验证软件的性能在正常环境和系统条件下重复使用是否还能满足性能指标。或者执行同样任务时新版本不比旧版本慢。一般还检查系统记忆容量在运行程序时会不会流失(memoryleak)。比如,验证程序保存一个巨大的文件新版本不比旧版本慢。

  3.1.2、测试规范

  测试规范是根据开发规范而制定的测试标准,测试规范也是后期测试用例编写的重要依据。因为开发规范因公司而异,因产品而异,所以测试规范的标准程度每个公司都不一样。

  从理论到方法到各类流程到各类报告模版,都属于测试规范的范畴,当一整套规范形成之后,可使得测试工作进行更加稳健,所有问题有据可查。

  3.2、软件需求规格说明书

  软件需求规格说明书是软件达到的各项功能的目标。是测试人员各项工作的依据,没有需求就无法判断测试结果是正确的。

  3.3、软件设计说明(概要与详细设计)

  设计说明书包含软件的一些框架、字段、数据库设计等。软件设计说明对测试工作开展有很大影响,没有软件设计说明很多问题将无法溯源,测试准备的前期工作也是根据软件设计说明来制定的。

3.4、页面原型(demo)

  页面原型是项目人员快速熟悉项目的最佳路径。在需求不够明确,设计说明书不够全面的情况下,页面原型也是后期测试用例编写思想的重要根据。

  4、测试过程设计

  明确测试目的,最终达成目的并验证结果是测试要做的事情。包括:

  1.测试范围:描述本次测试中的测试范围,如:测试软件功能范围、测试种类等。

  2.简单的描述如何搭建测试平台以及测试的潜在的风险。

  3.项目信息:说明要测试的项目的相关资料,如:输入输出文档,产品描述,软件主要功能。

  4.人力资源的分配。

  5.测试需求:笼统说,就是测试中的所有设计和需求文档。作为本次测试的依据

  4.1、测试策略制定

  这一阶段在于需求、详细设计、测试计划完成之后,主要是本次测试的策略阶段。很多公司少这个一个阶段,需要有计划性的分出产品的功能扣出测试的功能点,现阶段大多公司都是直接拿着文档就开始做用例设计。

  对需求进行分析,列出具体的功能列表。(一般根据功能交互文档就能明确出此功能的大体功能,一层层的分下去,一直到没个功能表单。然后考虑到使用那些测试方法?工作一旦做到执行阶段,我们可以更好的根据这些功能表一点一点的覆盖。也能让我们在用例评审时,充分的证实我们的工作是有效的能够保证产品的质量。)一般在此之前,一些业务培训和需求评审是有必要是听一下的。这样能够更早更熟练的理解需求,也能保证产品设计中出现的一些误区。

  对于一个个测试该如何进行测试?如下:

  a)功能测试

  ---功能范围(划分出各自负责的功能模块)

  ---使用测试方法(等价类、边界值等测试方法方法)

  ---测试标准(符合设计、需求和规范文档对该功能的描述)

  b)界面测试

  c)兼容性测试

  4.2、测试计划

  1)要充分考虑测试计划的实用性,即测试计划与实际之间的接近程度和可操作性。编写测试计划的目的在于充分考虑执行测试时的各种资源,包括测试内容、测试标准、时间资源、人力资源等等,准确地说是要分析执行时所能够调用的一切资源以及受各种条件限制,可能受到的各种影响。

  a)测试内容:对一个软件来说测试计划中会明确本次测试做哪些测试?

  如:系统测试:在整个系统测试中会有(界面测试、功能测试、性能测试、兼

  容性测试、安装卸载测试、可靠性测试等测试)。

  b)测试目的:一般多为保证产品质量是否达到预期的指标。这个指标也就是在测试中定义的结束标准。

  c)测试标准:需要考虑本次测试需要输入那些文档,该项目结束标准定义、测试结束标准的定义?bug级别定义、优先级定义、bug管理流程定义。这个都需要在执行测试事明确。计划中应该包含这些内容。

  d)资源分配:这里分为人力资源、软硬件资源等划分。一般会把人力资源的利用写入一个测试人员任务分配表里,按照不同的阶段,每个阶段提交相应的成果(难度很大)。软硬件资源中主要是在做计划时考虑到需要多少电脑或别的工具,列出清单。

  e)测试风险:大多考虑到的就是项目开发延期、测试人员不足用例无法全面覆盖测试点、时间不足用例无法全部执行、bug无法及时修改导致无法验证、测试人员技能不足导致测试进度拉长。

  f)软件测试策略一般都是分开来做相关测试方案。




4.3、测试附件

  用例模板、缺陷报告模板

  测试环境的搭建

  缺陷管理流程和缺陷级别定义

  缺陷状态一般分为:新建、打开、已分配、已修复、关闭、重新打开

  中间会有:延期、重复、拒绝等状态

  缺陷管理流程:

  1.测试人员或开发人员发现bug后,判断输入哪个模块的问题,填写bug报告后,系统会自动通过Email通知开发组长和该模块开发者。

  2.开发组长根据具体情况,重新reassigned分配给bug所属的开发者。

  3.开发者收到email信息后,判断是否为自己的修改范围。

  若不是,重新reassigned分配给开发组长或应该分配的开发者。

  若是,进行处理,resolved并给出解决方法。(可创建补丁附件及补充说明)

  4.测试人员查询开发者已修改的bug,进行回归测试。

  经验证无误后,修改状态为verified。待整个产品发布后,修改为closed。

  还有问题,reopened,状态重新变为"new",并发送邮件通知。

  5.如果这个bug一周内一致没被处理过。Bugzilla就会一直用email骚扰它的属主,直接采取行动。管理员可以设定最迟采取行动的期限,比如3天,系统默认7天。

  缺陷等级划分:




 5、测试实施

  5.1、执行

  开发就会转版本给我们测试部门进行系统测试了。拿到版本我们首先搭建测试环境

  做一个预测试,目的是来评断这个版本是不是可测试的。如果预测试不通过,打回开发部返工,如果通过了,就开始我们第一轮的系统测试。

  第一轮系统测试我们会执行我们所编写的所有测试用例,做好测试结果的记录,发现缺陷了提交缺陷报告。当第一轮测试结束后,我们把所有的bug单提交给开发人员,由他们进行修改。

  在他们修复bug期间,我们会对第一轮系统测试做一个测试评估,出一个测试报告。还要根据实际情况,对我们写的测试用例进行修改和增加。开发改bug结束,提交一个新的版本给我们,我们重新搭建测试环境开始第二轮系统测试。首先是回归我们提交的缺陷报告,然后会在用例中挑选一些优先级别比较高的用例来进行测试,发现问题了继续提交缺陷报告,只到缺陷率低于用户要求了,我们就进行最后一轮的回归测试,结束系统测试。具痰某沙と占牵匾唬�">一个软件测试工程师的成长日记(连载一)(图)

  • 自动化测试之QTP入门宝典






  • 52

    posted @ 2013-05-16 10:57 顺其自然EVO 阅读(396) | 评论 (0)编辑 收藏

    基于测试流程上的缺陷管理系统

     ● 缺陷的定义

        → 软件没有达到产品说明书表明的功能

        → 软件出现了产品说明书中不一致的表现

        → 软件功能超出产品说明书的范围

        → 软件没有达到用户期望的目标(虽然产品说明书中没有要求)

        → 测试员或用户认为软件的易用性差

      ● 不是所有缺陷都会修改

        → 市场的压力使得产品最终发行有时间限制

        → 测试员错误理解或者不正确操作引出的缺陷(FAQ)

        → 错误的修改影响的模块较多,带来的风险较大(遗留)

        → 修改性价比太低(FAQ,遗留)

        → 缺陷报告中提出的问题很难重现

      1、缺陷报告管理系统

      ● 是测试流程在工具上的固化

      ● 通过权限控制来实现流程监控

      ● 记录了缺陷识别到关闭过程中的所有数

      ● 记录了版本变更的信息

      ● 是开发和测试之间沟通的信息平台

      ● 实时的数据和信息的更新

      ● 度量和统计分析,为改进产品提供依据

      方正测试缺陷跟踪与管理系统

      ● 采用Lotus Notes作为bug管理平台

      ● 完全电子化的信息传递

      ● 统一管理和备份

      具备数据统计和查询功能

      能够进行个性化二次开发

      1.1 系统测试缺陷处理流程



    缺陷报告

      ● Bug报告准则

        → 如何重现错误-使用最少步骤重现

        → 现象描述没有歧义

        → 尽量简单-一个bug一个报告

        → 可以提出对错误的解决建议

      ● 开发人员拒绝修改的bug

        → 程序员无法重现或者现象难以捕捉

        → 没有明确的报告以说明重现bug的步骤

        → 程序员无法读懂的bug报告

        → 用户很少使用或者不符合用户使用习惯的操作出错

        → 由不受信任的测试人员提出

      1.2 集成测试缺陷处理流程









    ● 缺陷分析的关注点:

      1、对软件问题的功能域分布进行分析,找出系统的薄弱环节

        → 要详细采集每个功能模块或系统构件的bug数据,并按功能、错误类型、严重程度等分类

        → 比较实际发现的软件bug是否与预期的问题分布相吻合

        → 二八定理:80%的软件问题总是发生在大约20%的功能模块(系统构件)中。

      2、对bug的注入阶段的分布进行分析,并与历史数据相比较。应按不同的开发阶段详细采集bug的数据

        → 要求软件各开发阶段的缺陷密度小于本单位过去的平均值

        → 而且要求需求分析、设计和代码复查阶段的缺陷排除率之和大于或等于规定值(例如75%)。(同行评审)

      3、应对软件缺陷类型进行分析,以便针对各自的特点,先修复严重缺陷。

        → 可参考PSP中缺陷类型标准(如下表),其中缺陷类型是按照问题的复杂度来排列的,类型10到40是比较简单的编码缺陷,类型50到100是比较复杂的设计缺陷。

      4、应动态采集每个测试周期中发现的bug数,并有效地控制缺陷的修复率。

      5、应密切观察bug的状态,并及时跟踪其状态的变化,以检查测试和开发人员的工作情况

      6、应该采集bug不同方式的修复数据,以便检验软件产品是否满足交付规则

        → 分析修改代码、改变设计、封掉功能遗留以及下一版本解决的bug数约占缺陷总数的比例。

        → 在有严密和有效的质量保证体系条件的监控下,常常会引起有较高比例的延期解决的缺陷数,这是因为许多细微的或枝节性的问题被测试出来,经过评价证明不会造成大的质量影响,但可为产品进一步升级提供有价值的参考。

      ● 测试人员的绩效评价

        → 评价标准:

          1、bug数量:

          同一个项目组内,提交bug数量的多少是衡量测试人员工作效率的一方面;另一个衡量指标是每人日提交的bug数。

          2、bug严重程度:

          Bug的严重程度是衡量bug的质量的一个重要因素,好的bug应该是极端严重的,对系统造成极大危害的。

          3、bug价值:

          Bug的双方面评判,对于bug的价值开发人员在另外一个角度上进行评判

          以上三个因素的加权平均才能更有效的评价测试人员的绩效!

      缺陷统计分析工具介绍



      ●测试结果分析和评价

        缺陷密度:

          → 基本的缺陷测量是以每千行代码的缺陷数(Defects/KLOC)来测量的。称为缺陷密度(Dd),其测量单位是defects/KLOC。可按照以下步骤来计算一个程序的缺陷密度:

          → 累计开发过程中每个阶段发现的缺陷总数(D)。

          → 统计程序中新开发的和修改的代码; height:28px;">

     

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

    有效的自动化测试策略

    鉴于项目组以及整个Team的自动化测试现状,我在我们Team内部的一次Share会议上分享了我对于有效自动化测试策略的一些看法,可能观点相较于其他同事,比较极端,但是我的初衷其实是想给大家敲个警钟,不要小欲则安,浅尝辄止,我们应该保持对自动化,敏捷,以及持续集成的不断追求,在保证质量的同时提高效率。

      因此对于什么样的自动化测试才是有效的,我强调首先第一点,我们要确保我们的自动化case对我们的项目有用

      相信这一点,绝大多数人都是认同的,但是我这里把它又拎出来是因为,知道是一回事,但是有没有照着做又是另外一回事。要说做自动化,大家都做,都愿意做,但是我们做的真正对我们的项目有用嘛?下面是我罗列的三条标准:

      ● 要确信你的自动化case是有价值的,可以代替你的手动测试

      自动化测试,尤其是功能性,基于User Story的case,多数是对手动case的Cover,也就是说代替手动case的。所以说我们必须确信我们的case是有价值的,可以代替我们去执行相应的手动case。至于什么是有价值的自动化case,我们相信应该是这样的:在一定的环境中执行过了自动化case,我们就相信,在这个环境中,我们没必要再进行同样的手动操作。

      至于如何写出有价值的case,当然也有其策略和方法,这里不再提及。

      ● 在测试环境中的执行才更有价值的

      上条说道,在一定的环境中去执行case,那这个一定的环境是什么样的环境呢?这里我的观点可能比较极端,我认为写case的环境,是我们的开发环境,并不是我们理想中的测试环境。

      那什么才是测试环境呢?答案就是,我们自己定义的,并且专门用于测试的环境。这个环境的所有情形都是Expected,或者是可枚举的。比如说装什么系统,装什么相关软件,如何跑我们的case,这都应该是定义好的。这样的环境才是测试环境。

      也许有人会对我这里定义的测试环境持反对意见,认为这样的环境并不是用户真实使用的环境,我们应该在更复杂的环境中去执行自动化测试,以期找到更多的bug。但是我认为自动化测试的目的就是做Regression Testing,以期有效的功能测试和版本控制。自动化测试并不能代替手动case,它应该是一个增量式的过程,我们不要期望让自动化发现更多的bug,而应该不断的添加,丰富各种自动化case,以及Bug Verification,以解放测试人员,让其更关注于测试本身。

      ● 能持续集成的运行了,才算我们的自动化测试跑起来了

      这条算是锦上添花型的,持续集成是业界非常好的经验总结,不光适用于我们测试,实际上她应该是适用于整个项目的。要想做到持续集成我们有很多的开源工具可以选择,这条是大力提倡的。

      第二点,我们要拥抱任何有意义的变化

      这一点非常重要,这个是观念上的转变。很多时候,公司,领导花了大价钱,大精力,来让我们做自动化,而且我们也通过现有的,或者是买来的工具,也确实做了自动化。但是更多时候总会因为这样或者那样的原因,啥项目周期短啊,需求总是变动啊,导致我们的case这条挂了,那条跑不起来了,修了再修,最后测试人员也烦了,自然的,自动化case最终也束之高阁,日久生尘。

      但是这里我仍然强调,我们要拥抱任何有意义的变化,这是观念上的转变。为了做出更好的产品,需求在变,代码也跟着变,我们的case在变,自动化case又有何理由不变呢?如果因为需求的变动导致我们自动化case挂了,我们应该高兴才是,因为我们的case成功的侦测到了这个变动,它是有价值的。换句话说,如果需求都变了,而我们的case还跑的好好的,那我可就要怀疑你的case到底有没有价值喽?!

      拥抱任何有意义的变动,不是说创建稳定性好的自动化case就没有意义了。试想如果因为一个蚁穴,就导致我们的自动化大堤全线崩溃,那自动化的工作量可就如山高,如海深喽,那又谈何敏捷呢?!

      第三点,至于如何做自动化,我想说,Just Coding!

      虽然测试自动化可能并不如开发那么高深,但是我觉得我们不要自己潜意识当中就把自己限制的死死的,“我就是个测试,我肯定不如开发”,这样的观点是不对的。尤其现在公司推行的Scrum模式,其理想状态是不分DEV和QA的,大家都是敏捷模式的一员,工作甚至也是可以互相交换的。

      当然,现阶段无可否认,DEV的开发水平会更高一些,但是对于我们QA,尤其是做开源领域比如Android的测试,做自动化的终极解决方案其实就是阅读产品代码,当我们读懂了开发代码,那写测试case就不是问题了。

      Conclusion

      所以我最终的的建议就是:Just Coding,Just Do It!只有真正去做了,你才会发现问题,才会想到去解决问题,才会想到要总结一些方法,然后让我们的Case在测试环境中自由的跑起来!

    posted @ 2013-05-16 10:46 顺其自然EVO 阅读(280) | 评论 (0)编辑 收藏

    仅列出标题
    共394页: First 上一页 249 250 251 252 253 254 255 256 257 下一页 Last 
    <2024年11月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    导航

    统计

    常用链接

    留言簿(55)

    随笔分类

    随笔档案

    文章分类

    文章档案

    搜索

    最新评论

    阅读排行榜

    评论排行榜