此空间已闲置,个人主页已转到http://www.hixk.net

发布新日志

  • 自动化测试成功的关键: 制定计划

    2007-08-30 11:21:03

    在本文中,我们要讨论为什么进行测试,尤其是自动化测试,是必需的。然后,我们将介绍制定计划的概念:为什么制定计划是如此的重要?在随后的文章中,我们将分解测试计划中的不同因素,并且研究如何进行制定计划的过程才能最大程度地增加成功的机会。

    现代客户端/服务器应用程序是非常复杂的,因此测试也就成为开发过程中关键的并且至关重要的一部分。现在,没有人会考虑(或者承认)不对自己开发的软件进行测试工作。但是,研究和调查表明,在软件开发过程中,制定测试计划却常常是优先级较低的工作项目。而且,更加糟糕的是,计划往往没有被执行,或者即使执行了,也进行的不很完整、不很准确,或者没有持续进行。

    假设我们都赞成测试是必要的,那么我们接下来必须回答这些问题:我们如何进行测试?实际上都包括哪些内容?我们如何保证已经进行了有效的工作,并且真正地改善了应用程序的质量?

    答案很简单:制定计划。

    本文是系列文章中的第一篇,该系列文章将评审在软件生命周期中制定测试计划的作用,以及有效制定测试计划的有关概念。在本文中,我们要讨论为什么进行测试,尤其是自动化测试,是必需的。然后,我们将介绍制定计划的概念:为什么制定计划是如此的重要?在随后的文章中,我们将分解测试计划中的不同因素,并且研究如何进行制定计划的过程才能最大程度地增加成功的机会。

    为什么花费精力制定计划?

    现在看来,没有怎么制定测试计划而造成的后果比以前更加明显了。失败的案例有很多--看看报纸或者杂志就知道了。还有一些明显的低质量软件的案例,它们包括:

    • AT&T-一个软件交换系统,系统崩溃造成了美国几乎24小时的长距离通信中断。仅仅修改了一行源代码就解决了问题。
    • Denvor机场--软件的缺陷延误了机场的开放几乎长达9个月之久,据估算,每天花费纳税人大概$500,000。
    • Ashton-Tate--在80年代,Ashton-Tate的DBASE软件是基于PC的数据库应用程序的实际标准。版本中的缺陷导致了利润的减少,最终造成了Ashton-Tate(和DBASE)的转让。Ashton-Tate最后被Borland(拥有极具竞争力的数据库管理应用程序,Paradox)收购。

    当然,这些都是知名度很高的公司和项目。这些问题不会出现在您的公司中,对吗?

    错误!我们都要面对软件的缺陷,在我们的组织中与外界都是一样,这些问题都是关键的,也是很明显的。这里有一些低质量软件的更加共同的症状:

    生产力损失

    • 系统性能
    • 缺少功能/特性
    • 没有满足用户需求--无法销售

    用户挫折感

    • 强迫用户以不直观的方式执行任务
    • 循环工作
    • 延迟
    • 没有满足预期目标
    • 存在用户操作错误与理解错误




    回页首


    系统崩溃,数据丢失/破坏

    客户端/服务器应用程序到底有什么差别?

    客户端/服务器应用程序为质量保证专家带来了不同的挑战,下面是一些比较重要的内容:

    快速应用程序开发

    大多数的客户端/服务器应用程序都使用快速程序开发(RAD)方法学进行开发。测试人员必须"努力跟上"这些较短的开发周期。早些时候,非客户端/服务器应用程序常常使用18-24个月就完成了整个的开发过程和初始部署。现在,使用RAD,应用程序的发布需要经过多次部署或者"块"。每个块都基于以前的版本,并且包括改善、修改和修理。每个块都需要多次创建或者迭代的原型。每个块都需要进行测试,并且在3-6个月的更短时间内完成。

    客户端/服务器架构

    当前的客户端/服务器应用程序都需要很多的软件组件结合起来以实现功能,包括客户端应用程序、工作站操作系统、网络和数据库管理系统。常常也包括其他的组件,例如为实现正确执行而包含的附加源代码的DLL(动态连接库)、事务处理器或者应用程序与数据库管理服务。软件的每个附加"层"都在客户端/服务器架构中增加了额外的复杂度(并且需要进行测试)。

    多种类型的测试

    另外,测试客户端/服务器应用程序也需要使用许多不同类型的测试方法,例如,功能测试、用户界面、性能测试以及配置测试。这些测试都针对一个或几个测试目标。为了防止测试迂回不前或者尝试同时测试所有内容,每种测试必须制定仔细的计划。当您进行自动化测试时,这一点尤其正确。

    数据

    对于我们执行的每种类型的测试,都必须使用数据。数据对于测试的执行和成功完成来说是至关重要的,因为要使用数据识别最初的应用程序数据状态(条件),并且调用或者引出特定的事件或者操作。而且也要使用数据来验证测试事件或者操作是否运行正常!

    制定测试计划的其他原因

    如前所述,现代的应用程序与以前开发的应用程序相比具有很大的不同。客户端/服务器技术加强了我们开发与部署以任务关键型的企业系统的能力,而且花费的周期更短,提供的功能更加强大。客户端/服务器应用程序也为开发人员与终端用户提供了大量的选择和控制。但是使用这些好处的同时,也需要加强测试。

    测试自动化

    逐渐地,测试软件必须使用测试自动化工具和技术,以满足具有挑战性的日程安排。但是,单单使用工具还不足够,成功的测试自动化需要制定测试计划。在没有进行计划的条件下,实施测试自动化只会带来自动化的混乱。使用测试自动化工具,我们可以管理混乱并且识别过程中造成混乱的因素,同时管理项目费用(例如"未被文档化的特性/变更")。

    测试自动化是使软件测试人员跟上开发人员脚步的惟一方式,软件测试人员可以像测试早先构建版本那样,充满信心地、可靠地测试新构建的版本。

    但是测试常常为测试人员带来挑战,他们必须最有效地、生产力极高地使用时间,进行工作。测试自动化引入了一种新型的资源需求--测试开发。手工测试需要进行测试设计,以识别测试的内容和方式,但是由于没有使用工具,所以也没有必要开发任何的测试脚本或过程,仅仅来调试一下系统,然后使用键盘就可以了!如果对于每个要进行的测试,需要使用的资源仅仅是键盘,那么就可以看出,您并没有有效地利用时间。

    测试开发是一种新技术,在设计完成之后,需要使用工具并且创建测试过程。作为一种有效的方式,可以使用三名不同的技术员,并确保将最高级的资源用于设计与制定计划任务上,而将中级资源(或外界资源)用于开发与执行。这样可以增强职员所需的能力,并且共享资源,同时也不会对项目计划产生什么影响。

    缺陷管理与分析

    缺陷是肯定会被发现的。这是进行测试的结果,或者说是目的,所以我们必须对缺陷的生命周期进行识别和沟通,同时分析结果以确保缺陷已被有效地并且高效地处理。制定测试计划能够确保缺陷管理与分析是一笔面向整个项目的宝贵资产,而不会带来阻碍。如果您还没有配备缺陷管理系统和过程,或者已具有但是工作得不是很理想,那么制定测试计划就会给您带来创建(或者修正)它的机会。

    制定测试计划也可以识别应该使用什么样的度量方法。制定测试计划可以处理您所度量软件质量程度的问题。它也可以处理如何度量与沟通缺陷密度或缺陷趋势的问题。

    另外,制定测试计划可以识别与沟通数据收集与分布的方式,也应该指明使用报告的格式,以及作出报告的时间。

    风险分析

    制定测试计划提供了进行风险评估的机会。风险与不利因素对于组织来说是就一场噩梦,但是它们也是可以被控制的。不过首先必须对其进行分析。风险分析有助于制定测试工作的优先级,并且关注所进行的工作,确保测试内容的正确性,以正确的顺序解决正确的问题。(所谓正确,是以组织的风险与可接收度为基础的。)

    对于每个项目来说,都要进行风险评估并将其用于识别潜在的风险或者未发现缺陷带来的影响。风险应该用来评估缺陷对于直接终端用户、数据或者其他终端用户和应用程序带来的影响。这些数据可以用来建立测试优先级,并且评估所有约束,例如面市时间、预算或者费用,或者质量问题。

    风险评估还应该包括对于现有标准、指南和需求的评审。其目的就是为了分析这三种文档,判断它们对于项目是否恰当,并且由此进行实施或者修正。

    评审任何可能影响或者对项目带来冲击的外界因素也是很重要的。这些影响可以包括特定用户请求、规范的需求、或者市场条件,这其中的任何一项都可以变更风险或者优先级的评估结果。

    过程改善

    制定测试计划就是为测试过程制定文档。为测试制定计划不仅仅为文档化并且沟通测试工作提供机会,也可以评审测试工作的有效性。

    您曾听到过以下对话吗:

    "用户报告发现缺陷在…,难道你没有测试它吗?"
    "这是如此的明显,你怎么能发布带有这种缺陷的产品呢?"
    "我知道你已经说了需要三个月的时间进行测试,但是你只有两个…"

    改善产品质量(具有较少的软件缺陷)需要对产品开发过程进行持续的完善工作。开发测试计划可以使测试人员能够识别、执行、度量并且改善他们的测试工作。

    总而言之,可以从几个理由来说明制定良好计划的自动化测试的必要性。首先,不进行测试的组织会大大增加出现重大系统故障的可能,带来延迟,花费巨资进行修复,而且还可能潜在地带来对于客户信心无法修补的破坏。其次,现代客户端/服务器应用程序的本质允许快速地开发出复杂度很高的系统,该系统完全无法使用传统的手工方法进行正确的测试。最后,制定计划的目的就是为了管理不断增加的测试过程,分析并且跟踪已被发现的缺陷,执行关键性风险分析,并且持续改善测试与开发过程。在下一篇文章中,我们将更加深入地研究制定计划的过程,识别特定步骤,并且讨论如何才能开发出制定计划过程的有效策略。





    回页首


    IBM 软件集成解决方案

    IBM Rational 支持大量的 IBM 软件产品。IBM 软件解决方案可以赋予您实现优先业务和 IT 目标的能力。

    • DB2® 软件提供了数据支持、数据管理和数据分布的解决方案,可以帮助您有效地利用数据。
    • Lotus® 软件提供了编辑、管理、交流和共享知识的解决方案,可以帮助提高职员的生产率。
    • Tivoli® 软件帮助您管理那些运行在您的电子商务基础设施上的技术。
    • WebSphere® 软件帮助您把原来的关键业务扩展到 Web 上。
    • Rational® 软件提供的工具、服务和最佳实践可以帮助您提高软件开发能力。




    回页首


    IBM 的 Rational 软件

    来自 IBM 的 Rational 软件可以提高企业的软件开发能力来帮助他们创造商业价值。Rational 软件开发平台综合了软件工程最佳实践、工具和服务。通过它企业可以提高响应能力、更富有弹性、更加专注,从而在当前随需应变的世界中脱颖而出。Rational 基于标准的跨平台解决方案可以帮助软件开发团队创建和扩展业务应用程序、嵌入式系统和软件产品。《财富》100 强中有 98 家公司依靠 Rational 工具更快地开发更好的软件。更多信息可以访问 www.rational.comwww.therationaledge.com,以及每月一期的 Rational 社区电子杂志。



    参考资料

    • 您可以参阅本文在 developerWorks 全球站点上的 英文原文


    关于作者

    IBM has authored this article

  • 测试对象串行化

    2007-08-30 11:20:14

    Elliotte Harold (elharo@metalab.unc.edu), 副教授, Polytechnic University

    2006 年 7 月 06 日

    即使最杰出的开发人员有时也会忘记测试对象串行化,但那并不能作为您犯下同一错误的借口。在这篇文章中,Elliotte Rusty Harold 将解释对对象串行化进行单元测试的重要性,并为您展示一些应牢记的测试。

    测试驱动的开发的总体原则之一就是应测试一个类已发布的所有接口。如果客户机能够调用方法或访问字段,那么就测试它。但在 Java™ 语言中,许多类都有一个已发布的接口容易被遗漏:通过类实例生成的串行化对象。有时这些类显式实现 Serializable。而有时则是直接从超类继承这一特性。在任何一种情况下,您都应该测试其串行化形式。本文将介绍几种测试对象串行化的方法。

    测试串行化

    对串行化来说,测试极其重要,因为串行化非常非常容易出错。在修复 bug 或优化类时,非常容易破坏所有已有串行化对象。如果您在更改代码时未考虑串行化,几乎可以肯定您必将破坏原有对象。若您正在为任何形式的持久性存储使用串行化,那么这将是一个严重的 bug。即便仅为流程间的瞬时消息传递(如在 RMI 中)使用对象串行化,更改串行化格式也会使那些各类的版本不完全相同的系统无法顺利交换数据。

    幸运的是,若您谨慎对待串行化问题,在处理类时通常可以避免不兼容的更改。Java 语言提供了多种方法,可维护一个类的不同版本之间的兼容性,包括:

    • serialVersionUID
    • transient 修饰符
    • readObject()writeObject()
    • writeReplace()readResolve()
    • serialPersistentFields

    对于这些解决方案来说,最大的问题就在于程序员未使用它们。当您将精力集中在修复 bug、添加特性或解决性能问题时,往往不会停下来思考您的更改对串行化造成的影响。然而串行化是一个涉及范围极广的问题 —— 跨越一个系统的多个不同层。几乎所有更改都会涉及对串行化有某种影响的一个类的实例字段。这正是单元测试发挥作用的时机。在本文后续各节中,我将为您展示一些简单的单元测试,这些单元测试能确保您不会不经意地更改可串行化类的串行格式。







    我能否将其串行化?

    通常您编写的第一个串行化测试就是用于验证串行化是否可行的测试。即使一个类实现了 Serializable,依然不能保证它能够串行化。例如,如果一个可串行化的容器(如 ArrayList)包含一个不可串行化的对象(如 Socket),则在您尝试串行化此容器时,将抛出 NotSerializableException

    通常,对此测试,您只需在 ByteArrayOutputStream 上写入数据。若未抛出任何异常,测试即通过。如果您愿意,还可测试一些已写入的输出。例如,清单 1 所示代码片段用于测试 Jaxen 的 BaseXPath 类是否可串行化:


    清单 1. 此类是否可串行化?
      
    public void testIsSerializable() 
       throws JaxenException, IOException {
    
        BaseXPath path = new BaseXPath("//foo", new DocumentNavigator());
        ByteArrayOutputStream ōut = new ByteArrayOutputStream();
        ObjectOutputStream ōos = new ObjectOutputStream(out);
        oos.writeObject(path);
        oos.close();
        assertTrue(out.toByteArray().length > 0);
    
        }






    测试串行化形式

    接下来,您想要编写一个测试,不仅要验证输出得到了显示,还要验证输出是正确的。您可通过两种方式完成这一任务:

    • 反串行化对象,并将其与原始对象相比较。
    • 逐字节地将其与参考 .ser 文件相比较。

    我通常会从第一种选择入手,因为它还提供了一个反串行化的简单测试,而且编码和实现相对来说比较容易。例如,清单 2 所示代码片段将测试 Jaxen 的 SimpleVariableContext 类是否可写入并在之后重新读回:


    清单 2. 反串行化对象,并将其与原始对象相比较
      
    public void testRoundTripSerialization()
       throws IOException, ClassNotFoundException, UnresolvableException {
    
        // construct test object
        SimpleVariableContext ōriginal = new SimpleVariableContext();
        original.setVariableValue("s", "String Value");
        original.setVariableValue("x", new Double(3.1415292));
        original.setVariableValue("b", Boolean.TRUE);
    
        // serialize
        ByteArrayOutputStream ōut = new ByteArrayOutputStream();
        ObjectOutputStream ōos = new ObjectOutputStream(out);
        oos.writeObject(original);
        oos.close();
    
        //deserialize
        byte[] pickled = out.toByteArray();
        InputStream in = new ByteArrayInputStream(pickled);
        ObjectInputStream ōis = new ObjectInputStream(in);
        Object o = ois.readObject();
        SimpleVariableContext copy = (SimpleVariableContext) o;
    
        // test the result
        assertEquals("String Value", copy.getVariableValue("", "", "s"));
        assertEquals(Double.valueOf(3.1415292), copy.getVariableValue("", "", "x"));
        assertEquals(Boolean.TRUE, copy.getVariableValue("", "", "b"));
        assertEquals("", "");
    
      }

    让我们再试一次……

    在测试代码基础中那些此前从未测试过的部分时,几乎总是会发现 bug,对象串行化也是这样。在我第一次运行清单 2 中的测试时,测试失败了,输出结果如清单 3 所示:


    清单 3. 不可串行化
     
    java.io.NotSerializableException:
    org.jaxen.QualifiedName
                 at
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1075)
                 at
    java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
                 at java.util.HashMap.writeObject(HashMap.java:984)
                 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                 at
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    
                 at
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    
                 at java.lang.reflect.Method.invoke(Method.java:585)
                 at
    java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:890)
                 at
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1333)
                 at
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)
    
                 at
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
                 at
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1369)
                 at
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1341)
                 at
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)
    
                 at
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)
                 at
    java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
                 at
    org.jaxen.test.SimpleVariableContextTest.testRoundTripSerialization
      (SimpleVariableContextTest.java:90)
    

    这表明,SimpleVariableContext 包含一个对 QualifiedName 对象的引用,QualifiedName 类未标记为 Serializable。我为 QualifiedName 的类签名添加了 implements Serializable,这一次测试顺利通过。

    注意,此测试实际上并未验证串行化格式是否正确 —— 只是验证出对象能够来回转换。为测试正确性,您需要生成一些参考文件,以便与类的所有未来版本的输出相比较。





    测试反串行化

    通常,您不能依赖默认串行化格式来保持类的不同版本间的文件格式兼容性。您必须使用 serialPersistentFieldsreadObject()writeObject() 方法和/或 transient 修饰符,通过各种方式进行定制。如果您确实对类的串行化格式做出了不兼容的更改,应相应更改 serialVersionUID 字段,以指出您这样做了。

    正常情况下,您不会过分关注串行化对象的详细结构。而只是关注最初使用的那种格式随着类的发展得到了维护。一旦类基本上具备了恰当的形式,即可写入一些类的串行化实例,并存储在随后可将其作为参考使用的位置处。(您很可能确实希望多多少少地考虑如何串行化才能确保足够的灵活性,以便应对未来的发展。)

    编写串行化实例的程序是临时代码,只需使用一次。实际上,您根本就不应该多次运行这段代码,因为您不希望获得串行化格式中的任何意外更改。例如,清单 4 展示了用于串行化 Jaxen 的 SimpleVariableContext 类的程序:


    清单 4. 写入串行化实例的程序
    import org.jaxen.*;
    import java.io.*;
    
    public class MakeSerFiles {
    
      public static void main(String[] args) throws IOException {
    
        OutputStream fout = new FileOutputStream("xml/simplevariablecontext.ser");
        ObjectOutputStream ōut = new ObjectOutputStream(fout);
    
        SimpleVariableContext context = new SimpleVariableContext();
        context.setVariableValue("s", "String Value");
        context.setVariableValue("x", new Double(3.1415292));
        context.setVariableValue("b", Boolean.TRUE);
    
        out.writeObject(context);
        out.flush();
        out.close();
    
      }
    
    }

    您只需将一个串行化对象写入文件 —— 而且只需一次。这是您希望保存的文件,而不是用于写入的代码。清单 5 展示了 Jaxen 的 SimpleVariableContext 类的兼容性测试:


    清单 5. 确保文件格式未被更改
      
    public void testSerializationFormatHasNotChanged()
       throws IOException, ClassNotFoundException, UnresolvableException {
    
        //deserialize
        InputStream in = new FileInputStream("xml/simplevariablecontext.ser");
        ObjectInputStream ōis = new ObjectInputStream(in);
        Object o = ois.readObject();
        SimpleVariableContext context = (SimpleVariableContext) o;
    
        // test the result
        assertEquals("String Value", context.getVariableValue("", "", "s"));
        assertEquals(Double.valueOf(3.1415292), context.getVariableValue("",
    "", "x"));
        assertEquals(Boolean.TRUE, context.getVariableValue("", "", "b"));
        assertEquals("", "");
    
      }







    测试不可串行性

    默认情况下,类通常是可串行化的。例如,java.lang.Throwablejava.awt.Component 的任何子类都会从其祖先继承可串行性。在某些情况下,这也是您希望的结果,但并非总是如此。有的时候,串行化可能会成为安全漏洞,使恶意程序员能够在不调用构造函数或 setter 方法的情况下创建对象,从而规避了您小心翼翼地在类中构建的所有约束性检查。

    若您希望类可串行化,就需要测试它,这与您需要测试一个直接实现了 Serializable 的类相同。如果您不希望类可串行化,则应重写 writeObject()readObject(),使两者均抛出 NotSerializableException,随后您也需要对其进行测试。

    此类测试的实现方法与其他任何 JUnit 异常测试相似。只需在应抛出异常的语句两端包围一个 try 块即可,随后紧接欲抛出异常的语句之后添加一条 fail() 语句。如果愿意,您还可在 catch 中作出一些关于所抛出异常的断言。例如,清单 6 验证了 FunctionContext 是不可串行化的:


    清单 6. 测试 FunctionContext 是不可串行化的
      
    public void testSerializeFunctionContext() 
       throws JaxenException, IOException {
    
        DOMXPath xpath = new DOMXPath("/root/child");
        FunctionContext context = xpath.getFunctionContext();
        ByteArrayOutputStream ōut = new ByteArrayOutputStream();
        ObjectOutputStream ōout = new ObjectOutputStream(out);
        try {
            oout.writeObject(context);
            fail("serialized function context");
        }
        catch (NotSerializableException ex) {
            assertNotNull(ex.getMessage());
        }
    
      }

    Java 5 和 JUnit 4 使异常测试更为轻松。只需在 @Test 注释中声明所需异常即可,如清单 7 所示:


    清单 7. 带有注释的异常测试
    @Test(expected=NotSerializableException.class) public
    void testSerializeFunctionContext()
      throws JaxenException, IOException {
    
        DOMXPath xpath = new DOMXPath("/root/child");
        FunctionContext context = xpath.getFunctionContext();
        ByteArrayOutputStream ōut = new ByteArrayOutputStream();
        ObjectOutputStream ōout = new ObjectOutputStream(out);
        oout.writeObject(context);
    
      }







    结束语

    串行化格式可以说是代码基础中最脆弱、健壮性最差的部分。有的时候,似乎只要以奇异的眼神盯着它,它就会被破坏。单元测试和测试驱动的开发这些出色的工具使您可以信心十足地管理此类脆弱系统 —— 但只有在您确实使用了这些工具时,它们才能发挥作用。

    若您关注对象串行化,特别是希望为长期持久性存储使用串行化对象时,就必须对串行化进行测试。不要假设您的 Java 代码所做的一切都是正确的 —— 它很可能会出错!如果您将串行化测试作为测试套件的固定部分,则维护长期兼容性就会更轻松。您花费在对象串行化单元测试上的时间将为您带来成倍的回报,此后调试时您能节省的时间将数倍于投入时间。



    参考资料

    学习
    • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

    • 利用 Ant 和 JUnit 进行增量开发”(Malcolm Davis,developerWorks,2000 年 11 月):介绍 Java 平台上的单元测试。

    • 揭开极端编程的神秘面纱: 测试驱动的编程”(Roy Miller,developerWorks,2003 年 4 月):介绍关于测试驱动编程的一切,更重要的是 —— 测试驱动编程与什么无关。

    • Keeping critters out of your code”(David Carew,Sandeep Desai,Anthony Young-Garner,developerWorks,2003 年 6 月):介绍服务器端应用服务器环境的单元测试。

    • JUnit 4 抢先看”(Elliotte Rusty Harold,developerWorks,2005 年 9 月):介绍 JUnit 4 中基于注释的全新架构,需要 Java 5 或更新版本。

    • Java I/O,第 2 版(Elliotte Rusty Harold;O'Reilly,2006 年 5 月):深入讨论对象串行化的新版图书。

    • Pragmatic Unit Testing(Dave Thomas 和 Andy Hunt;Pragmatic Programmer,2003 年 9 月):单元测试 Java 代码的完整介绍。

    • Java 技术专区:数百篇关于 Java 编程各个方面的文章。

    获得产品和技术
    • JUnit:影响您的测试。


    讨论


    关于作者

    Elliotte Rusty Harold 来自新奥尔良, 现在他还定期回老家喝一碗美味的秋葵汤。不过目前,他和妻子 Beth 定居在纽约临近布鲁克林的 Prospect Heights,同住的还有他的猫咪 Charm(取自夸克)和 Marjorie(取自他岳母的名字)。他是 Polytechnic 大学计算机科学系的一名副教授,讲授 Java 和面向对象编程。他的 Cafe au Lait Web 站点已经成为 Internet 上最流行的独立 Java 站点之一,它的姊妹站点 Cafe con Leche 是最流行的 XML 站点之一。他编写的图书包括 Effective XMLProcessing XML with JavaJava Network ProgrammingJava I/O。目前,他在从事处理 XML 的 XOM API、Jaxen XPath 引擎和 Jester 测试覆盖工具的开发工作。

  • 模糊测试

    2007-08-30 10:58:56

    Elliotte Harold (elharo@metalab.unc.edu), 副教授, Polytechnic 大学

    2006 年 11 月 02 日

    模糊测试(Fuzz testing )是一项对代码质量有着深远影响的简单技术。在本文中,Elliotte Rusty Harold 故意将随机的坏数据插入应用程序,以观察发生的结果。他也解释了如何使用如校验和、XML 数据存储及代码验证等防护性编码技术,来加固您的程序以抵制随机数据。他以一个练习进行总结,在练习中他以一个代码破坏者的角度进行思考 —— 这是一种用于防护代码的至关重要的技术。

    多年来,我惊叹于有如此大量能够使 Microsoft Word 崩溃的坏文件。少数字节错位,会使整个应用程序毁于一旦。在旧式的、无内存保护的操作系统中,整个计算机通常就这样宕掉了。Word 为什么不能意识到它接收到了坏的数据,并发出一条错误信息呢?为什么它会仅仅因为少数字节被损坏就破坏自己的栈、堆呢?当然,Word 并不是惟一一个面对畸形文件时表现得如此糟糕的程序。

    本文介绍了一种试图避免这种灾难的技术。在模糊测试中,用随机坏数据(也称做 fuzz)攻击一个程序,然后等着观察哪里遭到了破坏。模糊测试的技巧在于,它是不符合逻辑的:自动模糊测试不去猜测哪个数据会导致破坏(就像人工测试员那样),而是将尽可能多的杂乱数据投入程序中。由这个测试验证过的失败模式通常对程序员来说是个彻底的震憾,因为任何按逻辑思考的人都不会想到这种失败。

    模糊测试是一项简单的技术,但它却能揭示出程序中的重要 bug。它能够验证出现实世界中的错误模式并在您的软件发货前对潜在的应当被堵塞的攻击渠道进行提示。

    模糊测试如何运行

    模糊测试的实现是一个非常简单的过程:

    1. 准备一份插入程序中的正确的文件。
    2. 用随机数据替换该文件的某些部分。
    3. 用程序打开文件。
    4. 观察破坏了什么。

    可以用任意多种方式改变该随机数据。例如,可以将整个文件打乱,而不是仅替换其中的一部分,也可以将该文件限制为 ASCII 文本或非零字节。不管用什么方式进行分割,关键是将大量随机数据放入应用程序并观察出故障的是什么。

    测试基于 C 的应用程序
    当字符串包含额外的零时,许多用 C 编写的程序都会出问题 —— 这类问题太过频繁以至于额外的零能够彻底隐藏代码中其他的问题。一旦验证出程序存在零字节问题,就可以移除它们,从而让其他的问题浮现出来。

    可以手动进行初始化测试,但要想达到最佳的效果则确实需要采用自动化模糊测试。在这种情况下,当面临破坏输入时首先需要为应用程序定义适当的错误行为。(如果当输入数据被破坏时,您发现程序正常运行,且未定义发生的事件,那么这就是第一个 bug。)随后将随机数据传递到程序中直到找到了一个文件,该文件不会触发适当的错误对话框、消息、异常,等等。存储并记录该文件,这样就能在稍后重现该问题。如此重复。

    尽管模糊测试通常需要一些手动编码,但还有一些工具能提供帮助。例如,清单 1 显示了一个简单的 Java™ 类,该类随机更改文件的特定长度。我常愿意在开始的几个字节后面启动模糊测试,因为程序似乎更可能注意到早期的错误而不是后面的错误。(您的目的是想找到程序未检测到的错误,而不是寻找已经检测到的。)


    清单 1. 用随机数据替换文件部分的类
    import java.io.*;
    import java.security.SecureRandom;
    import java.util.Random;
    
    public class Fuzzer {
    
         private Random random = new SecureRandom();
         private int count = 1;
    
         public File fuzz(File in, int start, int length) throws IOException  
    {
    
             byte[] data = new byte[(int) in.length()];
             DataInputStream din = new DataInputStream(new FileInputStream(in));
             din.readFully(data);
             fuzz(data, start, length);
             String name = "fuzz_" + count + "_" + in.getName();
             File fout = new File(name);
             FileOutputStream  ōut = new FileOutputStream(fout);
             out.write(data);
             out.close();
             din.close();
             count++;
             return fout;
         }
    
    
         // Modifies byte array in place
         public void fuzz(byte[] in, int start, int length) {
    
             byte[] fuzz = new byte[length];
             random.nextBytes(fuzz);
             System.arraycopy(fuzz, 0, in, start, fuzz.length);
    
         }
    
    }

    关于代码
    我可以用很多种方式优化 清单 1 中的代码。例如,有着 java.nio 的内存映射文件是一个相当不错的选择。我也能够改进这个错误处理及可配置性。因为不想让这些细节混淆这里所要说明的观点,所以我将代码保持了原样。

    模糊测试文件很简单。将其传至应用程序通常不那么困难。如 Applescrīpt 或 Perl 脚本语言通常是编写模糊测试的最佳选择。对于 GUI 程序,最困难的部分是辨认出应用程序是否检测出正确的故障模式。有时,最简单的方法是让一个人坐在程序前将每一个测试通过或失败的结果都标记下来。一定要将所有生成的随机测试用例单独地命名并保存下来,这样就能够重现这个过程中检测到的任何故障。

    防护性编码

    可靠的编码遵循了这样的基本原则:绝不会让程序中插入未经过一致性及合理性验证的外部数据。

    如果从文件中读入一个数字并期望其为正数,那么,在使用其进行进一步处理前对其先验证一下。如果期望字符串只包含 ASCII 字母,请确定它确实是这样。如果认为文件包含一个四字节的整数倍的数据,请验证一下。一定不要假设任何外部提供的数据中的字符都会如您所料。

    最常见的错误是做出这样的假设:因为程序将该数据写出,该程序就能不用验证再一次将该数据读回去。这是很危险的!因为该数据很可能已经被另一个程序在磁盘上复写过了。它也可能已经被一个故障磁盘或坏的网络传输所破坏了或已经被另一个带 bug 的程序更改过了。它甚至可能已经被故意更改过以破坏程序的安全性。所以不要假设任何事,要进行验证。

    当然,错误处理及验证十分令人生厌,也很不方便,并被全世界程序员们所轻视。计算机的诞生已进入了六十个年头,我们仍旧没有检查基本的东西,如成功打开一个文件及内存分配是否成功。让程序员们在阅读一个文件时测试每一个字节和每一个不变量似乎是无望的 —— 但不这样做就会使程序易被模糊攻击。幸运的是,可以寻求帮助。恰当使用现代工具和技术能够显著减轻加固应用程序的痛苦,特别是如下三种技术更为突出:

    • 校验和
    • 基于语法的格式,如 XML
    • 验证过的代码如 Java

    用校验和进行的模糊试验

    能够保护程序抵御模糊攻击的最简单的方法是将一个检验和添加到数据中。例如,可以将文件中所有的字节都累加起来,然后取其除以 256 的余数。将得到的值存储到文件尾部的一个额外字节中。然后,在输入数据前,先验证检验和是否匹配。这项简单模式将未被发现的意外故障的风险降低到约 1/256 。

    健壮的校验和算法如 MD5 和 SHA 并不仅仅取其除以 256 的余数,它完成的要多得多。在 Java 语言中,java.security.DigestInputStreamjava.security.DigestOutputStream 类为将一个校验和附属到数据中提供了便捷的方式。使用这些校验和算法中的一种可以将程序遭受意外破坏的机率降低到少于十亿分之一(尽管故意攻击仍有可能)。

    XML 存储及验证

    将数据以 XML 形式存储是一种避免数据损坏的好方法。XML 最初即着力于 Web 页面、书籍、诗歌、文章及相似文档,它几乎在每个领域都获取了巨大的成功,从金融数据到矢量图形到序列化对象等等。

    不切实际的限定
    如果真想要破坏一个 XML 解析器,有几种方法可以试试。例如,大多数 XML 解析器服从于特定的最大尺寸。如果一个元素名长度超过 22 亿字符(Java String 的最大尺寸),SAX 解析器将会失败。尽管如此,在实践中这些极限值如此之高,以至于在达到之前内存就已经耗尽。

    使 XML 格式抵制模糊攻击的关键特征是一个对输入不做任何 假设的解析器。这就是真正想在一个健壮的文件格式中所获得的。设计 XML 解析器是为了让任何输入(格式良好的或无格式的,有效的或无效的)都以定义好的形式处理。XML 解析器能够处理任何 字节流。如果数据首先通过了 XML 解析器,则仅需要准备好接受解析器所能提供的东西。例如,不需要检查数据是否包含空字符,因为 XML 解析器绝不会传送一个空值。如果 XML 解析器在其输入中看到一个空字符,它就会发出异常并停止处理。当然还需要处理这个异常,但编写一个 catch 块来处理检测到的错误比起编写代码来检测所有可能的错误来说要简单得多。

    为使程序更加安全,可以用 DTD 和/或模式来验证文档。这不仅检查了 XML 是否格式良好,而且至少与所预期更加接近。验证并不会告知关于文档所需了解的一切,但它却使编写大量简单检查变得很简单。用 XML,很明显能够将所接受的文档严格地限定为能够处理的格式。

    尽管如此,还有多段代码不能用 DTD 或模式进行验证。例如,不能测试发票上商品的价格是否和数据库中库存商品的价格一致。当从客户接收到一份包含价格的订单文档时,不论其是 XML 格式或是其他格式,在提交前通常都会检查一下,以确保客户并未修改价格。可以用定制代码实现这些最后的检查。

    基于语法的格式

    使 XML 能够对模糊攻击具有如此的抵御能力的是其使用巴科斯-诺尔范式(Backus-Naur Form,BNF)语法仔细且标准地定义的格式。许多解析器都是使用如 JavaCC 或 Bison 等解析器-生成器工具直接从此语法中构建的。这种工具的实质是阅读一个任意的输入流并确定其是否符合此语法。

    如果 XML 并不适合于您的文件格式,您仍可以从基于解析器的解决方案的健壮性中获益。您必须为文件格式自行编写语法,随后开发自己的解析器来阅读它。相比使用唾手可得的 XML 解析器,开发自己的解析器需要更多的工作。然而它是一个更为健壮的解决方案,而不是不根据语法正式地进行验证就将数据简单地装载到内存中。

    Java 代码验证

    由模糊测试导致的许多故障都是内存分配错误及缓冲器溢出的结果。用一种安全的垃圾收集语言(在如 Java 或 managed C# 等虚拟机上执行的)来编写应用程序避免了许多潜在问题。即使用 C 或 C++ 来编写代码,还是需要使用一个可靠的垃圾收集库。在 2006 年,台式机程序员或服务器程序员不应该还需要管理内存。

    Java 运行时对其自身的代码起到了额外保护层的作用。在将一个 .class 文件装载到虚拟机之前,该文件要由一个字节符验证器或一个可选的 SecurityManager 进行验证。Java 并不假设创建 .class 文件的编译器没有 bug 且运转正常。设计 Java 语言之初就是为了允许在一个安全沙箱中运行不信任的、潜在恶意的代码。它甚至不信任其自身编译过的代码。毕竟,也许有人已经用十六进制编辑器手工修改了字节符,试图触发缓冲器溢出。我们大家都应该对我们的程序也有对输入这样的偏执。





    回页首


    以敌人的角度思考

    之前介绍的每项技术都在阻止意外破坏方面造诣颇深。将它们综合起来恰当地实现,会将未被发现的非蓄意破坏发生的可能性几乎减少到零。(当然,并不会减少到零,但其发生的可能性就如同一束偏离轨道的宇宙射线将您 CPU 运算 1+1 的结果变为 3 的可能性一样微乎其微。)但不是所有的数据损坏都是非蓄意的。如果有人故意引入坏数据来破坏程序的安全性又该如何呢?以一个攻击者的角度进行思考是防护代码的下一个步骤。

    转回到一个攻击者的角度进行思考,假设要攻击的应用程序是用 Java 编程语言编写的、使用非本地代码且将所有额外数据都以 XML(在接受前经过彻底验证)形式存储,还能成功攻击吗?是的,能。但用随机改变文件字节的低级方法显然不行。需要一种更为复杂的方法来说明程序自身的错误检测机制及路径。

    当测试一个抵御模糊攻击的应用程序时,不可能做纯黑盒测试,但通过一些明显的修改,基本的想法还是可以应用的。例如,考虑校验和,如果文件格式包含一个校验和,在将文件传至应用程序前仅仅修改此校验和就可以使其同随机数据相匹配。

    对于 XML,试着模糊单独的元素内容和属性值,而不是从文档中挑选一部分随机的字节进行替换。一定要用合法的 XML 字符替换数据,而不要用随机字节,因为即使一百字节的随机数据也一定是畸形的。也可以改变元素名称和属性名称,只要细心地确保得到的文档格式仍是正确的就可以了。如果该 XML 文档是由一个限制非常严格的模式进行检查的,还需要计算出该模式没有 检查什么,以决定在哪里进行有效的模糊。

    一个结合了对剩余数据进行代码级验证的真正严格的模式也许不会留下可操纵的空间。这就是作为一个开发人员所需要追求的。应用程序应能够处理所发送的任何有意义的字节流,而不会因权利上( de jure ) 无效而拒绝。





    回页首


    结束语

    模糊测试能够说明 bug 在程序中的出现。并不证明不存在这样的 bug。而且,通过模糊测试会极大地提高您对应用程序的健壮性及抵御意外输入的安全性的自信心。如果您用 24 小时对程序进行模糊测试而其依然无事,那么随后同种类型的攻击就不大可能再危及到它。(并不是不可能,提醒您,只是可能性很小。)如果模糊测试揭示出程序中的 bug,就应该进行修正,而不是当 bug 随机出现时再对付它们。模糊测试通过明智地使用校验和、XML、垃圾收集和/或基于语法的文件格式,更有效地从根本上加固了文件格式。

    模糊测试是一项用于验证程序中真实错误的重要工具,也是所有意识到安全性问题且着力于程序健壮性的程序员们的工具箱中所必备的工具。



    参考资料

    学习

    获得产品和技术

    讨论
    • 改进代码质量论坛:作为专注于改进代码质量的顾问,Andrew Glover 将自己的许多专业意见都带到了这个他主持的讨论组中。


    关于作者

    Elliot Rusty Harold 照片

    Elliotte Rusty Harold 来自新奥尔良, 现在他还定期回老家喝一碗美味的秋葵汤。不过目前,他和妻子 Beth 定居在纽约临近布鲁克林的 Prospect Heights,同住的还有他的猫咪 Charm(取自夸克)和 Marjorie(取自他岳母的名字)。他是 Polytechnic 大学计算机科学的副教授,他在该校讲授 Java 和面向对象编程。他的 Web 站点 Cafe au Lait 已经成为 Internet 上最流行的独立 Java 站点之一,它的姊妹站点 Cafe con Leche 已经成为最流行的 XML 站点之一。他的书包括 Effective XML Processing XML with Java Java Network ProgrammingThe XML 1.1 Bible。他目前在从事处理 XML 的 XOM API、Jaxen XPath 引擎和 Jester 测试覆盖率工具的开发工作。

  • 成功的 Web 应用系统性能测试

    2007-08-30 10:53:37

    杨敏强 (myang@cn.ibm.com), 软件工程师, IBM

    2007 年 6 月 26 日

     

    性能测试是 Web 应用系统的一项重要质量保证措施。在现实中,很多 Web 性能测试项目由于性能测试需求定义不合理或不明确,导致性能测试项目不能达到预期目标或进度超期。本文针对 Web 应用系统的技术架构和系统使用特点,探讨如何有效实施性能测试过程,并重点介绍如何分析获得合理的性能测试需求,最终对 Web 应用系统性能进行科学、准确的评估。

    1 引言

    基于Web服务器的应用系统由于提供浏览器界面而无须安装,大大降低了系统部署和升级成本,得以普遍应用。目前,很多企业的核心业务系统均是Web应用,但当Web应用的数据量和访问用户量日益增加,系统不得不面临性能和可靠性方面的挑战。因此,无论是Web应用系统的开发商或最终用户,都要求在上线前对系统进行性能,科学评价系统的性能,从而降低系统上线后的性能风险。

    在很多性能测试项目中,由于不能合理定义系统的性能测试需求,不能建立和真实环境相符的负载模型,不能科学分析性能测试结果,导致性能测试项目持续时间很长或不能真正评价系统性能并提出性能改进措施。

    本文在总结许多Web应用系统性能测试实践经验和教训的基础上,从与性能测试工具无关的角度介绍Web应用系统性能测试的方法和实施过程,以及如何定义合理的性能测试需求。

    1.1 术语定义

    性能测试:通过模拟大量浏览器客户端同时访问Web服务器,获得系统的性能数据。

    虚拟用户:模拟浏览器向Web服务器发送请求并接收响应的一个进程或线程。

    响应时间:浏览器向Web服务器提交一个请求到收到响应之间的间隔时间。

    思考时间:浏览器在收到响应后到提交下一个请求之间的间隔时间。

    请求成功率:Web服务器正确处理的请求数量和接收到的请求数量的比。

    吞吐量:单位时间内Web服务器成功处理的HTTP页面或HTTP请求数量。

    在线用户:用户通过浏览器访问登录Web应用系统后,并不退出该应用系统。通常一个Web应用服务器的在线用户对应Web应用服务器的一个Session。

    并发用户数:Web服务器在一段时间内为处理浏览器请求而建立的HTTP连接数或生成的处理线程数。当所有在线用户发送HTTP请求的思考时间为零时,Web服务器的并发用户数等于在线用户数。

    1.2 Web应用系统技术架构

    Web应用系统的前端为浏览器,后台为Web服务器(如Apache,Microsoft Internet Information Server),浏览器和Web服务器之间的交互基于HTTP协议。HTTP协议本身是无连接的,Web服务器通过Session机制来建立一个浏览器所发出的先后连接之间的关联。通过实验证明,当浏览器客户端在首次访问Web服务器后,如果该浏览器客户端不发送后续请求,服务器维持该浏览器客户端的Session变量所消耗的系统资源非常小。

    2 Web应用系统性能测试过程

    标准的Web应用系统性能测试过程包括确定性能测试需求,开发性能测试脚本,定义性能测试负载模型,执行性能测试和形成性能测试报告。本章将分别介绍上述过程,并通过举例说明如何完成每一环节。

    2.1 确定性能测试需求

    科学定义Web应用系统性能测试需求对一个成功的性能测试非常重要。通常,Web应用系统的性能测试需求有如下两种描述方法。

    2.1.1 基于在线用户的性能测试需求

    该需求描述方法主要基于Web应用系统的在线用户和响应时间来度量系统性能。当Web应用系统在上线后所支持的在线用户数以及操作习惯(包括操作和请求之间的延迟)很容易获得,如企业的内部应用系统, 通常采用基于在线用户的方式来描述性能测试需求。以提供网上购物的Web应用系统为例,基于在线用户的性能测试需求可描述为:10个在线用户按正常操作速度访问网上购物系统的下定单功能,下定单交易的成功率是100%,而且90%的下定单请求响应时间不大于8秒;当90%的请求响应时间不大于用户的最大容忍时间20秒时,系统能支持50个在线用户

    2.1.2 基于吞吐量的性能测试需求

    该需求描述方法主要基于Web应用系统的吞吐量和响应时间来度量系统性能。当Web应用在上线后所支持的在线用户无法确定,如基于Internet的网上购物系统,可通过每天下定单的业务量直接计算其吞吐量,从而采取基于吞吐量的方式来描述性能测试需求。以网上购物系统为例,基于吞吐量的性能测试需求可描述为:网上购物系统在每分钟内需处理10笔下定单操作,交易成功率为100%,而且90%的请求响应时间不大于8秒

    2.2 开发性能测试脚本

    在确定Web应用系统性能测试需求后,就要根据性能测试需求中确定的功能开发性能测试脚本。比如,针对前面定义的网上购物系统的性能测试需求,将开发下定单功能的性能测试脚本。

    性能测试脚本是描述单个浏览器向Web服务器发送的HTTP请求序列。每个性能测试工具(如IBM Rational Performance Tester, LoadRunner)所提供的测试脚本语法是不同的。测试人员利用性能测试工具可从头手工编写测试脚本,也可以通过录制浏览器和Web服务器之间的网络通信数据而自动形成测试脚本。

    任何性能测试工具都不能保证录制形成的性能测试脚本的正确性,测试人员应通过在单用户下运行性能测试脚本对其正确性进行验证。测试脚本不正确的一个重要原因就是脚本的数据关联不正确,也就是并没完全建立一个测试请求和前面的响应内容之间的关联。测试脚本HTTP请求和响应之间的数据关联是否正确的一个重要标准是单用户运行脚本,脚本能完成期望的功能。

    在完成性能测试脚本的数据关联后,需要对脚本进行参数化,也就是把脚本中的某些请求数据替换成变量,变量的值来于一个独立的数据文件,从而保证在多虚拟用户运行脚本的情况下,每个虚拟用户所提交的数据是不同的。

    此外,为了测试Web应用的可靠性,还需要对请求所收到的响应进行验证(比如验证响应的HTTP返回码或验证响应的内容),便于性能测试完成后统计请求成功率。

    2.3 建立性能测试负载模型

    性能测试负载模型定义了测试工具如何向Web应用系统提交请求,包括向Web应用系统发送请求的虚拟用户数,每个虚拟用户发送请求的速度和频率。针对前面介绍的网上购物系统的性能测试需求,在性能测试工具中定义的性能测试负载模型应包括如下信息:

    虚拟用户数:性能测试不仅仅是执行一次,而且每次执行时虚拟用户数也不固定,因此在性能测试负载模型中定义的虚拟用户数将在测试执行时进行设置。

    虚拟用户发送请求的思考时间和迭代次数:虚拟用户发送请求的思考时间长短是决定Web应用系统负载量的重要因素之一,而迭代次数将决定性能测试的执行持续时间。对基于在线用户的性能测试需求,将基于录制脚本时记录的思考时间,而且由于现实中不同用户访问系统的思考时间不同,可把思考时间设置为在一定范围内的随机值。对于基于吞吐量的性能测试需求,将把思考时间设置为零,此时Web应用系统的在线用户数量将等于并发用户数。同时,为了避免性能测试压力的随机性,将增加请求的迭代次数来增加测试执行持续时间,从而获得系统在稳定压力下的性能数据。

    虚拟用户启动模式:在现实中,Web应用系统的用户不太可能同时做相同的操作,因此为了让Web应用系统所承担的压力随时间均匀分布,建议虚拟用户依次启动,同时也避免大量用户同时登录造成系统阻塞。以10个虚拟用户模拟下定单为例,可设置每个虚拟用户间隔30秒启动,这样10个虚拟用户可在5分钟后完成启动,并保证10个虚拟用户不会在同一时刻下定单,从而更符合实际情况。

    2.4 执行性能测试

    执行性能测试是指通过多次运行性能测试负载模型,获得系统的性能数据。在执行过程中,需利用测试工具、操作系统、系统软件(如Web Server或DB Server)提供的资源监控手段对资源进行监控和分析,帮助发现资源瓶颈,并在系统层面进行优化。同时,还需对应用进行性能分析,帮助定位应用代码中的性能问题,切实解决系统的性能问题。

    2.5 形成性能测试报告

    性能测试项目的最后阶段就是向相关人员提交性能测试报告,汇报性能测试结果。在向相关人员汇报性能测试结果时,并不是性能测试报告越丰富、性能数据越多越好。好的性能测试报告是能准确、简单地传递性能测试结论,而不需太多的技术细节。

    针对基于在线用户数的性能测试需求,可通过下图总结性能测试结论。其中横轴是在线用户数,纵轴是响应时间,如40在线用户访问网上购物系统时,90%的下定单请求响应时间不超过10秒。


    图一:在线用户数和响应时间时间的趋势图
    在线用户数和响应时间时间的趋势图

    针对基于吞吐量的性能测试需求,可通过下图的曲线来描述性能测试结果。以网上购物系统为例,下图描述下定单的并发用户、下定单响应时间以及吞吐量(服务器每秒处理定单笔数)之间的关系,从而快速判断系统是否能满足性能测试需求。从下图中可看出,并发用户增加,请求的响应时间也增加。服务器的吞吐量是先随并发用户数增加而增加,当吞吐量到达一定峰值后,再增加并发用户数,吞吐量会减少。原因在于当并发用户数少时,向Web服务器提交的请求量不大,服务器处理能力还有富余,所以吞吐量逐步增大;但当并发用户数超过某一值时,由于向服务器提交的请求太多,造成服务器阻塞,反而导致吞吐量减少。


    图二:响应时间、吞吐量和并发用户数的趋势图
    响应时间、吞吐量和并发用户数的趋势图

    3 如何获取合理的性能测试需求

    前一章介绍了Web应用系统的性能测试过程,确定性能测试需求是整个性能测试的起点和成功的重要因素。性能测试需求定义得过高,虽然确保系统上线后能满足性能需求,但可能会造成硬件资源的浪费;性能测试需求定义得过低,系统上线后可能会出现性能问题。如何通过分析系统上线后可能的用户访问行为,来获得合理的性能测试需求指标呢?

    假设现有一个基于Web的办公自动化系统(简称OA系统),该系统提供公文收发和查询功能。在部署该系统前,将对该系统进行性能测试。下面将详细介绍如何分析该OA系统的使用情况,定义合理的性能测试需求。

    3.1 如何获得OA系统的在线用户数量

    在线用户数量是指在特定时间区间内,有多少用户访问Web应用系统(对应到Web服务器的Session数),根据系统可能访问用户数以及每个用户访问系统的时间长短来确定。

    对于将要部署的OA系统,通过分析获得该系统有8000个注册用户,基本上所有的用户每天(8小时工作时间)都会访问OA系统,平均在线时间(从登录OA系统到退出OA系统之间的时间间隔,也可以是多次在线时间的合计)为12分钟,那么该OA系统的平均在线数(也就是Web应用Session变量数)为200个(8000 * 0.2 / 8),假设峰值在线用户数是平均在线用户数的3倍(该倍数可根据实际情况调整),则性能测试需求的在线用户数为600。

    3.2 如何确定OA系统的性能测试用例

    由于时间和资源限制,不可能对Web应用系统的所有功能进行性能测试,而是从业务的角度(如某一功能操作的用户多)和技术的角度(如某一功能虽然访问用户不多,但内部处理逻辑复杂或处理数据量大)来选择Web应用系统的特定功能作为性能测试用例。

    以OA系统为例,由于所有用户都经常公文查询功能,因此确定的性能测试用例为公文查询。

    3.3 如何确定OA系统的响应时间

    响应时间的快慢直接影响了系统使用用户的满意度,采用平均响应时间来描述系统系统性能测试需求是不科学的,因为无法直接和客户的满意度挂钩。而且,在做性能测试,如果某一请求的响应时间过长或过短,将导致平均响应时间和实际情况偏离。

    以OA系统为例,定义的响应时间需求为:90%(该百分比和要求的系统用户满意度相关)的查询请求响应时间不超过8秒(该时间可根据实际情况确定)。

    3.4 如何确定OA系统的交易吞吐量

    单位时间内Web应用系统需处理多少笔特定的交易可通过统计获得。以OA系统为例,假设每个用户每天(一天按8小时计算)平均会查询公文4次,那OA应用的Web服务器平均每分钟要能处理8000 * 4 / ( 60 * 8 ) = 66.67笔查询公文交易,考虑到峰值因素,要求每分钟能处理66.7 * 3=200笔查询公文交易。

    3.5 OA系统性能测试需求描述

    通过前面的分析,能明确定义合理的性能测试需求。OA系统性能测试需求定义如下:

    基于在线用户数的性能测试需求:600个在线用户按正常操作速度访问OA系统的查询公文功能,所有查询请求的成功率是100%,而且90%的查询请求响应时间不大于8秒。

    基于吞吐量的性能测试需求:OA系统在每分钟内需处理200笔查询公文操作,交易成功率为100%,而且90%的请求响应时间不大于8秒。

    4 总结

    Web应用性能测试项目成功的关键不在于性能测试工具,而在于有效的性能测试分析方法和实践。只有切实掌握性能测试需求分析方法,性能测试实践经验,才能保证一个Web应用性能测试的成功。



    参考资料



    关于作者

    杨敏强,IBM Rational 软件工程师。

  • OA与CRM、ERP的关系和功能层次

    2007-08-30 10:42:30

    传统的ERP/CRM等管理软件多侧重于管理包括现金流、物流,建立一个刚性的管理系统,并且呈现出流程化、规范化的特征,而OA软件则转向管人、管事,后者称为“老板级的信息化”,如所示。

      



      现在企业发展变化快,不光是新产品推出快,整个组织结构也要快速变化适应新形势。但ERP很难做到这一点。ERP要求企业所有的流程都要为了适应它而重新规划重组,它要适应后台管理的变化真是无能为力,这却是OA的强项。

      OA使用户的管理及业务人员不再受办公室和网络的约束,从而实现一种移动办公、在家办公、远程办公等多种办公形式。另外,虽然坐在办公室内,管理的范围却并不局限于办公室,远在万里之外的分公司、办事处、其他城市的合作伙伴、经销商等,所有的沟通管理都可以突破办公室的边界。

      所以,上过ERP的厂家,会需要OA软件作为补充;一个企业想上信息化系统的时候,也可以选择先上OA软件,通过OA软件建造一个柔性系统,将来再逐步地去扩展刚性系统。

     功能层次

      不同的办公环境要求不同类型的办公自动化系统,如政府和企业的办公自动化类型就不同。总的来讲办公自动化系统的基本功能[3]有:

      事务处理功能

      事务处理功能是处理办公部门中大量的事务性工作,这种工作量大,重复性高。使用办公自动化系统来处理可以使办公人员从这些工作中解脱出来。事务型为基础层,包括文字处理、个人日程管理、行文管理、邮件处理、人事管理、资源管理,以及其他有关机关行政事务处理等等

      信息管理功能

      信息管理功能就是对信息的流通进行控制和管理,做好对信息的收集、加工、传递、交流、存取、分析、判断和反馈,从而使信息资源的利用获得良好的效益。管理型为中间层,它包含事务型,管理型系统是支持各种办公事务处理活动的办公系统与支持管理控制活动的管理信息系统相结合的办公系统。

      辅助决策功能

      辅助决策功能是指办公自动化系统要有决策或辅助决策功能,在对大量信息进行分析的基础之上分析制定出各种优化解决方案提供给决策者。决策型为最高层,它以事务型和管理型办公系统的大量数据为基础,同时又以其自有的决策模型为支持,决策层办公系统是上述系统的再结合,具有决策或辅助决策功能的最高级系统。

  • 网站和OA系统的建设

    2007-08-30 10:40:58

    21世纪是一个信息化时代。我国信息化事业步入了加速发展的快车道,大力推进国民经济和社会信息化已经成为覆盖现代化建设全局的战略举措。“政府上网工程” 的建设,在很大意义上转变政府职能、提高行政效率和加强监管能力,增强政府工作的科学性、协调性和民主性,全面提高依法行政管理能力。

    综合招投标中心是省级工程、货物、服务、产权、土地综合类招投标场所,主要职责是为招投标主体提供信息网络报务、技术咨询服务、场所服务和其他相关服务。信息化建设尤其重要。

    一、信息化建设的意义

    通过网上招投标信息服务和招投标过程的管理,可以节约大量人力、物力,建立良好的公正、公平、公开的竞争环境,有效杜绝腐败,降低采购成本。

    以信息化为支撑,积累大量资料和数据,为领导决策和日常办公管理提供信息服务,提高办公效率,减轻工作人员负担,节约办公费用。改变传统管理思路和模式,提高管理人员和工作人员素质,支持实现政府机关工作决策科学化。

    政府信息化是构建精简高效、规范廉洁政府的有效途径,是行政管理制度革命化和现代化的催化剂。政府信息化是一个用现代信息技术改造传统管理模式的过程,信息化的目标是形成新型政务管理模式,进而在此基础上全面推行电子政务,使政府行政管理的效率和水平大大提高。

    信息化工作的一个重要方面,是对现有管理方式和业务流程进行梳理、分析、优化和规范化,从而形成科学的新型政务管理模式。充分利用信息化技术和手段,建构更广泛、更精细、更敏捷、更人性化的政府管理机构。政府机关信息公开是建设和谐社会的新途径、新工具、新手段,实现政府与公众关系的进一步改善,不仅具有重大的社会和政治意义,而且具有无可比拟的使用价值。

    从全球经济一体化的角度来看,电子政务是顺应这种发展趋势的必然阶段,最终服务于经济建设,服务于招投标市场。除了提高政府的社会服务效率外,还将向社会提供行政管理中的副产品--社会信息资源。企业将是社会信息资源的重要消费者。

    二、网站和OA系统的建设

    建设好网络平台的指导思想是:使网络成为最具交互性的沟通渠道,围绕提供优质服务、提高办事效率和亲民利民便民的总体要求,支持招投标主体各方获得效益,支持管理机关实施有效地监督和管理,建设一个规范统一、公正廉洁的招投标市场,完善省级招投标管理体制。

    系统采用面向对象和模块化的设计思路,体现了实用性、先进性、亲和便捷、安全可靠,体现网上网下协同处理和长效管理的原则,系统运行稳定、功能完备,让“技术服务于业务”。以“用户为中心”,按照“以人为本”的思想,设计办公自动化系统的操作界面。以应用为关键,按照“技术服务于人”的宗旨,推进办公自动化系统的使用。

    面向信息共享的应用。针对网络用户不同的角色定义权限,实现信息的发布、反馈、查询、下载、统计、文件交互、即时通讯、流程控制等功能,充分支持用户提高工作效率,提高管理水平,增强政府机关对市场的监督、调控手段和能力。

    三、信息化建设的管理

    “三分技术,七分管理”这个在其他领域总结出来的实践经验和原则,在信息安全领域也同样适用。中央办公厅、国务院办公厅转发了《国家信息化领导小组关于加强信息安全保障工作的意见》(2003[27]号文件)。27号文件第一次把信息安全提到了促进经济发展、维护社会稳定、保障国家安全、加强精神文明建设的高度,并提出了“积极防御、综合防范”的信息安全管理方针。管理已成为信息安全保障能力的重要基础。

    信息化技术管理方面。网站和OA系统是计算机和通信技术与科学的管理思想完美结合的一种境界和理想。正是这种结合的逐步提升,使传统的办公方式得以改变。而且,通过OA系统改善管理思想和管理手段的实践过程是无止境的。

    我们在建的网站和OA系统采取三级安全体制:托管机房,网站服务器,局域网防火墙。六项措施:身份认证系统、防病毒系统、入侵检测系统、漏洞扫描系统、防火墙系统和数据备份与恢复系统。

    信息化行政管理方面。行政管理的思想应一直贯穿在信息网络安全管理系统的设计、实施、运行、操作、维护、创新和发展的各个方面。在网站和OA系统功能基本实现的基础上,通过调整、磨合工作流程,协调完善机关管理监督事务,运用行政管理手段使网络信息技术最大限度地为办公服务,发挥网络信息技术的最大效能。

    制定信息化建设的管理规定:《局域网网络及计算机硬件设备管理规定》;《局网站和OA系统信息发布及维护管理规定》;《局计算机用户终端操作及维护管理规定》

    采用灵活的培训方法,将集中培训和个别辅导结合起来。使用操作培训是推进办公自动化系统应用一个必须而重要的环节。

    四、发展规划

    信息化建设是一项综合性很强的工作,既富有开创性又具有挑战性,需要各方面、长时期坚持不懈的探索与创新。实施电子政务,降低行政成本,将其行政管理和公共服务等方面的工作转移到网上去完成,建立一个简洁、高效、透明、公开的政府运行模式,是我们追求的目标。正如温家宝总理在国家行政学院组织的省部级干部“电子政务研讨班”上所讲:“电子政务从根本上讲是为了提高行政效率,降低行政成本,改进政府工作,方便人民群众”。温家宝总理简洁、深刻、精辟的阐明了电子政务的根本目的、总的出发点和必须遵循的原则。

    以需求为出发点,按照“技术服务于政务”的原则,完善网站和OA系统的功能。这需要一定时间的信息积累,包括业务经验积累、数据资料积累、技术积累和管理经验的积累。在具备丰富信息积累和管理经验的基础上谋求大跨跃式发展和创新。

     一是内网外网合一。整合全部信息资源,在网上实现招投标各环节管理监督电子化操作控制,实现网上报建、审批、开标、评标、现场直播等功能。二是实现真正意义上的网上办公。通过CA认证和网络安全运行体制的建立,实现网上无纸化办公的管理和监督。三是大力推进国产计算机应用软件的应用。如:CEB是版式文件,CEB格式基于面向XML的双向转换技术,可以实现电子文档的“永远存活”状态。DRM(数字版权保护)技术,依靠先进严密的加密算法,将安全保障细致做到每个层面。DRM技术为文档安全保驾护航,电子文件安全性不再困扰信息主管。从浏览、转发、打印、打印份数、拷屏、保存等各个权限控制点做到严密防范、安全发布。在实现政府机关内部敏感文件,对外公布文件权威性保证方面,DRM可以做到:谁起草谁决定,谁发布谁决定,谁发文谁决定,谁收文谁决定,谁上网谁负责。

    从未来的信息化发展趋势看,以“资源”为核心的电子政务一体化建设将成为今后三年的建设热点;以“文件”为核心的协同业务支撑平台,包括公文处理、内容管理、知识管理、互联审批服务等建设将进入实质性应用阶段;以“数据”为中心的数据整合支撑平台,包括数据采集、处理、数据仓库、数据挖掘、在线分析、支持决策等将进入基础性建设阶段。

  • OA系统应用开发后的用户测试

    2007-08-30 10:39:51

    “OA系统建设普遍存在立项多、花钱多、鉴定会多,但真正受用户欢迎、有三年以上寿命的OA系统不多。我认为,在OA系统项目开发过程中,对用户测试重视不够、管理不力,是造成这种现象的基本原因之一。因此,OA系统成功应用的关键,在于最终是否满足了应用者的‘口味’,它是——”

      黄延岭:现为中国国际信息信托投资公司(简称中信公司)管理信息中心OA处处长,参加了中信公司的三代OA系统的建设工作。从事OA系统建设工作20多年,参加多项大型OA系统建设项目,如作为项目组长开发第一代中国新闻记者网,获得国家科技应用三等奖。在OA建设领域有丰富的实践经验和深刻的认识。

      OA系统项目无一不是源于管理改革的需求,有人说,建设OA系统可以做到“交钥匙工程”,我认为这只是一种市场炒作的说法。不同单位有不同的管理需求,必然决定了OA系统的个性化特性,不可能存在通用的OA系统产品,因而用户测试对OA系统项目实用化具有不可替代、不可跳越的关键性作用。

      

      开发与应用“对视”

      

      用户测试是处于系统测试阶段结束和系统试运行阶段开始之前的一个相对独立的阶段。测试的主体,由开发技术人员转为最终应用者。用户通过对OA系统全部功能和工作流程的亲手应用、测试,逐步全面了解OA系统是否完全实现了需求书的要求,从而接受和认可该软件,这是保证OA系统功能和流程正确性、完整性和实用性的关键。实践证明,只有用户试用,才能提出合理建议,促使软件实用化和产品化。因此我们把用户测试看作开发工作的继续,是用户技能培训的过程,是系统试运行所需要的设备、技术、组织和制度的准备过程,也是甲方、乙方和用户方相互理解、建立长期密切合作关系的过程。

      

      准备好“行囊”

      

      用户测试的开始,要有一些准备。首先进行评审,确定系统具备了用户测试条件,可以从开发阶段转换到测试阶段。其次,进行组织和制度准备。第一,确定项目方(甲方)和开发方(乙方)和最终使用者共同组成一个项目协调小组,主要任务是需求控制和测试协调。第二,甲方任组长,重点负责需求控制和项目监督。第三,乙方重点负责优化完善OA系统。需要注意的是,此阶段开发队伍不能解散或人员减少。第四,用户代表主要负责对应用软件所有功能和流程进行使用测试,并提出建议和意见。用户代表最好是了解部门管理需求和业务全局,并熟悉主要业务的骨干。第五,建立每周一次项目协调会制度。协调会要保持科学性、严肃性、权威性和民主化。项目三方要对协调会负责,协调会要对内联网工程领导小组负责。

      

      选择好“目标和路线”

      

      用户测试要制定相应的测试要点,如,先测功能后测流程;先测处室内部后测处室之间;先测部门内部后测部门之间(包括集团领导、其他职能部门和子公司);最后进行集成测试和实战演习。同时,也要设计测试方案和选择典型案例,具体可以有如下步骤:

      1、作为用户测试的主要基础数据的依据,要确立模拟实际工作的典型案例,尽量多地覆盖待测试功能和流程。一般由开发方提出建议,由甲方和用户方审定;

      2、测试技术方案和技术文档主要由开发方准备;

      3、全过程测试记录表主要由甲、乙方根据案例和流程设计制作;

      4、集成测试时,有关部门、有关领导要亲自组织和协调;尽量用真角色、真数据,越接近实际使用越好;

      5、测试记录表由甲、乙方跟踪记录;反馈表由参测用户填写;作为评价系统和优化完善系统的依据;

      6、在测试开始时,开发方可以提供一个待测功能和流程的清单,方便初学用户测试;

      7、用户测试一般要反复多次测试;我们的经验一般要经过3轮测试。

      

      遇到问题困难时

      

      用户测试初期,反馈表主要填写程序中的一些BUG,但经过一、二轮测试后,用户反馈的问题就集中到功能完整性和流程合理性方面,特别是联调或集成测试时,用户已熟悉软件使用方法,会更多考虑系统的适用性和易用性,这时的意见直接关系到系统的实用性和产品化程度,是十分重要和关键的。因此,每当用户完成一轮测试,协调小组都要认真进行一次需求控制讨论会。在测试中,也有一些意想不到的问题——

      1、需求变更难以控制

      项目需求调研阶段,用户因为没有IT知识,讲不清究竟要系统干什么,虽然用户需求书双方签了字,但在用户测试过程中,随着IT经验的增加,自然会发现一些不合理或不完整或缺少的需求,必然会引起需求变更。我们的经验是:需求变化是不可避免的,关键是做好需求控制。如果放任需求变化,完全用户说了算,项目可能陷入无休止开发或进度失控状态。但若把需求书看作不可更改的圣经,从表面上看是坚持了合同,但无数事实表明,整个OA系统却可能因此而最终失败。我们的体会是:需求变更控制管理,是项目管理的核心和关键。我们在实施中,设计了用户测试反馈表,让用户在测试中随时填写。然后在每次协调会上,研究反馈表中用户的意见和建议。针对用户意见,我们有相应的三种策略:首先,没有满足需求书要求、或达到需求但没满足用户合理使用要求的,乙方要尽快解决;其次,对用户提出的新需求,如果三方协商一致同意实现,则以书面形式以总需求附件形式,纳入项目开发计划,受合同保护;第三,如果达不成共识,则不受合同保护。对用户不合理的要求,要敢于和善于向用户做实事求是的解释工作,争取得到用户的充分理解。经验表明,与用户搞僵的,多是以自己为中心的技术型人员,这些人对用户业务十分缺乏理解。

      2、技术开发的进度和成本难控制

      需求调研不充分,或因为开发人员对用户业务理解有限,或因为种种原因产生用户需求变更等等,都会引起修改或新开发程序,甚至引起技术路线的改变,造成进度拖延,而进度延迟,必然造成成本失控,类似问题相当普遍。

      3、数据导入工作的艰巨性难预测

      对于旧系统遗留的历史数据,其结构的复杂性或不规范性、数据量之浩大等等,常常估计不足。一旦发现问题,开发管理人员认为,让编程序的人去导入数据不划算;业务部门认为“我们工作都做不完,哪有时间去导入数据?”因而出现相互扯皮,有的出现程序测试没有数据的情况。而数据在信息系统中的重要性日益受到重视,越来越多的人认识到,“信息系统建设中,三分技术、七分管理、十二分数据”。新一代OA系统的重要特点是打破传统的信息孤岛现象,建立统一的信息共享平台。其核心之一,就是要对数据资源进行统一的规划,并制定统一的数据标准和建立整个OA系统共享的中心数据库。为此,建议成立专门的数据项目组、单独立项、专业实施。

      4、用户太忙,测试充分性难保证

      用户本职工作很忙,经常和测试发生时间冲突,既影响测试进度,又影响测试的充分性,这也是很难控制的问题。实践证明,用户代表在用户部门内的组织协调能力,以及甲、乙方积极配合,是解决问题的根本办法。那种完全依靠领导的做法,只能管一时或影响有限范围。

      由上可见,用户测试阶段是用户从使用角度,对OA系统进行全面检查和评价的过程。在这个阶段,用户可能提意见最多、最难听,也可能最不好理解,甚至有时为了搞清楚一个需求,还会发生激烈争论,但是,只有通过用户测试,开发方才能有的放矢地把OA系统优化完善成一个受用户欢迎的实用化的系统,它是 100步的第99步。当然,用户测试不是要到项目开发全部完成再进行,也可以根据项目情况,进行阶段的用户测试。问题发现得越早越好。这也是用户测试需要注意的。

      作者注:软件测试是一件很复杂的工作,而且包括很多方面,如压力测试、覆盖测试等等。本文仅阐述OA系统用户测试中的一些管理问题,欢迎交流。

  • 企业OA系统与政府政务OA的差别

    2007-08-30 10:39:02

     企业办公自动化系统(企业OA)与政务OA同为办公自动化系统,从技术上是一致的,从功能上也有很强的相似性。但由于应用领域、对象不同,两者也有着非常显著的差异。

      从功能上讲,政务OA应该说是以公文为核心的。流程是围绕着公文运转服务的。这是与政府部门的工作特点相一致的。而企业OA则是以工作流为核心,以协同工作和知识管理为重点,公文只是其中一个平行的一项应用。

      从特性上讲,政务OA更注重处理过程严格遵照政府部门的标准规范。而企业OA则随着每个企业的特点更注重从实际出发,更注重强调通过OA系统的实施改进企业流程。

      从目标上讲,政务OA同样以提高效率和对日常工作进行更加有效的管理为目标。而企业OA除此之外更加看重加强企业的快速反应能力,增强知识共享与管理,从而提升企业在激烈的市场中的竞争能力。从这个意义上讲,企业OA不仅是作为一个工具来应用,而更重要的是作为企业增强盈利能力的一个重要手段。这才是企业OA与政务OA的最本质的区别。
  • 企业OA入门(完整版)

    2007-08-30 10:38:07

    1、什么是企业办公自动化系统(企业OA)

    办 公自动化(OA: OFFICE AUTOMATION)就是采用Internet/Intranet技术,基于工作流的概念,使企业内部人员方便快捷地共享信息,高效地协同工作;改变过 去复杂、低效的手工办公方式,实现迅速、全方位的信息采集、信息处理,为企业的管理和决策提供科学的依据。一个企业实现办公自动化的程度也是衡量其实现现 代化管理的标准。

    企业办公自动化系统(企业OA)是企业应用软件体系的重要组成部分。

    企业OA系统,顾名思义,就是主要面向企业级的办公应用软件系统。它不是象MS Office一样的桌面(个人)办公系统,而是主要着眼于企业的工作人员间的协同工作。

    对于一个企业而言,不仅包括具体的生产、销售、采购过程,也不仅包括财务、人力资源等专项管理,而且同时有着大量的日常办公工作,有着大量不同职位、不同部门间的协同工作。企业办公自动化系统就是通过应用软件为企业的日常办公、协作提供支撑的平台。

    要更准确地理解企业办公自动化系统(企业OA),可以借助于分析它与其他相关概念的区别:

    1. 企业办公自动化系统(企业OA)的特点-与政务OA的差异 

      企业办公自动化系统(企业OA)与政务OA同为办公自动化系统,从技术上是一致的,从功能上也有很强的相似性。但由于应用领域、对象不同,两者也有着非常显著的差异。

      从功能上讲,政务OA应该说是以公文为核心的。流程是围绕着公文运转服务的。这是与政府部门的工作特点相一致的。而企业OA则是以工作流为核心,以协同工作和知识管理为重点,公文只是其中一个平行的一项应用。
      从特性上讲,政务OA更注重处理过程严格遵照政府部门的标准规范。而企业OA则随着每个企业的特点更注重从实际出发,更注重强调通过OA系统的实施改进企业流程。
      从 目标上讲,政务OA同样以提高效率和对日常工作进行更加有效的管理为目标。而企业OA除此之外更加看重加强企业的快速反应能力,增强知识共享与管理,从而 提升企业在激烈的市场中的竞争能力。从这个意义上讲,企业OA不仅是作为一个工具来应用,而更重要的是作为企业增强盈利能力的一个重要手段。这才是企业 OA与政务OA的最本质的区别。
    2. 企业办公自动化系统(企业OA)的特点-与ERP等系统的差异

      企业办公自动化系统(企业OA)与ERP、SCM、CRM等系统都是企业应用软件系统的重要组成部分,都为提升企业信息化水平、增强企业竞争力起着重要作用。但它们之间也存在着显著的差异。
      最基本的,就是它们功能不同。企业办公自动化系统(企业OA)着眼于协同工作、公文处理、文档管理、行政办公等。ERP着眼于企业的销售、采购、生 产、库存、财务等过程及资源控制与计划,SCM着眼于与上下游的衔接,CRM着眼于客户关系的管理,等等。
         更主要的,是它们的目标不同。可以说,ERP、SCM、CRM等系统更着重于企业的具体业务过程运作,而企业办公自动化系统(企业OA)更着重于企业的 管理过程。前者是通过优化业务过程的效率来提高生产效率、提高资金使用效率、加强对财、物的管理等等,后者则是通过优化管理过程来提高企业的日常办公与决 策效率、提高企业反应速度、决策能力、加强管理过程的规范性。
    3. 企业办公自动化系统(企业OA)的特点-与桌面办公软件的差异
      企业办公自动化系统(企业OA)从名称上讲与办公软件有相近之处,从概念上讲象MS Office等桌面办公软件也是办公自动化的组成部分。但从企业办公自动化系统(企业OA)的典型概念上,与桌面办公软件有着很大的差异。
      桌面办公软件应该说也是一种重要的办公自动化工具。但它们主要解决的是个人办公,面向的是个人工作效率的提高。虽然目前桌面办公软件也逐渐有一些协同 工作的功能,但都还是简单的协作,而无法面向企业级的、复杂的工作流程与协同工作。
      而企业办公自动化系统(企业OA)则主要面向的是企业整体办公效率的提高,其重点在于对跨岗位、跨部门的流程进行电子化处理,提高协同工作的效率与规范性,加强各部门间的知识共享,提高整体办公效率等等

    企业办公自动化系统(企业OA)通常包括以下主要部分:工作流、协同工作、知识管理、公文处理、行政办公等。

    企业办公自动化系统(企业OA)经历了数代发展,目前形成了以工作流技术为核心、以B/S应用模式为主流、多种支撑平台并存的技术方向。

    2、IT业界名词解释:办公自动化

    办 公自动化(OA: OFFICE AUTOMATION)就是采用Internet/Intranet技术,基于工作流的概念,使企业内部人员方便快捷地共享信息,高效地协同工作;改变过 去复杂、低效的手工办公方式,实现迅速、全方位的信息采集、信息处理,为企业的管理和决策提供科学的依据。一个企业实现办公自动化的程度也是衡量其实现现 代化管理的标准。

    虽然诸如Lotus 1-2-3和MS Office系列的许多应用软件可以提高办公效率,但是这仅仅是针对个人办公而言。办公自动化不仅兼顾个人办公效率的提高,更重要的是可以实现群体协同工 作。协同工作意味着要进行信息的交流,工作的协调与合作。由于网络的存在,这种交流与协调几乎可以在瞬间完成,并且不必担心对方是否在电话机旁边或是否有 传真机可用。这里所说的群体工作,可以包括在地理上分布很广,甚至分布在全球上各个地方,以至于工作时间都不一样的一群工作人员。

    办公自动化可以和一个企业的业务结合 的非常紧密,甚至是定制的。因而可以将诸如信息采集、查询、统计等功能与具体业务密切关联。操作人员只须点击一个按钮就可以得到想要的结果,从而极大得方 便了企业领导的管理和决策。   办公自动化还是一个企业与整个世界联系的渠道,企业的Intranet网络可以和Internet相联。一方面,企业的员工可以在Internet上 查找有关的技术资料、市场行情,与现有或潜在的客户、合作伙伴联系;另一方面,其他企业可以通过Internet访问你对外发布的企业信息,如企业介绍、 生产经营业绩、业务范围、产品/服务等信息。从而起到宣传介绍的作用。随着办公自动化的推广,越来越多的企业将通过自己的Intranet网络联接到 Internet 上,所以这种网上交流的潜力将非常巨大。

    目前企业的办公自动化程度可以划分为以下四类:

    • 起步较慢,还停留在使用没有联网的计算机,使用MS Office系列、WPS系列应用软件以提高个人办公效率。
    • 已经建立了自己的Intranet网络,但没有好的应用系统支持协同工作,仍然是个人办公。网络处在闲置状态,企业的投资没有产生应有的效益。
    • 已经建立了自己的Intranet网络,企业内部员工通过电子邮件交流信息,实现了有限的协同工作,但产生的效益不明显。
    • 已 经建立了自己的Intranet网络;使用经二次开发的通用办公自动化系统;能较好得支持信息共享和协同工作,与外界联系的信息渠道畅通;通过 Internet发布、宣传企业的产品、技术、服务;Intranet网络已经对企业的经营产生了积极的效益。现在正着手开发或已经在使用针对业务定制的 综合办公自动化系统,实现科学的管理和决策,增强企业的竞争能力,使企业不断发展壮大。

    办公自动化已经成为企业界的共识。众多企业认识到尽快进行办公自动化建设,并占据领先地位,将有助于保持竞争优势,使企业的发展形成良性循环。

    办 公自动化的实施应该考虑企业的实际情况,主要是企业的经济实力。按照上述分析,第一类企业进行办公自动化建设就需要较多投入,既要搭建企业 Intranet网络,又要开发办公自动化系统,需要企业有较强的经济实力才能完成;而对于第二、第三类企业,由于企业Intranet网络已经存在,只 是没有或没有好的办公应用系统,所以只须投入相对网络投资少得多的资金即可开发通用办公自动化系统,产生较高的投资回报。即便一步到位开发综合办公自动化 系统其投资也要比网络投资少得多,而产生的经济效益更高;对于第四类企业,由于其办公自动化基础好,只须较少的投资即可达到目前办公自动化的最高水平。

    3、办公自动化的发展

    从办公自动化的发展来看,办公自动化可以说经历了几个主要的阶段:

    第一阶段是以Lotus 1-2-3、WPS、MS Office软件等为代表的个人桌面办公的时代,实现了由手工到电脑的转变。

    第二阶段是以Lotus Notes(后来的IBM Domino)为代表,以及后来逐渐应用的MS Exchange及各种e-mail系统为代表的时代,即群件及e-mail的时代。它实现了交流与共享,也出现了基本的流程管理。

    第 三阶段是以B/S应用模式为代表的OA系统时代。在这一阶段普遍出现了较为成熟的系统。在技术上Domino平台在延续其生命力,但J2EE及.NET平 台开始占据优势。在应用上工作流(可配置的流程管理)逐渐成为标准。同时,也出现了知识管理等应用。可以讲这一阶段是一个功能应用逐步成熟的时代。

    第 四阶段是以协同为核心的时代。应该说它的范畴已经不局限于传统的OA,而是传统OA的新的扩展与发扬。但我们仍然可以把它划入OA的领域。这一阶段的特点 是,工作流、知识管理、门户技术全面成熟应用,行政办公与业务办公一体化,由原来孤立的功能应用发展为跨功能的全面信息与流程整合。

    以上是从OA的发展阶段来理解什么是OA。应该说不同时代办公自动化有不同的含义,而且这些阶段并不是截然分开,而是渐进发展的。今天我们理解的办公自动化,应该是企业(组织)内外部与办公相关功能的全面集成的一个协同工作平台。

    4、OA与知识管理的关系

    知识管理(KM)和OA的关系,简单来说:这是大概念和小概念的关系。OA只不过是KM中的一小部分。OA更加关注于流程的处理以及文档的管理,但是KM更多地关注于整个知识环路的全部过程。

    KM是将各种信息,经过传递、加工、整理,而升华为知识。目前大家都将文档管理称为知识管理,这是非常错误的。OA软件也绝对不是KM。

    真正的KM应该包括以下几个部分:OA、门户、e-learning、实时通讯、现实通讯等几个主要内容。但是,KM更多的是一种概念,而OA则更多的是一种应用。两者实在不应该混为一谈。

    现在很多OA拿着文档管理就叫知识管理,?如果是这样的KM----那就是OA中的一部分而已。如果要把KM理解成知识的挖掘/引进,收集,保存,共享的全过程,?那么不光OA了,?ERP/PDM很多都和它有交集

    知识管理要说大可以比任何系统大,要说小有可能就一文不值,关键还是看我们怎么样的应用,事实上也没有跟ERP等管理软件比较的地方,而应该是集成的使用,才能体现其价值。

    应用KM的结果是希望能为每个企业的日常运作增添更有效的信息,如与ERP的整合,能从中提取到非常有利益的资料,对于以后的分析提供更好的工具。

  • VBScript中的正则表达式语法详解

    2007-08-21 10:11:38

    -------------------正则表达式的所有内容-----------------------------
    RegExp属性
    Global
    IgnoreCase
    Pattern
    RegExp方法
    Execute
    Replace
    Test
    RegExp对象
    Match
    Match属性
    FirstIndex
    Length
    Value
    RegExp集合
    Matches
    SubMatches
    我在学习正则表达式的时候根本不知何谓正则表达式、对他的理解也非常模糊,以至于接触了很长时间才懂得,虽然vbs手册中有很详细地解释。
    正则表达式我个人将其理解为用来搜索文本然后然后对搜索结果作处理的一些列动作。
    先来看一段大家所熟知的ubb代码
    function ubb(str)
    Dim rex,match,matches 建立变量。
    Set rex= New RegExp 建立规范表达式。
    rex.IgnoreCase = True 设置是否区分字母的大小写。
    rex.Global = True 设置全程性质。
    rex.Pattern = "\(.*)\[\/url]" 设置模式。官方是这样解释的,我认为我们应该换一种叫法:搜索方法,这样我们才便于理解。
    ubb = rex.replace(str,"<a href=$1>$2</a>") 将我们搜索到的内容替换
    我们在设定搜索的时候用到了两个括号,也就是说我们将只需要用到这两个括号中的内容,这两个括号中的内容在替换的时候将会用$1(第一个括号中的内容)和$2(第二个括号中的内容)来代替。
    end function
    用法
    dim text
    text="
    link"
    document.write ubb(text) 输出文本并调用正则表达式
    如果在asp中使用请将document替换为response
    上面是一个简单的正则演示,在这个演示中我们只用了一行内容,用方法replace在替换文字的时候只处理一行中的第一个ubb代码头和最后的一个ubb代码的尾,如下:
    link link
    将会被替换为<a href=http://www.aaa.com]link [url=http://www.aaa.com></a>,这个结果可不是我们要的,
    也就是说我们必须在大量替换搜索内容前将要搜索的全部的文本或者字符串作处理。处理的结果就是要保证每一行只能存在一个相应的代码。这点非常重要,在我学习的时候一直搞不明白为什么?后来才知道是这个原因。
    在上面的一个示例中我们用到了正则表达使得所有属性以及replace的方法,下来我们来看一下有关于方法Execute,对象Match及所有属性,集合Matches 的一个官方的示例
    Function RegExpTest(patrn, strng)
    Dim regEx, Match, Matches 建立变量。
    Set regEx = New RegExp 建立正则表达式。
    regEx.Pattern = patrn 设置模式。即:搜索方法
    regEx.IgnoreCase = True 设置是否区分大小写。
    regEx.Global = True 设置全程可用性。
    Set Matches = regEx.Execute(strng) 执行搜索。我们可以理解为被搜索的字符串
    For Each Match in Matches 遍历 Matches 集合。
    RetStr = RetStr & "匹配" & Match 注意,在官方提供的示例中这里是错误的,
    这里是被匹配的名称
    RetStr = RetStr & "位于" & Match.FirstIndex & "。"这里是匹配内容的第一个字符,该数字从0开始
    RetStr = RetStr & "匹配的长度为"& Match.Length & "个字符。" 这里不用解释了吧?
    RetStr = RetStr & vbCRLF 这里是换行
    Next
    RegExpTest = RetStr
    End Function
    document.write(RegExpTest("is.", "IS1 is2 IS3 is4"))
    如果在asp中使用请将document替换为response
    在这个示例中我们可以看到方法Execute和对象Match是使用在集合Matches中的,Match和Matches是作为变量来使用的,为了我们很容易得看懂它,我们没有必要将他们换名字。关于对象Match的属性,我在上面的示例中都做了注释了。
    最后我们来看集合SubMatches,代码如下:(由于官方的这段代码很含糊,所以我修改了一下)
    Function SubMatchTest(inpStr)
    Dim Re, Match, Matches
    Set Re = New RegExp
    Re.Pattern = "(\w+)@(\w+)\.(\w+)"
    Set Matches = Re.Execute(inpStr)
    Set Match = Matches(0) 由于这里没有使用循环,所以只能搜索一次。只匹配搜索到的第一个内容
    retStr = "电子邮件地址是: " & Match & vbNewline 这里是匹配的内容
    retStr = retStr & "电子邮件别名是: " & Match.SubMatches(0) 第一个括号中的内容
    retStr = retStr & vbNewline
    retStr = retStr & "组织是: " & Match. SubMatches(1)第二个括号中的内容
    SubMatchTest = retStr
    End Function
    document.write(SubMatchTest("请写信到 dragon@xyzzy.com 。谢谢!"))
    如果在asp中使用请将document替换为response
    在上面的这段代码中我们看到了对象Match和集合Matches的另外一种用法,由此可见所有的集合均可以用这种方法,就像实用数组一样。看完上面的代码有些朋友可能想到既然在属性Pattern中已经提供了$1$2.....$n这种方法,为什么还要存在集合SubMatches呢?实际上在我们使用证则表达式的时候可能搜索要匹配的内容或字符串很长,然而我们还要对搜索到匹配的字符串进行进一步的处理,而$又不能实现这个,于是便有了集合SubMatches。
    到这里有关于VBscrīpt的正则表达式的内容就全部说完了,上面的3个代码均可以放在<scrīpt Language="VBscrīpt"></scrīpt>标签中使用也可以放在ASP中执行。
  • JavaScript正则表达式

    2007-08-21 10:10:46

    正则表达式是一个描述字符模式的对象。
    Javascrīpt的RegExp对象和String对象定义了使用正则表达式来执行强大的模式匹配和文本检索与替换函数的方法.

    '***********************
    '             Javascrīpt
    '
    '***********************

    在Javascrīpt中,正则表达式是由一个RegExp对象表示的.当然,可以使用一个RegExp()构造函数来创建RegExp对象,
    也可以用Javascrīpt 1.2中的新添加的一个特殊语法来创建RegExp对象.就像字符串直接量被定义为包含在引号内的字符一样,
    正则表达式直接量也被定义为包含在一对斜杠(/)之间的字符.所以,Javascrīpt可能会包含如下的代码:

    var pattern = /s$/;

    这行代码创建一个新的RegExp对象,并将它赋给变量parttern.这个特殊的RegExp对象和所有以字母"s"结尾的字符串都匹配.用RegExp()也可以定义
    一个等价的正则表达式,代码如下:

    var pattern = new RegExp("s$");

    无论是用正则表达式直接量还是用构造函数RegExp(),创建一个RegExp对象都是比较容易的.较为困难的任务是用正则表达式语法来描述字符的模式.
    Javascrīpt采用的是Perl语言正则表达式语法的一个相当完整的子集.

    正则表达式的模式规范是由一系列字符构成的.大多数字符(包括所有字母数字字符)描述的都是按照字面意思进行匹配的字符.这样说来,正则表达式/Java/就和
    所有包含子串 "Java" 的字符串相匹配.虽然正则表达式中的其它字符不是按照字面意思进行匹配的,但它们都具有特殊的意义.正则表达式 /s$/ 包含两个字符.
    第一个特殊字符 "s" 是按照字面意思与自身相匹配.第二个字符 "$" 是一个特殊字符,它所匹配的是字符串的结尾.所以正则表达式 /s$/ 匹配的就是以字母 "s" 结尾
    的字符串.


    1.直接量字符

    我们已经发现了,在正则表达式中所有的字母字符和数字都是按照字面意思与自身相匹配的.Javascrīpt的正则表达式还通过以反斜杠(\)开头的转义序列支持某些非

    字母字符.例如,序列 "\n" 在字符串中匹配的是一个直接量换行符.在正则表达式中,许多标点符号都有特殊的含义.下面是这些字符和它们的含义:

    正则表达式的直接量字符

    字符                                  匹配
    ________________________________
    字母数字字符                       自身
    \ f                                       换页符
    \ n                                      换行符
    \ r                                       回车
    \ t                                       制表符
    \ v                                      垂直制表符
    \ /                                       一个 / 直接量
    \ \                                       一个 \ 直接量
    \ .                                       一个 . 直接量
    \ *                                      一个 * 直接量
    \ +                                      一个 + 直接量
    \ ?                                       一个 ? 直接量
    \ |                                        一个 | 直接量
    \ (                                        一个 ( 直接量
    \ )                                        一个 ) 直接量
    \ [                                        一个 [ 直接量
    \ ]                                        一个 ] 直接量
    \ {                                        一个 { 直接量
    \ }                                        一个 } 直接量
    \ XXX                                    由十进制数 XXX 指 定的ASCII码字符
    \ Xnn                                    由十六进制数 nn 指定的ASCII码字符
    \ cX                                       控制字符^X. 例如, \cI等价于 \t, \cJ等价于 \n

    ___________________________________________________

    如果想在正则表达式中使用特殊的标点符号,必须在它们之前加上一个 "\" .


    2.字符类

    将单独的直接符放进中括号内就可以组合成字符类.一个字符类和它所包含的任何一个字符都匹配,所以正则表达式 / [abc] / 和字母 "a" , "b" , "c" 中的任何一个
    都匹配.另外还可以定义否定字符类,这些类匹配的是除那些包含在中括号之内的字符外的所有字符.定义否定字符尖时,要将一个 ^ 符号作为从左中括号算起的第
    一个字符.正则表达式的集合是 / [a-zA-z0-9] / .

    由于某些字符类非常常用,所以Javascrīpt的正则表达式语法包含一些特殊字符和转义序列来表示这些常用的类.例如,  \s 匹配的是空格符,制表符和其它空白符, \s
    匹配的则是空白符之外的任何字符.

    正则表灰式的字符类

    字符                                          匹配
    ____________________________________________________
    [...]                                           位于括号之内的任意字符
    [^...]                                         不在括号之中的任意字符
    .                                                除了换行符之外的任意字符,等价于[^\n]
    \w                                             任何单字字符, 等价于[a-zA-Z0-9]
    \W                                            任何非单字字符,等价于[^a-zA-Z0-9]
    \s                                              任何空白符,等价于[\ t \ n \ r \ f \ v]
    \S                                              任何非空白符,等价于[^\ t \ n \ r \ f \ v]
    \d                                              任何数字,等价于[0-9]
    \D                                              除了数字之外的任何字符,等价于[^0-9]
    [\b]                                            一个退格直接量(特例)
    ________________________________________________________________

    3.复制

    用以上的正则表式的语法,可以把两位数描述成  / \ d \ d /,把四位数描述成 / \d \ d \ d \ d /.但我们还没有一种方法可以用来描述具有任意多数位的数字或者是一个

    字符串.这个串由三个字符以及跟随在字母之后的一位数字构成.这些复杂的模式使用的正则表达式语法指定了该表达式中每个元素要重复出现的次数.

    指定复制的字符总是出现在它们所作用的模式后面.由于某种复制类型相当常用.所以有一些特殊的字符专门用于表示它们.例如: +号匹配的就是复制前一模式一次

    或多次的模式.下面的表列出了复制语法.先看一个例子:

    /\d{2, 4}/                                  //匹配2到4间的数字.

    /\w{3} \d?/                               //匹配三个单字字符和一个任意的数字.

    /\s+Java\s+/                             //匹配字符串"Java" ,并且该串前后可以有一个或多个空格.

    /[^"] * /                                   //匹配零个或多个非引号字符.


    正则表达式的复制字符

    字符                                          含义
    __________________________________________________________________
    {n, m}                                       匹配前一项至少n次,但是不能超过m次
    {n, }                                          匹配前一项n次,或者多次
    {n}                                            匹配前一项恰好n次
    ?                                               匹配前一项0次或1次,也就是说前一项是可选的. 等价于 {0, 1}
    +                                              匹配前一项1次或多次,等价于{1,}
    *                                               匹配前一项0次或多次.等价于{0,}
    ___________________________________________________________________


    4.选择,分组和引用

    正则表达式的语法还包括指定选择项,对子表达式分组和引用前一子表达式的特殊字符.字符| 用于分隔供选择的字符.例如: /ab|cd|ef/ 匹配的是字符串 "ab",或者是

    字符串 "cd",又或者 "ef". /\d{3}|[a-z]{4}/ 匹配的是要么是一个三位数,要么是四个小写字母.在正则表达式中括号具有几种作用.它的主要作用是把单独的项目分组

    成子表达式,以便可以像处理一个独立的单元那种用 *、+或? 来处理那些项目.例如: /Java(scrīpt) ?/ 匹配的是字符串 "Java",其后既可以有 "scrīpt",也可以没有. /

    (ab|cd) + |ef) / 匹配的既可以是字符串 "ef",也可以是字符串"ab" 或者 "cd" 的一次或多次重复.

    在正则表达式中,括号的第二个用途是在完整的模式中定义子模式。当一个正则表达式成功地和目标字符串相匹配时,可以从目标串中抽出和括号中的子模式相匹配

    的部分.例如,假定我们正在检索的模式是一个或多个字母后面跟随一位或多位数字,那么我们可以使用模式 / [a-z] + \ d+/.但是由于假定我们真正关心的是每个匹配

    尾部的数字,那么如果我们将模式的数字部分放在括号中 (/ [a-z] + (\d+)/) ,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的.

    代括号的子表达式的另一个用途是,允许我们在同一正则表达式的后面引用前面的子表达式.这是通过在字符串 \ 后加一位或多位数字来实现的.数字指的是代括号的

    子表达式在正则表达式中的位置.例如: \1 引用的是第一个代括号的子表达式. \3 引用的是第三个代括号的子表达式.注意,由于子表达式可以嵌套在其它子表达式中,

    所以它的位置是被计数的左括号的位置.
    例如:在下面的正则表达式被指定为 \2:
                                                                     /([Jj]ava([Ss]cript)) \sis \s (fun\w*) /


    对正则表达式中前一子表达式的引用所指定的并不是那个子表达式的模式,而是与那个模式相匹配的文本.这样,引用就不只是帮助你输入正则表达式的重复部分的快

    捷方式了,它还实施了一条规约,那就是一个字符串各个分离的部分包含的是完全相同的字符.例如:下面的正则表达式匹配的就是位于单引号或双引号之内的所有字

    符.但是,它要求开始和结束的引号匹配(例如两个都是双引号或者都是单引号):
                                                                    /[' "] [^ ' "]*[' "]/


    如果要求开始和结束的引号匹配,我们可以使用如下的引用:
                                                                                                              /( [' "] ) [^ ' "] * \1/


    \1匹配的是第一个代括号的子表达式所匹配的模式.在这个例子中,它实施了一种规约,那就是开始的引号必须和结束的引号相匹配.注意,如果反斜杠后跟随的数字比

    代括号的子表达式数多,那么它就会被解析为一个十进制的转义序列,而不是一个引用.你可以坚持使用完整的三个字符来表示转义序列,这们就可以避免混淆了.例如,

    使用 \044,而不是\44.下面是正则表达式的选择、分组和引用字符:

    字符                                                     含义
    ____________________________________________________________________
    |                                                           选择.匹配的要么是该符号左边的子表达式,要么它右边的子表达式
    (...)                    分组.将几个项目分为一个单元.这个单元可由 *、+、?和|等符号使用,而且还可以记住和这个组匹配的字符以供此后引

    用使用
    \n                                                         和第n个分组所匹配的字符相匹配.分组是括号中的子表达式(可能是嵌套的).分组号是从左到右计数的左括号数
    ____________________________________________________________________

     

    5.指定匹配的位置

    我们已经看到了,一个正则表达式中的许多元素才能够匹配字符串的一个字符.例如: \s 匹配的只是一个空白符.还有一些正则表达式的元素匹配的是字符之间宽度为

    0的空间,而不是实际的字符例如: \b 匹配的是一个词语的边界,也就是处于一个/w字字符和一个\w非字字符之间的边界.像\b 这样的字符并不指定任何一个匹配了的

    字符串中的字符,它们指定的是匹配所发生的合法位置.有时我们称这些元素为正则表达式的锚.因为它们将模式定位在检索字符串中的一个特定位置.最常用的锚元

    素是 ^, 它使模式依赖于字符串的开头,而锚元素$则使模式定位在字符串的末尾.

    例如:要匹配词 "Javascrīpt" ,我们可以使用正则表达式 /^ Javascrīpt $/. 如果我们想检索 "Java" 这个词自身 (不像在 "Javascrīpt" 中那样作为前缀),那么我们可以使

    用模式 /\s Java \s /, 它要求在词语Java之前和之后都有空格.但是这样作有两个问题.第一: 如果 "Java" 出现在一个字符的开头或者是结尾.该模式就不会与之匹配,除

    非在开头和结尾处有一个空格. 第二: 当这个模式找到一个与之匹配的字符时,它返回的匹配的字符串前端和后端都有空格,这并不是我们想要的.因此,我们使用词语

    的边界 \b 来代替真正的空格符 \s 进行匹配. 结果表达式是 /\b Java \b/.
    下面是正则表达式的锚字符:


    字符                                                       含义
    ____________________________________________________________________
    ^                                                           匹配的是字符的开头,在多行检索中,匹配的是一行的开头
    $                     匹配的是字符的结尾,在多行检索中,匹配的是一行的结尾
    \b                                                          匹配的是一个词语的边界.简而言之就是位于字符\w 和 \w之间的位置(注意:[\b]匹配的是退格符)
    \B                                                          匹配的是非词语的边界的字符
    _____________________________________________________________________

     

    6.属性

    有关正则表达式的语法还有最后一个元素,那就是正则表达式的属性,它说明的是高级模式匹配的规则.和其它正则表达式语法不同,属性是在 / 符号之外说明的.即它

    们不出现在两个斜杠之间,而是位于第二个斜杠之后.Javascrīpt 1.2支持两个属性.属性 i 说明模式匹配应该是大小写不敏感的.属性 g 说明模式匹配应该是全局的.也

    就是说,应该找出被检索的字符串中所有的匹配.这两种属性联合起来就可以执行一个全局的,大小写不敏感的匹配.

    例如: 要执行一个大小不敏感的检索以找到词语 "Java" (或者是 "Java" 、"Java"等) 的第一个具体值,我们可以使用大小不敏感的正则表达式 /\b Java\b/i .如果要在

    一个字符串中找到 "Java" 所有的具体值,我们还可以添加属性 g, 即 /\b Java \b/gi .

    以下是正则表达式的属性:


    字符                                                      含义
    _________________________________________
    i                                                            执行大小写不敏感的匹配
    g                                  执行一个全局的匹配,简而言之,就是找到所有的匹配,而不是在找到第一个之后就停止了
    _________________________________________

    除属性 g 和 i 之外,正则表达式就没有其它像属性一样的特性了.如果将构造函数 RegExp 的静态属性 multiline 设置为 true ,那么模式匹配将以多行的模式进行.在这

    种模式下,锚字符 ^ 和 $ 匹配的不只是检索字符串的开头和结尾,还匹配检索字符串内部的一行的开头和结尾.例如: 模式 /Java$/ 匹配的是 "Java",但是并不匹配

    "Java\nis fun" .如果我们设置了 multiline 属性,那么后者也将被匹配:

                                 RegExp.multiline = true;


    该文章转载自网络大本营:http://www.xrss.cn/Info/11409.Html

  • JScript 和 VBScript 正则表达式特殊字符

    2007-08-21 10:02:50

    有不少元字符在试图对其进行匹配时需要进行特殊的处理。要匹配这些特殊字符,必须首先将这些字符转义,也就是在前面使用一个反斜杠 (\)。下表给出了这些特殊字符及其含义:

    特殊字符 说明
    $ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
    ( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
    * 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
    + 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
    . 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。
    [ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
    ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
    \ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
    ^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
    { 标记限定符表达式的开始。要匹配 {,请使用 \{。
    | 指明两项之间的一个选择。要匹配 |,请使用 \|。

  • 什么是正则表达式

    2007-08-21 09:59:32

    正则表达式是查找和替换文本模式的简洁和灵活的表示法。Visual Studio 中使用的正则表达式是 Visual C++ 6.0 中使用的、具有简化语法的表达式的超集。

       
    在“查找”、“在文件中查找”或“在文件中替换”对话框中,可使用下列正则表达式来改进和扩展搜索。

       
    注意在将下列任何表达式用作搜索条件的一部分之前,必须在“查找”、“在文件中查找”和“在文件中替换”对话框中选择“使用”复选框。
    可使用下列表达式匹配搜索字符串中的字符或数字:

    表达式 语法 说明
    任一字符 . 匹配除换行符外的任何一个字符。
    最多 0 项或更多 * 匹配前面表达式的 0 个或更多搜索项。
    最多一项或更多 + 匹配前面表达式的至少一个搜索项。
    最少 0 项或更多 @ 匹配前面表达式的 0 个或更多搜索项,匹配尽可能少的字符。
    最少一项或更多 # 匹配前面表达式的一个或更多搜索项,匹配尽可能少的字符。
    重复 n ^n 匹配前面表达式的 n 个搜索项。例如,[0-9]^4 匹配任意 4 位数字的序列。
    字符集 [] 匹配 [] 内的任何一个字符。要指定字符的范围,请列出由短划线 (-) 分隔的起始字符和结束字符,如 [a-z] 中所示。
    不在字符集中的字符 [^...] 匹配跟在 ^ 之后的不在字符集中的任何字符。
    行首 ^ 将匹配定位到行首。
    行尾 $ 将匹配定位到行尾。
    词首 < 仅当词在文本中的此位置开始时才匹配。
    词尾 > 仅当词在文本中的此位置结束时才匹配。
    分组 () 将子表达式分组。
    | 匹配 OR 符号 (|) 之前或之后的表达式。). 最常用在分组中。例如,(sponge|mud) bath 匹配“sponge bath”和“mud bath”。
    转义符 \ 匹配跟在反斜杠 (\) 后的字符。这使您可以查找在正则表达式表示法中使用的字符,如 { ^。例如,\^ 搜索 ^ 字符。
    带标记的表达式 {} 标记括号内的表达式所匹配的文本。
    n 个带标记的文本 \n 在“查找”或“替换”表达式中,指示第 n 个带标记的表达式所匹配的文本,其中 n 是从 1 9 的数字。
    在“替换”表达式中,\0 插入整个匹配的文本。

    右对齐字段 \(w,n) 在“替换”表达式中,将字段中第 n 个带标记的表达式右对齐至少 w 字符宽。
    左对齐字段 \(-w,n) 在“替换”表达式中,将字段中第 n 个带标记的表达式左对齐至少 w 字符宽。
    禁止匹配 ~(X) X 出现在表达式中的此位置时禁止匹配。例如,real~(ity) 匹配“realty”和“really”中的“real”,而不匹配“reality”中的“real”。
    字母数字字符 :a 匹配表达式
    ([a-zA-Z0-9])

    字母字符 :c 匹配表达式
    ([a-zA-Z])

    十进制数 :d 匹配表达式
    ([0-9])

    十六进制数 :h 匹配表达式
    ([0-9a-fA-F]+)

    标识符 :i 匹配表达式
    ([a-zA-Z_$][a-zA-Z0-9_$]*)

    有理数 :n 匹配表达式
    (([0-9]+.[0-9]*)| ([0-9]*.[0-9]+)| ([0-9]+)).
    带引号的字符串 :q 匹配表达式 (("[^"]*")| ('[^']*'))
    字母字符串 :w 匹配表达式

    ([a-zA-Z]+)
    十进制整数 :z 匹配表达式
    ([0-9]+)

    转义符 \e Unicode U+001B
    Bell \g Unicode U+0007

    退格符 \h Unicode U+0008
    换行符 \n 匹配与平台无关的换行符。在“替换”表达式中,插入换行符。
    制表符 \t 匹配制表符,Unicode U+0009
    Unicode
    字符 \x#### \u#### 匹配 Unicode 值给定的字符,其中 #### 是十六进制数。可以用 ISO 10646 代码点或两个提供代理项对的值的 Unicode 代码点指定基本多语种平面(即一个代理项)外的字符。

    下表列出按标准 Unicode 字符属性进行匹配的语法。两个字母的缩写词与 Unicode 字符属性数据库中所列的一样。可将这些指定为字符集的一部分。例如,表达式 [:Nd:Nl:No] 匹配任何种类的数字。

    表达式 语法 说明
    大写字母 :Lu 匹配任何一个大写字母。例如,:Luhe 匹配“The”但不匹配“the”。
    小写字母 :Ll 匹配任何一个小写字母。例如,:Llhe 匹配“the”但不匹配“The”。
    词首大写字母 :Lt 匹配将大写字母和小写字母结合的字符,例如,Nj Dz
    修饰符字母 :Lm 匹配字母或标点符号,例如逗号、交叉重音符和双撇号,用于表示对前一字母的修饰。
    其他字母 :Lo 匹配其他字母,如哥特体字母 ahsa
    十进制数 :Nd 匹配十进制数(如 0-9)和它们的双字节等效数。
    字母数字 :Nl 匹配字母数字,例如罗马数字和表意数字零。
    其他数字 :No 匹配其他数字,如旧斜体数字一。
    开始标点符号 :Ps 匹配开始标点符号,例如左方括号和左大括号。
    结束标点符号 :Pe 匹配结束标点符号,例如右方括号和右大括号。
    左引号 :Pi 匹配左双引号。
    右引号 :Pf 匹配单引号和右双引号。
    破折号 :Pd 匹配破折号标记。
    连接符号 :Pc 匹配下划线标记。
    其他标点符号 :Po 匹配逗号 (,)?"!@#%&*\、冒号 (:)、分号 (;)' /
    空白分隔符 :Zs 匹配空白。
    行分隔符 :Zl 匹配 Unicode 字符 U+2028
    段落分隔符 :Zp 匹配 Unicode 字符 U+2029
    无间隔标记 :Mn 匹配无间隔标记。
    组合标记 :Mc 匹配组合标记。
    封闭标记 :Me 匹配封闭标记。
    数学符号 :Sm 匹配 +=~| < >
    货币符号 :Sc 匹配 $ 和其他货币符号。
    修饰符号 :Sk 匹配修饰符号,如抑扬音、抑音符号和长音符号。

  • QTP的一点资料

    2007-08-20 09:04:19

    QTP连接数据库

    ----------------------------------------------------------------------------------------------------------------------

    引用地址: http://www.51testing.com/?135582/action_viewspace_itemid_18118.html

    ----------------------------------------------------------------------------------------------------------------------

    (1)    首先要在控制面板中,加一个odbc数据源。

    (2)    {6j ~
    iu&M:F78029(((
    qtp中建立连接和记录集51Testing软件测试网+@K[D*LE

    set cnn=createobject("adodb.connection")
    m-G|m/qp78029set ōbjrsa=createobject("adodb.recordset")51Testing
    软件测试网?9\ t'T|fJ#w

    (3)    连接数据库


    IR-az.Z`78029cnn.open "provide=msdaora;userid=apts;password=apts;data source=afctwo"51Testing软件测试网8qw s+e[1]q;s
    userid/password,
    是登陆数据库的用户名和密码,这样数据库就连接上。

    (4)    @R(_0V7n,yF78029对数据库进行操作。
    `Y#J9G/T78029objrsa.open "select bustypefullname from bustypeinfo",cnn,3,251Testing软件测试网JV
    {"F)y%L[!`&K‑i

    a
    =objrsa("bustypefullname").value
    得到字段bustypefullname的值赋值给了变量a

     

     

    QTP中建立一个数据库检查点

    ----------------------------------------------------------------------------------------------------------------------

    引用地址: http://www.rapidtesting.cn/Html/QTP/07102.html  

    ----------------------------------------------------------------------------------------------------------------------

    Robot相比,QTP直接提供了对数据库中的数据进行检查的检查点,这样如果在我们的测试中需要对后台的业务数据进行检查,只需要建立一个数据库检查点就可以了。建立数据库检查点对于一些比较复杂的业务逻辑的测试非常重要。

    QTP 8种,建立一个数据库检查点的基本步骤如下:

    1  Insert菜单或工具条上选择新建一个Database Checkpoint  

    2  接下来需要为这个Database Checkpoint建立相应的Database Query,这里我们可以通过QTP 8提供的向导完成建立Database Query的过程。

    QTP 8里,我们有两种建立数据库query的选择:一种是通过Microsoft Query建立,这种方法比较简单,但是需要安装Microsoft Office中的Microsoft Query;另一种方法是手动建立,如果你对在Windows中手动建立ODBC数据源和SQL语句比较熟悉,那么可以选择这种方法。

    使用Microsoft Query建立数据库query的画面如下图,Microsoft Query可以帮助我们建立数据连接,选择数据源并建立数据库的qeury

    最后Microsoft Query会把建立好的query返回给QTP 8

    3  query建立好之后,QTP 8将打开Database Checkpoint的属性对话框让我们决定如何建立这个数据库检查点。

    数据库检查点对话框上方的表格中有蓝色对号的单元格表示将会作为基准数据在执行测试时参加检查,我们可以选择那些单元格的数据作为我们的基准数据。而在对话框下方有三个属性页,第一个属性页表明当前选择的基准数据是怎样配置的,可以是常数,也可以从数据表中读取,或者从被测软件的输出数据中读入。

    第二个属性页用来设置比较数据的规则。

    而第三个属性页用来设置在进行数据检查时怎样识别数据表的行,列以及单元格。如果我们选择通过键值来定位行数据,那么被选择为主键的列标题会加上图标作为标识。

    当属性设置完成以后,一个数据库检查点就建立成功了。

    4  修改数据库检查点

    如果需要对建立好的数据库检查点进行修改,可以通过选择该数据库检查点,然后选择检查点的Object Properties,在数据库检查点的Object Properties对话框中修改连接字串或者SQL query

    如果需要修改数据库检查点的数据或其它属性,也可以再次打开盖数据库检查点的Checkpoint Properties对话框。

     

     

     

    QTP识别和操作对象的原理

    QTP为用户提供了两种操作对象的接口,一种就是对象的封装接口,另一种是对象的自身接口。 对象的自身接口是对象控件本身的接口,只要做过软件开发,使用过控件的人应该很清楚。
       
    对象的封装接口是QTP为对象封装的另一层接口,它是QTP通过调用对象的自身接口来实现的。
       
    两种接口的脚本书写格式的差别在于:
       
    自身接口需要在对象名后面加object再加属性名或方法名,    封装接口就不用在对象名后面加object
       
    比如操作JavaEdit对象,通过QTP封装的封装接口,脚本如下:
       
    设置JavaEdit的内容:
         JavaDialog("Add NE").JavaEdit("NE Name").Set "NE1"
       
    读取JavaEdit的内容:
         msgbox JavaDialog("Add NE").JavaEdit("NE Name").GetROProperty("value")
       
    如果通过JavaEdit的自身接口,脚本如下:
       
    设置JavaEdit的内容:
        JavaDialog("Add NE").JavaEdit("NE Name").object.setText("NE1")
       
    读取JavaEdit的内容:
        Msgbox JavaDialog("Add NE").JavaEdit("NE Name").object.getText()
        QTP
    执行JavaEdit().Set语句时,是通过执行JavaEdit().object.setText()来实现的。
        QTP
    执行JavaEdit().GetROProperty("value"),是通过执行JavaEdit().object.getText()来实现的。
        JavaEdit
    对象的封装接口Set()GetROProperty("value"),是QTP封装JavaEdit对象的自身接口setText()getText()而得来的。
       
    对象的封装接口是QTP使用的缺省接口,我们录制出来的脚本都是使用封装接口,大家用的也都是封装接口。但是封装接口不如自身接口丰富,因为QTP只是封装了部分常用的自身接口嘛。所以我们在需要时,可以绕过封装接口,直接调用对象的自身接口。不过有些自身接口不够稳定,在实践中偶尔会出现问题,但是概率很少。封装接口有相应功能的话,就尽量用封装接口吧!  
       
    理解了封装接口和自身接口的原理,我们就可以更加灵活的操作对象了。
       
    但是我们怎么知道对象都有哪些封装接口和自身接口呢?
       
    其实很简单,用对象查看器(Object Spy)查看对象,在查看窗口里有列出这些接口,包括属性和方法。
       
    窗口中间有选择栏让你选择Run-time Object或者Test Object    当你选择Run-time Object时,它显示的就是对象的自身接口(自身的属性和方法)当你选择Test Object时,它显示的就是对象的封装接口(封装的属性和方法)
       
    明白了这些,你还等什么呢?快拿起对象查看器,看看对象都有哪些封装接口和自身接口,肆意的操作它,玩弄它吧!
       
    比如执行
        JavaDialog("Add NE").JavaEdit("NE Name").object.setVisible(false)
        
    哈哈,你的JavaEdit对象就当场消失不见了!!!

     

    QTP日志记录方法

    QTP自动化脚本执行中,QTP工程师肯定要考虑如何记录运行中的信息,什么时间执行了什么,中间遇到什么问题等等

    1.通过Shell记录windows事件,windows事件查看器中查看

    优点是操作方便

    Set WshShell = WScripit.CreateObject("Wscrīpt.Shell")

    0是信息,1是错误,2是警告

    WshShell.LogEvent 0, "Logon scrīpt Completed Successfully"
    WshShell.LogEvent 1, "Logon scrīpt failed"
    WshShell.LogEvent 2, "
    中文,2" 

    2.通过FileSystemObject来打开文件来记录

    优点是功能强大,想记录啥就是啥

    3.利用Desktop.CaptureBitmap来记录当前Screen

    填写问题单时,发生错误的页面抓图很有说服力,也便于查看,当出错时调用此函数

     

     

     

    QTP专家视图

    专家视图

    专家视图,也叫脚本视图,属于QTP中比较高级的功能选项。在该视图中,测试人员可以直接修改测试脚本(VB脚本)的代码,来增强测试脚本的功能,它要求测试人员具有一定VB脚本语法基础。
    当然,测试脚本中也不完全是VB脚本,严格意义上来说,QTP的测试脚本应该是标准 VB脚本和QTP测试对象的组合体。
    所谓的QTP测试对象,就是QuickTest定义的用来表示Windows窗体元素的对象,如同窗口,命令按钮等,每一个QTP测试对象都有若干个方法和属性,允许用户加以修改。
    就是我们刚才录制的测试脚本的专家视图:




    我们直接在该视图中修改和在关键字视图中修改的效果是一样的。
    VB脚本是一种容易学习并且功能强大的脚本,它是VB的一个子集,遵循VB的语法。
    如果读者原来没有接触过VB脚本的话,可以将关键字视图和专家视图中的对应项结合起来学习。

    下面简单介绍一下其语法:

    Ø
    常见的对象名:
    Dialog:对话框,括号里面的参数表示对话框标题栏上的名字
    WinEdit:Windows窗体中的文本框
    WinButton: Windows窗体中的命令按钮
    ActiveX: ActiveX控件
    WinComboBox: Windows窗体中列表框

    Ø
    常见的事件名:
    Set:当在文本框中输入信息时会触发该事件
    Click:当点击命令按钮时会触发该事件
    Select:当选择列表框或是单选按钮时会触发该事件
    Close:当关闭一个标准窗口或对话框时会触发该事件

    查看(1865) 评论(3) 收藏 分享 管理

  • 上班了,测试部门就我一个人

    2007-07-03 14:05:40

       毕业一周多了,今天正式去上班,到公司才知道,测试部门就我一个人,刚摸到公司的东西,好迷茫的感觉
  • 软件测试人员 缘何成为IT就业新贵

    2007-05-18 11:27:18

    近日,在国展举办的一次招聘会上,多家企业纷纷打出各类高薪招聘软件测试人员的海报,出人意料的是收到的简历尚不足招聘岗位数的50%,而合格的竟不足30%。同一时间前程无忧和中华英才网都显示,软件测试工程师将成为2006年最紧缺的人才,该类职位的需求主要集中在沿海发达城市,其中北京、上海的需求量分别占去33%29%。可以说,软件测试人才供远小于求使其成为今年就业市场的香饽饽。因此,越来越多的职业培训机构也纷纷推出相关软件测试培训项目。

    IT测试专才告急
      近年来,在中国IT行业的迅猛发展下,越来越多的IT企业已逐渐意识到测试环节在软件产品研发中的重要性。此类软件质量控制工作均需要拥有娴熟技术的专业软件测试人才来协作完成,软件测试工程师作为一个重头角色正成为IT企业招聘的热点。
      随着IT业在中国的发展,产品的质量控制与质量管理正逐渐成为企业生存与发展的核心。从软件、硬件到系统集成,几乎每个中大型IT企业的产品在发布前都需要大量的质量控制、测试和文档工作,而这些工作必须依靠拥有娴熟技术的专业软件人才来完成。
      为了保证软件在出厂时的健康状态,几乎所有的IT企业在软件产品发布前都需要大量的质量控制工作。作为软件质量控制中的重要一环,软件测试工程师应运而生。
      作为产品的把关人,软件测试人才的职场供需处于矛盾局面。一方面,企业对软件测试人才有大量需求,但却苦于招不到合适的人。而另一方面,很多应聘者甚至是高学历人才却因为缺乏相关技能而被用人单位拒之门外。
      对此,业内专家表示,软件测试行业已显现出实际需求与人力资源之间的尖锐矛盾。尽管期望加入软件测试行业者数量众多,然而能够达到企业需求的求职者数量寥寥。调查显示,企业在招聘中遇到很多计算机专业应届毕业生缺乏实际经验和动手能力以往有做过测试的应聘者并未系统化掌握软件测试流程问题的比例分别占到了72.7%59.1%。可见,无论是有经验者还是无经验者,由于对软件测试缺乏系统的了解和足够的职业技能,均成为阻碍求职者顺利进入的门槛。
      需求前景普遍被看好
      在许多IT企业中,软件测试并非只担当挑错的角色,其重要性不亚于软件的开发环节。根据资料显示,在国外大多数软件公司,1个软件开发工程师便需要辅有1-2个软件测试工程师。前微软亚洲研究院博士、软件测试专家陈宏刚表示,在很多大型的软件开发项目中,软件测试绝对不是开发活动完成后的收尾工作,甚至会占据整个项目周期一半以上的时间。
      在企业内部,软件测试工程师基本处于双高地位,即地位高、待遇高,有的人月薪可高达上万元,职场前景非常广阔,因而,近两年来,软件测试工程师也成为了IT就业最新的亮点。数据显示,有68.2%的受调查企业认为软件测试非常重要,必须设立专门的测试部门,并将其放到与开发环节同等重要的地位。但就目前软件测试和开发人员的比例来看,软件测试人员在公司所占比例仍然极不合理。调查数据显示,被调查企业中测试人员与开发人员比例为1:5的企业高达36.4%,比例为1:2的企业占31.8%,比例为1:1及以上的企业仅占31.7%
      IT测试专才缘何走俏
      在IT业就业形势不甚乐观的情况下,软件测试工程师却一枝独秀,企业在招聘时也相应地降低了要求,这个岗位也成为了进入IT业的一条捷径。且和开发人员相反的是测试人员的工作生命周期长,而且越老越值钱
      大多数人对软件测试的认识还局限在软件编写完成以后通过简单使用发现错误,事实上,软件测试作为一个软件产品正式面世前必不可少的质量控制环节,贯穿在整个软件产品的研发周期内,地位不容忽视。

  • GUI简介及设计原则

    2007-05-18 08:03:53

    1GUI基本概念

    1)什么是GUI

    GUIGraphical User Interface)是图形用户界面的英文缩写

    2)什么是UI

    UI的本意是用户界面(User Interface

    3UI计和GUI设计

    UI设计从工作内容上分3个方向:

    l         图形设计Graphic UI Design

    l         交互设计Interaction Design

    l         用户研究 User experience engineer

    l         研究界面图形设计师 graphic UI designer

    l         研究人与界面的关系交互设计师 Interaction Designer

    l         研究人用户测试/研究工程师 User Experience Engineer

    2.GUI发展历程及目前国内现状

    1)就用户界面的具体形式而言,过去经历了批处理、联机终端(命令接口)、(文本)菜单等多通道多媒体用户界面和虚拟现实系统

    2)就用户界面中信息载体类型而言,经历了以文本为主的字符用户界面(GUI)、以二维图形为主的用户界面(GUI)和多媒体用户界面,计算机与用户之间的通信带宽不断提高

    3)就计算机输出信息的形式而言,经历了以符号为主的字符命令语言、以视觉感知为主的图形用户界面、兼顾听觉感知的多媒体用户界面和综合运用多种感观(包括触觉等)的虚拟现实系统

    4)就人机界面中的信息维度而言,经历了一维信息(主要指文本流,如早期电传式终端)、二维信息(主要是二维图形技术,利用了色彩、形状、纹理等维度信息)、三维信息(主要是三维图形技术,但显示技术仍利用二维平面为主)和多维信息(多通道的多维信息)空间

    不论从何种角度看,人机交互发展的趋势体现了对人的因素的不断重现,使人机交互更接近于大自然的形式,使用户能利用日常的自然技能,不需经过特别的努力和学习,认知负荷降低,工作效率提高

    3GUI设计原则

    l         关注用户及其任务,而不是技术

    l         首先考虑功能,然后才是表示

    l         确定用户对任务的看法

    l         不要让用户任务复杂化

    l         促进学习

    l         传递信息,而不仅仅是数据

    l         设计应满足响应需求

    l         针对用户进行充分测试,然后进行修补

     

    案例分析请到我的文件里面下载,谢谢

    http://www.51testing.com/batch.download.php?aid=3507

    关于界面规范

    http://www.51testing.com/batch.download.php?aid=3514

  • C/S程序界面规范

    2007-05-17 11:03:27

    1. 界面规范
    1.1. 总体原则
    l 以用户为中心。设计由用户控制的界面,而不是界面控制用户。
    l 清楚一致的设计。所有界面的风格保持一致,所有具有相同含义的术语保持一致,且易于理解
    l 拥有良好的直觉特征。以用户所熟悉的现实世界事务的抽象来给用户暗示和隐喻,来帮助用户能迅速学会软件的使用。
    l 较快的响应速度。
    l 简单且美观。
    1.2. 原则详述
    1.2.1. 用户控制

    用户界面设计的一个重要原则是用户应该总是感觉在控制软件而不是感觉被软件所控制。
    l 操作上假设是用户--而不是计算机或软件--开始动作。用户扮演主动角色,而不是扮演被动角色。在需要自动执行任务时,要以允许用户进行选择或控制它的方式来实现该自动任务。
    l 提供用户自定义设置。因为用户的技能和喜好各不相同,因此他们必须能够个性化界面的某些方面。Windows为用户提供了对许多这方面的访问。您的软件应该反应不同的系统属性--例如颜色、字体或其他选项的用户设置。
    l 采取交互式和易于感应的窗口,尽量避免使用模态对话框,而使用"非模式"辅助窗口。 "模式"是一种状态,它排除一般的交互,或者限制用户只能进行特定的交互。当最好使用一个模式或该模式只是可替换的设计时--例如,用于在一个绘图程序中选定一个特定感觉--请确保该模式是显然的、可见的,是一个明确的用户选定的结果,并且容易取消。
    l 在后台运行长进程时,保持前台式交互。例如,当正在打印一个文档,即使该文档不能被改变,用户也应该可以最小化该窗口。
    l 谅解。用户喜欢探索一个界面,并经常从尝试和错误中学习。一个有效的界面允许交互式的发现,它只提供一组合适的选择,并在用户可能破坏系统或数据的情况时发出警告。如果可行,还应提供可逆转或可还原的操作。即使在设计得很好得界面中,用户也可能犯错误。这些错误既可以是物理上得(偶然地指向了错误的命令或数据),也可以是逻辑上的(对选定哪一个命令或哪些数据做出了错误的决定)。有效的设计避免很可能导致错误的情况。它还包容潜在的用户错误,并且使用户易于还原。
    1.2.2. 清楚一致的设计
    一致允许用户将已有的知识传递到新的任务中,更快地学习新事物,并将更多的注意力集中在任务上。这是因为他们不必花时间来尝试记住交互中的不同。通过提供一种稳定的感觉,一致使得界面熟悉而又可预测。一致在界面的所有方面都是很重要的,包括命令的名称、信息的可视表示,操作行为,以及元素在屏幕和窗口内部的放置。
    l 相同含义的词使用统一的术语。比如对于仓库中存放的物料,不可同时又称为物品、货物、备品、产品和材料等等,而统一约定一个称谓,且此称谓是用户熟悉的和易于理解的。
    l 使用一组一致的命令和界面来展示常见功能。例如,避免一个"复制"命令在一种情况下立刻执行一个操作,但在另一种情况显示一个对话框要求用户键入目标然后才执行。应该使用同样的命令来执行对用户来说相似的功能。
    l 操作环境内的一致。保持Windows提供的交互操作和界面约定之间的高度一致,用户将能很快熟悉软件的使用。
    l 使用隐喻的一致性。如果一个特定的行为更多的是一个不同的事物的特征,而不是它的隐喻的含义,那么用户可能在学习将行为和该事物相关联时遇到困难。例如,对于放在回收站中的对象而言,焚烧炉和废纸箩代表不同的模型。
    l 建立项目保留字。通过建立保留字来明确和统一术语和操作命令。
    l 提供可视反馈。在后台运行长进程时(时间超过1~10秒,视具体情况而定),必须提供进度条等信息指示。
    l 除非特别必要时,不要提供声音反馈。在有严重的问题发生时,可以使用声音来提示用户,但是通常应该允许用户取消声音。
    l 保持文字内容清楚。信息的表达要言简意赅,易于理解而又不罗嗦;避免使用冗长的文字给用户反馈。
    1.2.3. 有良好的直觉特征
    l 用熟悉的隐喻为用户的任务提供直接而直观的界面。通过允许用户利用他们的知识和经验,隐喻使得预测和学习基于软件的表示的行为更加容易。
    l 在使用隐喻时,不需要将基于计算机的实现局限在真实世界的对应物上范围之内。例如,与其基于纸张的对应物不同,Windows桌面上的文件夹可以被用来组织各种对象,例如打印机、计算器、以及其他文件夹。同样,Windows文件夹可以其真实世界对应物不可能的方式被排序。在界面中使用隐喻的目的是提供一个认知的桥梁;隐喻并不以其自身为最终目的。
    l 隐喻支持用户认知而不是记忆。用户记起与一个熟悉的事物相关联的意义要比他们记起一个特定命令的名称要容易得多。
    l 同常见软件保持一致性。出色的用户界面在程序中将实现同用户以前用过的其它成功软件一致的动作。
    1.2.4. 较快的响应速度
    l 保持界面能很快对用户操作作出反应。
    l 提供快捷键。特别对于有大量录入项的界面,能让用户不使用鼠标即可完成快速数据录入。在用户界面中加入一些功能,这些功能可以让熟练用户在不同的区域快速的输入数据。这些功能包括重复功能、快捷键、带有有意义的图标的按钮等等,所有这些可以使速度快的用户可以控制界面并加快数据的输入。
    l 除非必要,不要重绘屏幕。
    1.2.5. 简单且美观
    l 简单。界面应该很简单(不是过分单纯化)、易于学习、并且易于使用。它还必须提供对应用程序的所有功能的访问。在界面中,扩大功能和保持简单是相互矛盾的。一个有效的设计应该平衡这些目标。支持简单性的一种方法是将信息的表示减少到进行充分交流所需的最少信息。例如,避免命令名和消息的文字描述。不相关或冗长的句子扰乱了您的设计,使得用户难以很容易地提取重要信息。另一个设计简单而有用的界面的方法是使用自然的映射和语意。界面元素的排列和表示影响它们的意义和关联。简单还与熟悉相互关联。熟悉的事物通常似乎更简单。尽可能尝试建立利用用户已有的知识和经历的联系。您可以使用渐进揭示来帮助用户管理复杂的事物。"渐进揭示"涉及到仔细的信息组织,以便只在恰当的时候才显示信息。通过隐藏向用户表达的信息,您减少了用户必须处理的信息数量。例如,您可以使用菜单来显示操作或选择的列表,还可以使用对话框来显示一组选项。渐进揭示并不意味着对显示信息使用非传统的技术,例如需要一个修饰键作为访问基本功能的唯一方法,或者强迫用户通过一个更长的分级交互序列。这会使用户界面更加复杂和麻烦。
    l 美观。可视设计是应用程序界面的重要部分。可视属性提供了非常好的印象,并传达特定对象的交互行为的重要线索。同时,出现在屏幕上的每一个可视元素也是很重要的,它们可能竞争用户的注意。提供清楚地促进用户对表达的信息的理解的连贯环境。图形或可视设计器的技巧对于这一方面是无价的。

    1.3. 细节约定
    1.3.1. 界面风格

    1.3.1.1. 普通外观
    l 使用一致性一致的外观将使用户界面更易于理解和使用。用户界面控件看起来应该是一致的。
    l 使用安排和流程在西方文化中(包括中国),人们习惯于从左到右,从上到下进行阅读,因此,应该将重要信息放在上面和左边。左上角最容易吸引起人们的注意力。
    l 使用对齐通常,使用左对齐来使用户界面控件更易于浏览。对于数值文本,应该使用小数点对齐或右对齐。对于非数值文本,应该避免使用右对齐或居中对齐。不必对什么都使用中间对齐,或者使它们保持对称形式。在右边或底部保留空白区域更适合习惯。
    l 使用分组将相关的用户界面控件分成组,以体现它们之间的关系。同时,还要显示相关信息。将控件放在它所作用的对象旁。使用空格、分组框、线条和标签,或者其它分隔符对用户界面控件进行分组。
    l 使用强调使用焦点、位置、分组、层次、启用/禁用、大小、颜色或者字体等,来将注意力集中在需要首先看到的用户界面控件上。尽量以可视的方式指明用户接下来应该进行的操作。
    l 使用可视的提示尽量使用近似的大小和间距来指出用户界面控件是相似的,而使用不同的大小和间距来指出用户界面控件视是不同的。
    l 使用空格使用空格来创建一个"透气室",以使窗口布局更易于理解,并且查看起来更舒服。空格的多少要适当,不要显得太分散。但是,要避免过多地使用空格。如果可能,尽量使窗口小一些。
    l 警惕空洞不要到处粘贴公司或产品的名称及徽标。虽然在启动屏或"关于"框中出现公司或产品名称及徽标是完全可以接受的,但其他窗口中的可用空间应该出现其他内容。如果没有其他内容,那么应尽量使窗口小一些。
    l 注意大小使用用户界面控件的分辨率具有独立性。使用系统规格(使用GetGystemMetrics API 函数)或文本规格(使用GetTextMetrics或GetTextExtentPoint32 API 函数)来确定用户界面控件的大小。任何显示文本的对象(如对话框或定义的文本文档)都应该使用文本规格。
    l 考虑使用资源或预定义的布局网格资源模板或预定义的布局网格有助于您在不同的窗口之间实现一致性。

    注意,下页所示图的第二个对话框,与第一个不同,它有一个紧凑、从左到右、从上到下的流程,并且,左对齐的标签很便于浏览;通过对齐编辑框并调整其大小,使它显得更有组织,更加平衡。
     
    不合理的


    平衡的对话框
    1.3.1.2. Windows的可视提示
    暗示与用户只需通过查看可视提示来确定对象的使用方式的能力有关。在Windows中,请保持使用下面的可视提示:
    l 可以单击凸起的项目。
    l 可以单击当鼠标从其上移过时突出显示的项目。
    l 不能单击下凹的项目。
    l 可以编辑具有白色背景和闪烁垂直条(光标)的项目。
    l 不能编辑具有灰色背景的项目。
    l 灰色项目是被禁用的。
    l 可以拖动凸起的项目。
     

    1.3.1.3. 交互
    l 尽量提供对所有功能的键盘访问理想情况下,除了绘图这样的图形功能,其他所有的功能都应该只能通过键盘来访问。
    l 尽量提供对所有功能的鼠标访问理想情况下,除了文本输入外,其他所有功能都应该只能通过鼠标来访问。
    l 确保具有明显后果的操作要求用户进行明确的选择*用户需要完全明确他将要进行危险性操作或破坏性操作。
    l 对于使有耗时的操作都给出反馈*在进行长时间的操作时,要确保有等待光标、进度表或其他的可视反馈。用户应该能够取消长时间的操作。如果可以取消未完成的操作,那么将按钮标记为"取消",否则将按钮标记为"停止"。
    l 可视的指示模式*向用户提供一种可视的反馈,以指出用户进入一种模式,通常可以通过更改光标或标题栏文本来做到这一点。
    l 确保单击和双击的一致性*单击用于非按钮选定,而双击用于选定并执行默认操作。换句话说,双击(在列表框、组合框,或其他接受双击的控件中)的效果应该与选定控件中的一个项目,然后按下Enter键的效果一样。
    l 鼠标右键仅用于快捷菜单*确保鼠标右键仅用于快捷菜单,而不要用于其他用途。
    l 不要使用鼠标中键*如果用户的鼠标有中键,那么让用户使用"控制面板"中的"鼠标"实用程序自己分配中键的行为。
    l 保持分配的快捷键的一致性组合功能键和Ctrl键用于快捷键。习惯上不将Alt键用于组合键,业务Alt键常常被用于访问键。尽量避免使用Alt键和Ctrl键,因为这种组合会使快捷键非常麻烦,而且也很不方便。
    l 将快捷键作为补充方式*千万不要将快捷键作为访问命令的唯一方法。应该让用户有更多的明显选择。
    l 避免水平滚动条与垂直滚动条不同,水平滚动条并不受欢迎,因为它会使项目阅读起来比较困难。解决的办法有:尽量使用垂直滚动条、加宽窗口、减小文本的宽度,或者使文本自动换行等。当然,如果确实需要,还可以使用水平滚动条。
    1.3.1.4. 程序
    l 只有主程序窗口才有标题栏图标、菜单栏、工具栏和状态栏*因为单击主窗口的任务栏按钮也会激活二级窗口,所以二级窗口绝对不要显示在任务栏中。二级窗口不要因为使用菜单栏、工具栏或状态栏而使其变得复杂。可以使用标题栏图标来明显区分主窗口和二级窗口。另外,绝对不要使用默认的Windows图标(飘动的窗口图标)作为窗口图标。
    l 简化默认配置让用户按自己的速度来学习和使用程序。
    l 应用程序应该使用多文档界面(MDI)或单文档(SDI)这些程序界面应该与应用程序的使用模式匹配。
    l 默认情况下,应用程序应该保持为最大化当应用程序占用整个屏幕时,常常能够提高用户的工作效率。
    l 实用程序应该使用SDI或对话框界面这些程序界面应该与实用程序的使用模式匹配。对于实用程序,建议不要使用MDI界面,因为管理这些窗口需要付出很多努力。
    l 实用程序应该在小屏幕范围内运行实用程序常常与其他程序一起运行,因此它们需要在小屏幕范围内运行。实用程序应该有灵活的窗口布局,以适应多种不同的大小。实用程序很少以最大化的形式运行。
    l 使用实际文档的SDI程序必须支持运行多个实例*运行多个实例使用户能够同时操作多个文档。
    l 使用"退出"命令终止程序使用"退出"终止程序;使用"关闭"移走主窗口和非模式对话框;使用"取消"移走模式对话框。当关闭主窗口并不表示终止进程时,对于主窗口使用"关闭"来代替使用"退出"。例如:关闭打印机状态窗口不会取消打印任务。
    1.3.1.5. 默认
    l 保存和恢复用户选择程序应该能够能够恢复到其最后退出的状态。MDI程序应该能够恢复文档窗口的大小和位置。对话框通常应该使用最后输入的值作为默认值。
    l 提供适当的默认值提供提供适当的默认值来减少用户不必要的操作,从而帮助用户完成工作。提供最可能使用并给出设置实际使用方式的默认值。通常,最好的默认值是用户最后输入的值。
    l 考虑选择默认值时的安全性* 不应该将不可恢复或破坏性的操作设置为默认值。不要使用令用户感到莫名其妙的默认值。
    1.3.1.6. 窗体
    对话框窗体大小尽量不要超过640*460,留20给任务栏。并且高和宽(或W宽和高)的比应该大致保持为3:4(或4:3)。一般应该将窗体的"Position"属性定义为 "poDesktopCenter","WindowState"属性为"wsNormal",某些主界面设置为"wsMaximized"。"ShowHint"属性设为"True"。如果是模式对话框,则将"BorderStyle"属性设置为"bsDialog"。
    窗体文件(*.dfm)保存为文本格式,以便在VSS中比较不同版本之间的差别。如果窗体大小超过屏幕大小,则在Delphi开发环境中打开时,大小会有改变,并且影响到运行时刻效果。由于每个人的屏幕大小设置不一样,有些是1024*768,有些是800*600,因此在设计期间请注意窗体大小,尽量不要超过800*600,以免出现上述问题。
    
    1.3.1.7. 布局和间距
    窗体控件布局和间距尽量保持与Windows标准一致。控件与窗体的上、下、左、右边距为7象素。右下角主命令按钮之间的间距为6象素,如果主命令按钮在右上角,之间的间距则为4象素。主命令按钮一般情况为75×21象素,如果按钮的文本很长,应该适当加宽按钮的宽度。如下图。其它详细资料请完全参照错误!书签自引用无效。和命令按钮。
     

    控件的"TabOrder"属性值应该与控件排列顺序一致,即遵循从上到下、从左到右这样一个流程。如果在PageControl的多个页面中存在类似的控件,应该尽量使得它们在各个页面中出现的位置/大小比较一致,以免在页面间切换时产生闪烁感。

    1.3.1.8. 图标、图片
    不同界面中的同一功能应该使用同样的图标和图片。图标、图片的色调、风格尽量保持一致。图标、图片的隐喻应能确切表示功能的含义,如果不能,就直接使用文本,以免混淆用户。如果功能是一个动作时,可能比较难找到确切表示该功能的图标,这时应该尽量采用此动作相关的名词做图标。例如Windows中的"剪切"功能就是用一把剪刀来表示的。
    1.3.1.9. 提示信息(Hint)
    工具栏按钮应该设置工具提示 "Hint" 属性。Hint能帮助用户更方便地理解和使用。详细资料可以参照工具栏、工具提示。
    如果使用了"TSpeedButton"控件,并且只有图标,同样应对它设置"Hint"属性。如果不是特殊情况,应尽量避免使用"TSpeedButton"控件,而使用"TButton"控件代替。
    1.3.1.10. 标点符号
    在标识控件用途的标签文本(Label)和提示信息(Hint)中,应使用半角符号。如果是指导性标签文本(如解释按钮功能的句子),则使用全角符号,并且句子应遵循中文标点符号标准。如下图Microsoft标准对话框例子。其他详细资料可参照静态文本。


    1.3.1.11. 对话框
    l 对话框应该在所有视频模式下都能够正确显示当在VGA模式(640×480)下显示时,对话框应该不超过640×460(留20像素给任务栏)。这将确保对话框能够显示在所有的视频模式下。
    l 确保模式对话框的模式*确保使用具有父窗口的模式对话框都提供正确的父窗口句柄,而不时提供NULL句柄。如果没有提供父窗口句柄,那么父窗口仍处于活动状态,因此该对话框实际上并不是模式对话框。
    l 不要使用可滚动的对话框*也就是说,不要使用需要滚动条来进行完全查看的对话框。这种对话框使用起来非常不方便,并且也时完全不必要的。应该重新设计这种对话框。
    l 不要在作为二级窗口的对话框中使用菜单栏*使用这种对话框需要付出很多努力。注意,在用作主窗口的对话框(如"查找"实用工具)中,菜单栏时可以接受的。还要注意的是,在所有对话框中,快捷菜单和菜单按钮都是可以接受的。


    二级对话框不要使用菜单栏,但可以使用菜单按钮。

    l 不要在作为二级窗口的对话框中使用标题栏图标*标题栏图标用于区别主窗口和二级窗口。
    l 不要在任务栏上显示作为二级窗口的对话框*注意,单击主窗口的的任务栏图标也将激活二级窗口。
    l 对话框中使用下页图所示的页面布局和间距。
     
    l 对于相似的对话框,使用控件位置来强调其相似性。如果意义相同的同一控件出现在一些相似的对话框中,那么它应该显示在相同的位置。另一方面,应避免将可能会产生混淆的不同控件放在同一位置。
    l 对非模式对话框最好使用可停放的对话框可停放对话框在功能上与非模式对话框是等效的,但其位置设置更为灵活。
    l 策略地设置输入焦点将最初的输入焦点设置在最可能首先使用的控件上。
    l 在对话框标题文本中不要出现省略号例如,作为选择"打印选项..."命令结果而显示地对话框的标题应该为"对于选项"。但是,表示命令正在执行过程中菜单对话框(如"连接到Internet..."对话框)是一种例外情况。
    l 为所有可处理访问键的控件分配访问键*访问键可以使用户的手保持在键盘上,从而使访问程序更加方便。您可以直接在其标题中为诸如命令按钮、单选按钮、复选框等控件分配访问键。通过提供静态文本标签或带有访问键、在Tab顺序上先于控件的组框,您可以为诸如编辑框、列表框、组合框等控件分配访问键。在其他情况下不要为组框分配访问键--这会使人产生混淆。"确定"按钮没有访问键,因为在作为默认按钮时,它通过提Enter键来选定的。"取消"按钮也没有访问键,因为Esc键预览清除模式对话框。如果可能,避免使用小写的g、j、p、q或y作访问键,也避免使用这些字母前后的字母作为访问键。下划线不能与这些字母的下行字母分开。当然,访问键必须是唯一的。
    l 避免使用粗体文本尽量少使用粗体文本。在Windows 3.1 的对话框中,粗体文本用于在旧式的视频硬件上绘制被禁用的文本(即抖动的灰色文本)。因为现在的视频硬件可以绘制没有抖动的灰色文本,所以Windows 为了使外观更加清洁,现在Windows 在对话框中使用正常文本。粗体文本仅用于强调。对于大多数对话框不要粗体文本。
    l 提供环境敏感的帮助对于复杂的对话框,应该为整个对话框提供环境敏感的帮助(通过帮助按钮或F1键访问),或者为个别控件提供控件特定的帮助(通过"这是什么?"按钮或Shift+F1 键来访问),或者同时提供这两种帮助。
    1.3.1.12. 对话框的主要命令按钮
    l 将主命令按钮与对话框主体分开*主命令按钮包括像"确定"、"取消"、"关闭"、"帮助"、"停止"、"隐藏",以及其他相关按钮的等命令按钮。这种分开使主命令按钮更易于查找和识别。
    l 认真选择对话框的方向在西方文化中,人们习惯于从左到右、从上到下进行阅读,因此,将主命令按钮靠底部或右边放置更容易被发现。您应该选择对话框的外观比例与屏幕的外观比例(通常高与宽的比例为3:4)相似的方向。这将使对话框的外观看起来更加舒服,并且更易于在屏幕上进行定位。如果按钮具有不同的大小,那么可以将它们放在对话框菜单底部。当不能确定时,也可以将按钮放在底部,因为这种定位方式最为常见,也更易于阅读。
    l 将排列在底部的主命令按钮右对齐右对齐主命令按钮适合从左到右的阅读习惯。当只有一个主命令按钮时,您或许希望例外地将其居中放置。

     

    右对齐主命令按钮

    l 避免使用多行或多列的主命令按钮多行或多列的主命令按钮对用户是一个打击。如果有许多主命令按钮,那么注意,通常在右边排成一列与在底部排成一行相比可以放置更多的按钮。另外,您可以考虑使用命令菜单。如果必须使用很多按钮,那么注意使用多行别使用多列的效果好。
    l 对模式对话框,通常提供"确定"和"取消"按钮*要使用对话框,用户需要能够方便地识别前进(使用"确定"按钮)和后退(使用"取消"按钮)的方式。您可以使用更明确的按钮代替"确定"按钮,但绝对不要在模式对话框中替换"取消"按钮,除非用"停止"来表明正在进行的操作无法取消。
    l 对于非模式对话框或或作为主窗口的对话框,提供"关闭"按钮而不提供"确定"和"取消"按钮*将"确定"和"取消"按钮用于非模式对话框或作为主窗口的对话框可以使对话框看起来像是模式对话框。而且,当用于非模式环境中时,"确定"和"取消"时没有什么意义的。使用"关闭"按钮可以消除这种混淆。
    l 通常将"确定"按钮排第一,"取消"其次,"帮助"最后*"确定"或其等价按钮通常作为第一个主命令按钮。"取消"按钮应该位于"确定"的右边或下面。将"确定"和"取消"按钮放在一起。"帮助"按钮应该时最后一个按钮。如果没有"确定"按钮,那么应该将"取消"按钮放在"帮助"按钮的前面。这可以使主命令按钮更易于查找和识别。
    l 确保"取消"按钮真正用于取消操作*当取消时,程序的状态栏应该与之前显示的模式对话框完全相同。如果不是这样,那么应该用"停止"按钮来代替"取消"按钮。模式对话框中的"取消"按钮应该与标题栏中的"关闭"按钮效果相同。而属性表是个例外,因为"取消"按钮不会取消已经应用的更改。
    1.3.1.13. 属性表和属性页
    l 让属性页独立工作避免使一个属性页的行为或操作受其他属性页的限止。用户不可能发现属性页之间的这种独立关系。在属性页的使用顺序方面应该没有限止。用户应该能够随时查看任意的属性页。
    l 属性页的布局相互独立一些属性页通常不会占用同样大小的空间。占用空间较小的属性页应该与最大的属性页的布局的格式方式不同,因为将会产生额外的空间(见下图)。

     

    属性页的布局保持独立,避免居中。

     

    l 用属性表代替使用带选项卡的对话框使用属性表而不使用带选项卡的对话框除了具有一致性之外,没有什么明显的实用性优势。另外,对于实际显示对象属性的对话框使用属性表,而对于其他用途,所有带选项卡的对话框。
    l 对属性显示总采用属性表,即使仅有一个页*采用属性表能够明确告诉用户查看的使属性而不是一般的对话框。属性表有一个"应用"按钮来帮助用户测试设置。
    l 绝对不要使用两行以上的标签*最好使用一行标签,但两行也是可接受的,两行以上就太多了,可用级连属性设置或多个对话框代替。
    l 总为属性提供"应用"按钮再说一次,提供"应用"按钮帮助用户对设置进行测试。
    l 对显示属性的属性表总是在其标题中写上"属性"一词和对象的名称*请注意,不是所有的属性表都是用来显示属性的。
    l 总将命令按钮放在右边*适用于所有页的命令按钮必须置于标签页区域的外面,而仅适用于单个页的命令按钮必须置于该标签页的里面。
    1.3.1.14. 向导
    l 对高级的、复杂的或不常用的任务使用向导向导对非常高级或复杂的任务十分有用,省去了用户许多麻烦的操作。当向导用于不常用的任务时,其效果最好。对常用任务使用向导则显得大而不当。
    1.3.1.15. 控件
    l 尽量采用标准控件尽可能采用标准控件(6个最早的控件和新的Win32常用控件)。采用非标准控件的程序与绝大多数Windows程序看起来不一致。只用完全合理时才使用自定义控件。
    l 定制标准控件时要小心改变标准控件的标准外观或行为时一定要小心,这是个常常出错的地方。
    l 将无效控件置为不可用*将不适用于当前程序状态的控件置为不可用。
    l 取消不必要滚动条尽量使控件的尺寸足够大,避免使用滚动条。
    1.3.1.16. 命令按钮
    l 采用最小的宽度和标准的高度带文字的命令按钮应该采用50个对话单位(75个像素点)的最小宽度、14个对话单位(21个像素点)的标准高度。尽量将不同大小的带文字命令按钮的个数控制在两个以内。对父窗口拖动(owner-draw)按钮或无文字的按钮(如"…"),其大小可以任意设置,原则是使命令按钮外观简朴一致。高度大于14个对话单位(21个像素点)的按钮看起来不够专业。尽管不限制命令按钮的最大宽度,但宽度超过200个对话单位的按钮使不妥当的。请参阅下图所示关于命令按钮的实例。
     

    命令按钮大小示例

    l 针对国际化适当加宽按钮尽管50个对话单位(75个像素点)的宽度是适合英语文字的最小宽度,但对需要针对其他语言进行本地化的程序来说,可能就太小了。对于需要翻译为其他语言的程序,将命令按钮的最小宽度定为60个对话单位可能更适合。
    l 将无效按钮置为不可用,以取消报错*绝对不要使可用的按钮仅产生一条出错信息。
    l 总采用省略号来表示需要更多信息*命令中的省略号表示执行命令时需要更多信息,而不是简单的确认。省略号并不表示一定会出现对话框。
    l 绝对不要指定双击行为*用户意料不到命令按钮会响应双击,因此不可能发现这样的行为。
    命令按钮大小使用Window标准75x21象素。一般情况下,"确定"和"取消"按钮的属性设置如下:
      btnOk: TButton
         Caption = '确定'
         Default = True
         ModalResult = mrOk
      end
      object btnCancel: TButton
         Cancel = True
         Caption = '取消'
         ModalResult = mrCancel
      End
    "确定"和"取消"按钮一般被映射为Enter键和Esc键,因此不应该对它们指定访问键,除此以外的命令按钮都应该指定一个访问键。如下图:
     

    主命令按钮在下

    如果主命令按钮在右上角,应该布置为这样。
     

    主命令按钮在上

    如有其他不明,请参照命令按钮。
    如果设计期间未指定"ModalResult",注意一定要在按钮的"OnClick" 事件代码中为"ModalResult"赋值。
    1.3.1.17. 复选框
    l 用复选框开关选项,用单选按钮改变模式*用复选框进行选项的开关操作是很有效的,但如果用来将模式改变为另外一种状态就难免让人迷惑了。例如,可用一个复选框来表示是否显示工具栏,但若用复选框来切换打印机的横向模式和纵向模式就会使人糊涂,对横向和纵向模式应该用一组单选按钮代替。
    l 避免一组复选框中选项个数超过8个应该考虑用复选框列表代替,它占用的空间更少,但复选框列表需要滚动时使用就稍稍麻烦了。尽管控件足够或保持与同一窗口中其他复选框一致时,采用复选框时可取的,但大于8个左右的复选框就未免太多了。
    l 考虑将修改组的复选框置于应该分组框中这样的分组使得复选框之间的关系更为明显。
    l 宁可竖向对齐虽然更合适的情况下采用横向对齐或直角对齐也是可以接受的,但竖向对齐的一组复选框更易于浏览。
    1.3.1.18. 单选按钮
    l 避免一组单选按钮中的选项个数超过8个考虑用列表或组合框代替,它们占用的空间更少,但要记住控件使用更麻烦些。尽管控件足够或保持与同一窗口中其他单选按钮一致时,采用单选按钮是可取的,但多于8个的单选按钮未免太多了。
    l 避免使用单选按钮进行开 / 关或是 / 否选择用复选框代替。
    l 总将单选按钮置于一个分组框中*由于单选按钮是一组相互排斥的选项,所以分组框使选择更为明确。
    l 宁可竖向对齐虽然更合适的情况下采用横向对齐或直角对齐也是可以接受的,但竖向对齐的一组单选按钮更易于浏览。
    1.3.1.19. 组合框
    l 总给组合框提供一个标签*必须用标签来表明组合框的用途。
    l 使组合框的下拉列表最少有5行长少于5行的列表就没有可用的滑块,不易于滚动。请注意,如果组合框没有足够的列项来填满列表,那么将自动缩短列表的长度。
    l 避免组合框的列项少于4考虑用单选按钮代替,它们虽然多占空间,但更易于操作。如果空间更为重要或为了保持与同一窗口中的其它组合框一致时,采用组合框则更为可取。
    1.3.1.20. 编辑框
    l 总给编辑框提供一个标签*必须用标签来标明编辑框的用途。如果标签在左边,将标签文字与编辑框文本垂直对齐。
    l 避免有输入限制的编辑框将编辑框用于用户对任何文本的输入或数字编辑框用于数字的编辑。对于输入受限的情况,使用其他的控件,如组合框、列表、滑块和微调框。对于日期和时间,使用日期和时间拾取控件。
    l 用微调框和浏览按钮使编辑框可视微调框和浏览按钮是简单的可视机制,它们帮助用户在编辑框中进行有效的输入。避免让用户必须输入。仅对数字编采用带微调框的编辑框,对于文本,使用组合框代替。
    l 按期望输入来设置编辑框的宽度编辑框的宽度是对期望输入的可视提示。例如,如果用户是输入地址,两个字符宽的State字段明显暗示用户输入两个字符的州名缩写。如果期望的输入没有特别的大小,就选择与其他编辑框或控件一致的宽度。
    l 总采用数字编辑框用于数字输入*当用户在数字字段中输入非数字文本时,不应该有任何出错消息。
    1.3.1.21. 滑块
    l 总给滑块提供一个标签* 必须用标签来标明滑块的用途。而且,滑块还应该有标明高、低值意义和当前选择的标签--当然都不带冒号。
    1.3.1.22. 静态文本
    l 左对齐静态文本标签左对齐使得标签外观更有条理,且易于浏览。
    l 宁可将静态文本标签置于相关控件的左边,而不是上面这样对齐使标签更易于被发现,且方便了标签和控件的浏览。很明显,长控件是例外情况,如列表视图、树形视图(Tree)和多行编辑框。
    l 总在用于标识控件的静态文本标签后带上冒号*使用冒号明显表示为控件标签的文本。为控件提供附加信息的标签不应该有冒号,如用来解释滑块控件的标签。标签也可作为屏幕读出器的输入信息。
    l 对非标签文本总用只读编辑框*  只读编辑框允许用户将文本复制到剪贴板上,并在文本比控件长时可进行滚动。
    l 不要把静态文本置于凸起的边界上*在凸起边界上的静态文看起来像按钮,因而用户会试图单击它。
    1.3.1.23. 列表框
    l 总给列表框提供一个标签*必须用标签来标明列表框的用途。
    l 使列表框至少5行长少于5行的列表没有滑块,不便于滚动。如果列表框没有滚动条,那么使用一个更短的列表框也是可以接受的。
    l 对多个选择考虑采用复选框复选框列表可以突出其多个选择的能力。如果不能接受复选框列表,那么可以采用多选列表,并用静态文本表示选项个数,清楚指明可进行多项选择。
    l 对多选列表考虑提供"全部选中"和"全部取消选中"命令由于希望全部选中或全部取消使常见的事情,所以这两个命令方便了用户进行多项选择。
    1.3.1.24. 列表视图
    l 总给列表视图提供一个标签*必须用标签来标明列表视图的用途。
    l 使列表视图至少5行长少于5行的列表视图没有滑块,不便于滚动。如果列表视图没有滚动条,那么使用一个更短的列表视图也是可以接受的。
    l 仅在列表可排序时采用可单击的表头*可单击的表头只应用于排序。首次单击时应按正序对列表进行排序,而第二次单击时按反序进行排列。
    l 对列项大约超过30的列表视图总使其可进行排序*用户能够对列表进行排序方便了对信息的查找。
    1.3.1.25. 滚动条
    l 滚动条仅用于滚动*使用滑块或微调框来设置数值。
    l 使滚动条足够长,保证有可用的滑块。没有滑块的滚动条不便于使用。
    1.3.1.26. 分组框
    l 利用分组框分组相关控件尽管分组框通常是用于单选按钮的分组,但也可用于任何控件的分组。避免使用只有一个控件的分组框,除非是为了保持与同一对话框中其他分组框一致。
    l 考虑采用静态线或文本标签来代替分组框分组框多时要占去许多空间。如果空间紧张的话,一个替代分组控件的好办法是同时采用静态文本标签和静态线。

     

    考虑采用静态文本标签和静态线代替分组框

    l 不要在分组框标签的后面使用冒号*分组框标签的意思明白,使用冒号完全没有必要且让人糊涂。

    1.3.1.27. 菜单
    l 总用单个单词作为菜单标题*菜单栏上多个单词的菜单标题看起来像多个菜单标题。
    l 不要在菜单栏的文本间留有空隙*不一至的菜单栏文本既无用,又难看。
    l 避免占多行的菜单栏*尽管将父窗口缩小到足够窄时,任何菜单栏都要占用几行,当要避免正常使用时因菜单项都而占用几行的菜单栏。
    l 保持菜单稳定*将无效菜单置为不可用,而不要删除它们。但是,对整个程序实例都无效的菜单,就应该删除。
    l 合理安排菜单项的顺序将相关菜单项组合在一起。重要的命令应该位于菜单的顶部,而不重要的菜单则位于菜单的底部。
    l 将无效菜单置为不可用来代替报错*菜单绝不应该有仅产生出错消息的可用命令。
    l 分配访问键*访问键使用户可以手不离开键盘进行操作,并提供程序的可访问性。尽可能避免用小写字母g、j、p、q、y或单词中与它们靠近的字母来分配访问键,因为下划线与下一行的字母不好区分。当然,一个菜单中的访问键应该是唯一的。
    l 总采用省略号来表示需要更多信息*命令中的省略号表示执行时需要更多的信息,而不是简单确认。省略号不表示一定有对话框出现。
    l 使用标准菜单避免不提供"文件"、"编辑"和"帮助"菜单。由于这些是标准菜单,所以用户会期望它们出现。例如,期望在"文件"菜单中发现像"打印"和"退出"这样的命令,虽然这些命令可能与"文件"无关。同样,用户期望在"编辑"菜单中发现"剪切"、"复制"和"粘贴"命令,至少要在"帮助"菜单中发现"关于"命令。
    l 统一放置"查找"和"选项"命令总将"查找"命令放在"编辑"菜单中,而有"工具"菜单时,总将"选项"置于其中,否则置于"查看"菜单中。
    l 用复选标记来开关选项,用单选组来改变模式*用复选标记进行选项的开关操作是有效的,但如果用来将模式改变为另外一种状态就难免让人迷惑了。例如,可用一个复选标记来表示是否显示工具栏,但若用复选框来切换打印机的横向模式和纵向模式就会使人糊涂,对横向和纵向模式应该用一个单选组来代替。
    l 不要使用多列的下拉菜单*多列增加了菜单不必要的复杂性。
    l 不要使用"Bang"(爆炸的声音)菜单*Bang菜单是菜单栏上那些看起来像下拉菜单,但实际是选择后立即执行的命令,如"退出"!显然,用户希望菜单标题就只是菜单,而不是命令。
    l 不要右对齐菜单标题*这样的菜单风格陈旧且不易于使用。
    1.3.1.28. 上下文菜单
    l 考虑将上下文菜单作为冗余使用上下文才菜单不应该是访问命令的唯一方式。通常上下文菜单中的命令应该在菜单栏中也提供,使用上下文菜单是为了提高访问效率。
    l 避免在上下文菜单中包含快捷键应该将快捷键分配在菜单栏中,上下文菜单的快速访问是通过鼠标进行,而不是通过键盘。
    1.3.1.29. 工具栏
    l 保持工具栏稳定*将无效的工具栏按钮置为不可用,而不是将它删除。但是,应该考虑删除用户进入一种模式用不到的整个工具栏。
    l 将无效命令置为不可用,而不是报错*工具栏绝不应该包含只出现错误消息的命令。
    l 对实用程序采用大工具栏按钮好的使用程序工具栏常常与应用程序的按钮不同,其按钮更简朴,更大。实用程序工具栏应该只包含几个带有描述性文字和图形的显眼命令。
    l 对应用程序采用可移动的、可定制的工具栏,而对实用程序采用固定的工具栏应用程序需要灵活的工具栏来支持其典型的使用方式。用户使用实用程序的时间一般不长,因而不需要定制工具栏。
    l 提供显示或隐藏工具栏选项如果有多个工具栏,分别为它们提供显示或隐藏的选项。
    l 总使用工具提示*工具提示帮助用户了解工具栏按钮的作用。
    1.3.1.30. 工具提示
    l 用工具栏的工具提示来提供信息,但要简短避免提示很明显的事情。考虑采用省略号来表示执行命令时需要更多信息。如果该命令已分配有快捷键,则显示该快捷键。
    l 使工具提示文本成为高级用户的媒介工具提示用于简短的识别和提醒,而不是用来教学。
    l 用工具提示显示有用信息不仅仅可在工具栏上使用工具提示,它的使用简单,能够向用户提供有用信息。但不可滥用--工具提示太多也就失去了其价值。不要对命令按钮会静态文本这样的控件使用工具提示。
    l 不要自动消去包含许多文字的工具栏提示默认时,10秒种后工具提示将自动消去。如果工具提示的文字很多,10秒钟对用户来说就看不完了。
    1.3.1.31. 文本
    l 避免不必要的缩写词要么给文本更多的空间,要么改写文本使其占用更少的空间,缩写词使文本不易理解。
    l 避免不必要的大写字母文本除非只去首字母构成的缩写词,否则不要用字母全为大写的单词,这样的单词看起来像在冲用户大喊大叫一样。
    l 避免复杂的标号尽量采用简单的标点,如句号、逗号、问号,以及破折号。避免使用分号、感叹号、圆括号、括号,等等。
    l 采用一致的大小写规则*对窗口标题、菜单、命令按钮、列标题属性页选项卡以及工具栏提示文字采用与书题一样的大小写规则,而对于标题、单选按钮、复选框、分组框和菜单项帮助中的文本采用与句子一致的大小写规则。(对于标题,除了不是标题开头和结尾的冠词和介词外,每个单词的第一个字母大小。对于句子,每个句子的第一个单词以及通常大写的单词--如专有名词的首字母大写。)
    l 避免不好的背景将文本放在实地、颜色适中的背景上,确保在文本和背景之间存在良好的对比。
    l 避免冒犯性语言避免激烈的词语,如fatal(致命的)、execute(执行)、kill(杀死、毁掉)、terminate(终止)、和abort(中止)。
    1.3.1.32. 消息框
    l 仔细选择消息框的类型采用带"确定"按钮的信息消息框向用户提供有关命令结果的信息。采用带"是"、"否",以及可能"取消"按钮的警告消息框在继续进行前需要用户输入的情形下告诫用户。采用危急消息框通知用户进行工作前需要修改一个错误。
    l 不要使用疑问消息框类型*不再推荐对消息框使用疑问标记符(MB_ICONQUESTION),因为它在Windows98后一致用来表示上下文修改帮助。
    l 避免不必要的消息框不要用出错消息来报告正常行为,而应该用来报告不正常或不期望的结果。不要对很容易恢复的操作进行确认。
    l 问用是/否回答的问题问用户问题时,采用"是"和"否"按钮代替"确定"和"取消"按钮,这样使问题易于理解。与对话框中不一样,"确定"和"取消"按钮很少同时用在消息框中。
    l 确保消息框选项按钮与文本一致例如绝不要用"是"和"否"来作为非提问消息的响应。同样,不要使用多个效果相同的选项按钮。例如,除非有不同的操作结果,否则不要同时提供"否"和"取消"按钮。"否"按钮应该执行操作,而"取消"应该取消操作。
    l 仔细选择默认按钮将最安全的或最常用的选项作为默认按钮。
    l 避免无用的帮助除非提供真正有用的附加信息,否则不要提供"帮助"按钮。不要附加带无用帮助信息的没意义的消息框。
    l 对危急错误考虑采用系统模式消息框采用系统模式消息框向用户提示严重的、可能造成破坏性的、急需注意的错误。系统消息框除了有WS_EX_TOPMOST样式外,与应用程序模式对话框完全一样。与在16位Windows中不一样的是,系统模式不影响用户与其他程序的交互。
    1.3.1.33. 错误消息
    l 避免错误号除非这个错误号对用户真正有用,否则不要给出错误号。
    l 避免责怪用户避免在出错消息文字中出现单词you(你)或your(你的)。如果需要,当指用户操作时使用被动语气。采用与"错误发生了"等价的表达,比采用与"你捅漏子了"等价的表达要好得多。
    l 避免敌对性语言避免在错误消息文字中使用词语bad(糟糕的、坏的)、caution(小心)、error(错误)、fatal(致命的)、illegal(非法)、invalid(无效)和warning(警告),而应该使用更具体的描述性词语。并且应该尽量解释到底是什么出了错。
    l 在出错消息文字中使用平实的语句表达要简短、清楚、协调、具体。除非缩写词,否则不要使用全部大写的单词,那样的单词看起来像在冲用户大喊大叫一样。使用完整的句子和一般的现在或过去时态。避免缩写词。
    l 避免在用户错误消息文字中装做有趣或高人一等用户并不觉得错误消息有趣,故装幽默并不能被广泛接受。
    l 允许用户压制非危急的错误消息对经常出现的非危急错误,向用户提供一个压制该错误消息的选项。
    1.3.1.34. 字体
    字体统一使用以下设置:
    Charset = GB2312_CHARSET
    Name = '宋体'
    Size = 9
    Color = clWindowText
    Style = []
    字符集不要使用 ANSI_CHARSET 或 DEFAULT_CHARSET,否则可能导致不同的操作系统下字符集不一致。
    l 尊重用户的字体选择*Windows允许用户为标题栏、菜单、消息框和工具提示选择字体。及时处理WM_SETTINGCHANGE消息以根据设置迅速而安全地改变字体。
    l 避免让人分心地字体一般说来,应避免使用Arial、Tahoma和MS Sans Serif之外的字体。Verdana、TrebuchetMS和Century Gothic也适合于轻微差别的外观。即使文档中的截线字体很不错,但界面中的任何截线字体都被认为是让人分心的。除了提示用户输入或模拟打字机外,不要采用等宽字体。
    l 避免使用粗体和斜体用粗体来吸引人的注意,用斜体表示着重,但要还少使用。
    l 避免混合字体任何不包含文档的窗口最多包含两种不同的字体。
    1.3.1.35. 颜色
    l 使用系统颜色*尊重用户的颜色选择,避免使用固定颜色。不要强迫用户使用您选择的颜色。避免让人分心的文本颜色,通常是黑色之外任何颜色,对文本使用系统颜色COLOR_BTNTEXT或COLOR_WINDOWTEXT。在白色(COLOR_WINDOW)背景上使用黑色(COLOR_WINDOWTEXT)文字是完全正确的。及时处理WM_SYSCOLORCHANGE消息以根据设置迅速而完全地改变颜色。
    l 根据内容而不是外观来选择系统颜色*不要将作为一个集合中的几种系统颜色混合匹配在一起。例如,不要将COLOR_BTNTEXT和COLOR_WINDOW混合在一起。
    l 考虑对图形使用中间调色板在256色模式下使用中间色调色板避免了调色板的闪烁。
    l 不要用颜色作为传递消息的唯一方式*不依赖于对颜色的区分可以增强程序对色盲用户的可访问性,并且使程序可运行在单色显示器上。
    1.3.1.36. 三维效果
    l 避免不必要的三维效果除非对控件分组,否则避免三维静态线和矩形框。宁可采用空白来分开组件,绝不在三维矩形框周围套其他的三维矩形框。避免使用三维文本。

     

    三维效果过多

    在界面中采用太多的三维效果是程序员常范的错误。毕竟,如果有些三维效果很酷,对吧?不完全如此。请看下面的对话框。一点也不酷。一旦三维控件流行起来,就好像能使用三维的都采用三维,而不管看起来是好是坏。即使采用三维边框,其目的也是为了让人理解。采用许多三维静态框架控件通常是个坏征兆,现代的趋时是倾向于更为简单的风格。
     


    l 使用柔和的三维效果请注意Window98中更为细致的三维效果是如何比Window 3.1中的三维效果更有效更悦目的。尽管绝大多数现时世界的物体有加亮区,但很少有黑色实边框的。Windows98仅是通过在突起物体的右边和底部加上黑色边框以及在凹陷物体的上部和左边加黑色边框来达到三维效果。

     

    去除多余的三维效果

     

    最少三维效果

    l 使用一致的三维效果*确保三维效果的光源位于屏幕的左上角。
    1.3.1.37. 各种细节
    l 不要发音和闪动没什么比发音和闪动的程序更烦人的了。但闪烁程序的任务栏窗口按钮通知用户未决消息例外。
    l 避免不必要的视频效果至少一个使其为可选择的。理想情形是,默认时关闭这样的效果,用户有明确要求时才打开。
    l 用缩放功能提高文档可访问性提供提供文档缩放功能,可提高显示文档的程序的可访问性和整体性能。
    l 处理WM_DISPLAYCHANGE消息*改变显示分辨率后,程序应该能够正确显示和运行。
    l 基于光盘的程序的应该支持自动播放当光盘插入驱动器后,"自动播放"应该显示一列选项,包括安装。程序安装以后,不应该运行"自动播放"。
    l 支持用户采用日期和时间拾取控件进行日期输入,GetDateFormat和GetTimeFormat函数用于设置货币和数字的格式,LCMapString API用于排序。考虑采用RichEdit控件用于文本输入和输出。最后,利用WM_INPUTLANGCHANGE消息来处理输入语言的改变。
    1.3.2. 统一术语
    1.3.2.1. 术语的重要性
    我们用名称来区别、描述和查找事物,使用名称来分解并理解不熟悉的事物。采用统一的术语有助于我们更好地理解和进行交流--简化并统一用户界面术语有助于用户理解和充分应用我们设计的界面。
    使用不同的术语描述相同的事物是最让人迷惑的,而改变人人都已经熟悉的术语也是有害的。这两种情况都使得程序难以讨论、描述,以及归档。甚至使它难以编程。
    1.3.2.2. 命名
    下面是一些需要命名的、与界面有关的典型对象:
    ● 程序本身;
    ● 程序使用的文档类型;
    ● 用户利用程序执行的主要操作;
    ● 所有的窗口、对话框和属性表;
    ● 主程序窗口中的使用区域;
    ● 认为非标准的屏幕对象、命令、属性、交互、或者技术。
    简而言之,用户可以看到或需要与其进行交互的、显示在菜单、工具栏、窗口、对话框、状态栏、联机帮助或文档中的任何内容都需要有一个名称。当然,您将会使用已存在的标准屏幕对象的名称。例如,您不需要命名常用的对话框,因为它们已经拥有名称。

    1.3.2.3. 用用户的语言说话
    使用软件面向的用户所熟悉的词语,除非您的软件是为了程序员设计的,否则应该避免使用计算机行话,而应用常用的单词代替。例如,对绝大多数用户来说,常用单词"separator"(分隔符)就比技术术语"delimiter"(定界符)要好得多。如果必须使用技术词汇,那么应采用那些用户可能知道的术语。
    1.3.2.4. 要避免的术语
    也有些术语是千万不要用在您的用户界面中的。尽管"execute"执行、"kill"(杀死)、"terminate"(结束)、"fatal"(致命的)和"abort"(中止)这样的术语在程序员文献中是完全可接受的,但完全应该避免出现在其他的文字中。

  • GUI录制回放测试方法缺点

    2007-05-17 10:58:31

    现在的专业测试工具,如Robot、Winrunner等,均提供通过GUI录制回放进行功能测试的功能。在厂商的宣传资料中,可以见到厂商把录制回放描述的如何如何好,如何如何有效。但是在使用的过程会逐渐的发现事实并非如此。
    1、脚本的维护性
        现在网上有很多的网友都遇到了脚本难于维护的问题,因为GUI经常会有变化。直接导致脚本回放失败。另一方面,被测程序会有众多的窗口,回放过程中经常会出现不期望的窗口,导致回放失败,然后修改脚本加入对新窗口的处理代码,这个过程会使你感到厌烦。所以很多测试者,等到程序相对稳定时才开始自动化测试。
    2、效率问题
        好不容易将脚本修改的可以处理全部窗口(已经花费了很多时间和精力),效率问题又出现了。如果需要测试大量的数据,虽然可以使用多台计算机同时回放,但是有时还是满足不了要求。
    3、界面识别问题
        虽然现在的专业的测试工具都支持很多种编程语言,但是还是有很多的控件无法正确识别。虽然工具也提供了通过记录鼠标移动轨迹和按键的功能,但是实际的使用效果并不一定理想。

        虽然GUI录制回放有很多的缺点,但是它仍然是一种不错的测试方法,还是有很多适合使用的地方。
        专业的测试工具是通用的,在具体的测试环境中并不能完全满足要求。可以结合其他的工具使用,各取所长。我测试采用VB、SQL SERVER、Robot三者结合使用,取长补短。

  • UI测试要点

    2007-05-17 10:49:56

    01.按功能将界面划分局域块,完成相同或相近功能的按钮框起来, 并要有功能说明

    02.界面要支持按Tab键的自动切换功能;Tab键切换是否正确; Tab键的顺序与控件排列顺序要一直,目前流行总体从上到下,同时行间从左到右的方式;

    03.默认按钮要支持Enter及选操作,即按Enter后自动执行默认按钮对应操作

    04.菜单点击,窗口初始化

    05.父窗体或主窗体的中心位置应该在对角线焦点附近;子窗体位置应该在主窗体的左上角或正中;多个子窗体弹出时应该依次向右下方偏移,以显示窗体出标题为宜

    06.分辨率1024*768下是否显示正常

    07.前景与背景色搭配合理协调,反差不宜太大,最好少用深色,如大红、大绿等。常用色考虑使用Windows界面色调。

    08.如果窗体支持最小化和最大化或放大时,窗体上的控件也要随着窗体而缩放;对于含有按钮的界面一般不应该支持缩放,即右上角只有关闭功能。

    09.窗体能否多次正确关闭,打开

    10.滚动条是否能拖动,并可通过键盘自动拖动

    11.与正在进行的操作无关的按钮应该加以屏蔽(Windows中用灰色显示,没法使用该按钮)

    12.对可能造成数据无法恢复的操作必须提供确认信息,给用户放弃选择的机会,如删除确认提示,退出前确认是否保存

    13.可写控件的数据类型及长度,尽量在前台进行控制

    14.非法的输入或操作应有足够的提示说明, 让用户明白错误出处,避免形成无限期的等待,提示、警告、或错误说明应该清楚、明了、恰当;提示顺序按Tab顺序

    15.对一些特殊符号的输入、与系统使用的符号相冲突的字符等进行判断并阻止用户输入该字符, 特殊字符常有;;’”><,{、\|}]+=)-(_*&&^%$#@!,.?/还有空格

    16.在读入用户所输入的信息时,根据需要选择是否去掉前后空格。

271/212>
Open Toolbar