var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-333696-1']); _gaq.push(['_trackPageview']); _gaq.push(['_trackPageLoadTime']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();
  • 2008年06月15日

    【翻译】如何测试AJAX应用程序(1)

    分类:

    原作者:Markus Clermont, John Thomas

    原文第一部分第二部分

     

    背景

    通常我们解决测试AJAX应用程序通过过多的大的端到端测试,并且(很有希望地)高单元测试覆盖。这里,我们概要了用这种方法的主要问题并演示一个有效的测试策略为一个基于GWT应用程序的示例,它超过“测试仅通过GUI。”

     

    GUI测试的问题

    一般通过GUI测试:

    l  是昂贵的(需要长时间写测试而且执行是资源密集型)

    l  有限地深入系统

    l  通常仅考虑“恰当路径”

    l  把多个方面化合成单个测试

    l  速度慢且脆弱

    l  需要大量的维护

    l  很难调试

     

    而在单元测试中不面临许多这些问题,它们本身不够主要是因为它们:

    l  较少深入组件间如何相互交互

    l  不提供业务逻辑和系统功能满足需求的信心

     

    解决办法

    虽然没有“一个通适”解决方案,有一些基本原则我们可以使用,以解决web应用程序的测试问题:

    l  投资在集成测试(找出最小的子系统)

    l  关注分离(不做安排通过你正在测试的接口)

    l  单独地测试每个接口(模拟出所有你不在测试的内容)

    l  考虑在生产中的依赖 (找出如何依赖能失败,并测试它)

    l  混合使用策略和工具。没有银弹。

    l  还有不要。。。你不能扔弃你所有的端到端测试

     

    好的测试食谱

    使用上述原则我们可以建立用于测试 Web 应用程序一个食谱。

    1.     探索系统的功能

    2.     确定系统的体系结构

    3.     确定组件间的接口

    4.     确定的依存关系和故障状态

    5.     对每个功能:

    l  确定参加组件

    l  找出潜在的问题

    l  隔离测试问题

    l  创造一个“恰当路径”测试

    后注:测试的价值

    常见由开发人员编写测试时问道的问题,“这真正值得我的时间?”简短的回答是“总是!”。由于修复一个bug比首先预防它更为昂贵,编写好的测试始终值得耗费时间。

     

    虽然有许多不同分类的测试,最常见分类它们的方式是基于它们的大小和它们测试产品的面。每个测试回答有关产品的特定的问题:

    l  单元测试:该方法履行了其制约?

    l  小集成测试:两个类能互相交互?

    l  中等集成测试:类能正确交互它的依赖?是否正确预见和处理错误?所需的函数是否公开APIGUI 上?

    l  子系统测试:两个子系统能互相交互?是否其中一个预期其它所有的错误并相应地处理它们?

    l  系统测试:是否整个系统如预期表现?

     

    记住这个问题,各种级别的测试使我们可以编写更集中和有意义的测试。请记住有效的测试是指那些提供快速和有用的反馈,即快速识别问题和定位该问题的确切位置。

     

    测试应用程序

    我们要测试的示例应用程序是一个简单的库存管理系统,它允许用户增加或减少在不同的存储地点的部分数。该应用程序使用GWT构建但这里描述的测试方法能使用到任何AJAX应用程序。

     

    让我们看看详细的每个步骤:

    1.    探索系统的功能

    听起来简单,它是测试应用程序一个关键的第一步。在你能开始写测试用例前,你需要从用户角度看系统如何运行。开启应用程序,浏览,点击按钮和链接并获取该应用程序的“感觉”。这里我们的示例应用程序如下所示:

    应用程序有一个导航板过滤清单的地点,列出每个位置中的项目数,增加/减少平衡的项目并依据办公室和产品排序清单。

     

    2.    确定系统的体系结构

    有关系统体系结构的学习是下一个关键的步骤。这一点上认为,该系统作为一组组件和找出他们如何互相交谈。设计文档和体系结构图有助此步骤。 在我们的示例中我们有下组成部分:

    l  GWT客户端:Java代码编译成驻存在用户浏览器的JavaScript。与服务端通过HTTP-RPC进行通信

    l  Servlet:标准Apache Tomcat servlet服务"frontend.html"(主页面)用注入的JavaScript,并服务RPC以同客户端JavaScript进行通信

    l  服务器端实现的RPC桩:Servlet调度RPC通过HTTP调用来实现它。RPC实现通过协议缓冲区同RPC后端进行通信

    l  RPC后端:处理业务逻辑和数据存储。

    l  Bigtable:用于存储数据

     

    这有助于绘制一个简单的关系图,表示这些组件之间的数据流,如果不存在:

    在我们的示例应用程序中,RPC实现称为“存储服务”,而其它RPC后端称为"办公室后端"

     

    3.    确定组件间的接口

    一些明显的是:

    l  gwt_module指向Ant构建文件

    l  “服务”Apache Tomcatservlet

    l  RPC接口的定义

    l  协议缓冲区

    l  Bigtable

    l  用户界面(毕竟它是一个接口!)

     

    4.    确定的依存关系和故障状态

    随着接口被正确识别,我们需要确定依赖项并支出被需要模拟系统中错误条件的输入值。

     

    我们的案例中,用户界面跟servlet交互反过来servlet又跟存储服务(RPC实现)交互。我们应验证在存储服务时会发生什么:

    l  返回空

    l  返回空列表

    l  返回大列表

    l  返回列表格式不正确的内容 (错误编码,空或长字符串)

    l  超时

    l  获取两个并发调用

     

    除了RPC实现(存储服务)RPC后端(办公室管理)交互,再次我们要确保正确的调用被引发和在后端时会发生什么:

    l  返回格式不正确的内容

    l  超时

    l  发送两个并发请求

    l  抛出异常

     

    为了实现这些目标,我们将要用模拟(原文:mock)替代RPC实现(存储服务),这样我们能控制,并使servlet同模拟交互。对办公室管理是同样的-我们将要用一个更可控的欺骗替代实际的RPC后端,并使存储服务同该模拟交互。

     

    为了更好地概述,我们会首先看个别用例并看组件间如何互动。示例将是用户界面上的过滤功能(只有那些在导航板中在勾选位置被勾选的项将被显示在表中)

    分享到:

    历史上的今天: