总是很难忘记生活的点点滴滴, 脑海中总是闪过好多的曾经, 美好的回忆, 但成长中却让我们失去了很多, 很想在忙碌的生活中淡淡忘记; 不曾放低的东西却始终让我忘记不了, 但我还要在忙碌的生活中继续生活!

发布新日志

  • java性能优化

    2008-11-14 14:06:14

    一、避免在循环条件中使用复杂表达式


    在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

    例子:
    import java.util.Vector;
    class CEL {
        void method (Vector vector) {
            for (int i = 0; i < vector.size (); i++)  // Violation
                ; // ...
        }
    }

    更正:
    class CEL_fixed {
        void method (Vector vector) {
            int size = vector.size ()
            for (int i = 0; i < size; i++)
                ; // ...
        }
    }

    二、为'Vectors' 和 'Hashtables'定义初始大小


    JVM为Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大是一个颇费时间的事。
    通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小。

    例子:
    import java.util.Vector;
    public class DIC {
        public void addObjects (Object[] o) {
            // if length > 10, Vector needs to expand
            for (int i = 0; i< o.length;i++) {    
                v.add(o);   // capacity before it can add more elements.
            }
        }
        public Vector v = new Vector();  // no initialCapacity.
    }

    更正:
    自己设定初始大小。
        public Vector v = new Vector(20);  
        public Hashtable hash = new Hashtable(10);

    参考资料:
    Dov Bulka, "Java Performance and Scalability Volume 1: Server-Side Programming
    Techniques" Addison Wesley, ISBN: 0-201-70429-3 pp.55 – 57

    三、在finally块中关闭Stream


    程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。
             
    例子:
    import java.io.*;
    public class CS {
        public static void main (String args[]) {
            CS cs = new CS ();
            cs.method ();
        }
        public void method () {
            try {
                FileInputStream fis = new FileInputStream ("CS.java");
                int count = 0;
                while (fis.read () != -1)
                    count++;
                System.out.println (count);
                fis.close ();
            } catch (FileNotFoundException e1) {
            } catch (IOException e2) {
            }
        }
    }
             
    更正:
    在最后一个catch后添加一个finally块

    参考资料:
    Peter Haggar: "Practical Java - Programming Language Guide".
    Addison Wesley, 2000, pp.77-79

    四、使用'System.arraycopy ()'代替通过来循环复制数组


    'System.arraycopy ()' 要比通过循环来复制数组快的多。
             
    例子:
    public class IRB
    {
        void method () {
            int[] array1 = new int [100];
            for (int i = 0; i < array1.length; i++) {
                array1 [i] = i;
            }
            int[] array2 = new int [100];
            for (int i = 0; i < array2.length; i++) {
                array2 [i] = array1 [i];                 // Violation
            }
        }
    }
             
    更正:
    public class IRB
    {
        void method () {
            int[] array1 = new int [100];
            for (int i = 0; i < array1.length; i++) {
                array1 [i] = i;
            }
            int[] array2 = new int [100];
            System.arraycopy(array1, 0, array2, 0, 100);
        }
    }
             
    参考资料:
    http://www.cs.cmu.edu/~jch/java/speed.html

    五、让访问实例内变量的getter/setter方法变成”final”


    简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”

    例子:
    class MAF {
        public void setSize (int size) {
             _size = size;
        }
        private int _size;
    }

    更正:
    class DAF_fixed {
        final public void setSize (int size) {
             _size = size;
        }
        private int _size;
    }

    参考资料:
    Warren N. and Bishop P. (1999), "Java in Practice", p. 4-5
    Addison-Wesley, ISBN 0-201-36065-9

    六、避免不需要的instanceof操作


    如果左边的对象的静态类型等于右边的,instanceof表达式返回永远为true。
             
    例子:         
    public class UISO {
        public UISO () {}
    }
    class Dog extends UISO {
        void method (Dog dog, UISO u) {
            Dog d = dog;
            if (d instanceof UISO) // always true.
                System.out.println("Dog is a UISO");
            UISO uiso = u;
            if (uiso instanceof Object) // always true.
                System.out.println("uiso is an Object");
        }
    }
             
    更正:         
    删掉不需要的instanceof操作。
             
    class Dog extends UISO {
        void method () {
            Dog d;
            System.out.println ("Dog is an UISO");
            System.out.println ("UISO is an UISO");
        }
    }

    七、避免不需要的造型操作


    所有的类都是直接或者间接继承自Object。同样,所有的子类也都隐含的“等于”其父类。那么,由子类造型至父类的操作就是不必要的了。
    例子:
    class UNC {
        String _id = "UNC";
    }
    class Dog extends UNC {
        void method () {
            Dog dog = new Dog ();
            UNC animal = (UNC)dog;  // not necessary.
            Object o = (Object)dog;         // not necessary.
        }
    }
             
    更正:         
    class Dog extends UNC {
        void method () {
            Dog dog = new Dog();
            UNC animal = dog;
            Object o = dog;
        }
    }
             
    参考资料:
    Nigel Warren, Philip Bishop: "Java in Practice - Design Styles and Idioms
    for Effective Java".  Addison-Wesley, 1999. pp.22-23

    八、如果只是查找单个字符的话,用charAt()代替startsWith()


    用一个字符作为参数调用startsWith()也会工作的很好,但从性能角度上来看,调用用String API无疑是错误的!
             
    例子:
    public class PCTS {
        private void method(String s) {
            if (s.startsWith("a")) { // violation
                // ...
            }
        }
    }
             
    更正         
    将'startsWith()' 替换成'charAt()'.
    public class PCTS {
        private void method(String s) {
            if ('a' == s.charAt(0)) {
                // ...
            }
        }
    }
             
    参考资料:
    Dov Bulka, "Java Performance and Scalability Volume 1: Server-Side Programming
    Techniques"  Addison Wesley, ISBN: 0-201-70429-3

    九、使用移位操作来代替'a / b'操作


    "/"是一个很“昂贵”的操作,使用移位操作将会更快更有效。

    例子:
    public class SDIV {
        public static final int NUM = 16;
        public void calculate(int a) {
            int div = a / 4;            // should be replaced with "a >> 2".
            int div2 = a / 8;         // should be replaced with "a >> 3".
            int temp = a / 3;
        }
    }

    更正:
    public class SDIV {
        public static final int NUM = 16;
        public void calculate(int a) {
            int div = a >> 2;  
            int div2 = a >> 3;
            int temp = a / 3;       // 不能转换成位移操作
        }
    }

    十、使用移位操作代替'a * b'


    同上。
    [i]但我个人认为,除非是在一个非常大的循环内,性能非常重要,而且你很清楚你自己在做什么,方可使用这种方法。否则提高性能所带来的程序晚读性的降低将是不合算的。

    例子:
    public class SMUL {
        public void calculate(int a) {
            int mul = a * 4;            // should be replaced with "a << 2".
            int mul2 = 8 * a;         // should be replaced with "a << 3".
            int temp = a * 3;
        }
    }

    更正:
    package OPT;
    public class SMUL {
        public void calculate(int a) {
            int mul = a << 2;  
            int mul2 = a << 3;
            int temp = a * 3;       // 不能转换
        }
    }

    十一、在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只有一个字符的话



    例子:
    public class STR {
        public void method(String s) {
            String string = s + "d"  // violation.
            string = "abc" + "d"      // violation.
        }
    }

    更正:
    将一个字符的字符串替换成' '
    public class STR {
        public void method(String s) {
            String string = s + 'd'
            string = "abc" + 'd'   
        }
    }

    十二、不要在循环中调用synchronized(同步)方法


    方法的同步需要消耗相当大的资料,在一个循环中调用它绝对不是一个好主意。

    例子:
    import java.util.Vector;
    public class SYN {
        public synchronized void method (Object o) {
        }
        private void test () {
            for (int i = 0; i < vector.size(); i++) {
                method (vector.elementAt(i));    // violation
            }
        }
        private Vector vector = new Vector (5, 5);
    }

    更正:
    不要在循环体中调用同步方法,如果必须同步的话,推荐以下方式:
    import java.util.Vector;
    public class SYN {
        public void method (Object o) {
        }
    private void test () {
        synchronized{//在一个同步块中执行非同步方法
                for (int i = 0; i < vector.size(); i++) {
                    method (vector.elementAt(i));   
                }
            }
        }
        private Vector vector = new Vector (5, 5);
    }

    十三、将try/catch块移出循环


    把try/catch块放入循环体内,会极大的影响性能,如果编译JIT被关闭或者你所使用的是一个不带JIT的JVM,性能会将下降21%之多!
             
    例子:         
    import java.io.FileInputStream;
    public class TRY {
        void method (FileInputStream fis) {
            for (int i = 0; i < size; i++) {
                try {                                      // violation
                    _sum += fis.read();
                } catch (Exception e) {}
            }
        }
        private int _sum;
    }
             
    更正:         
    将try/catch块移出循环         
        void method (FileInputStream fis) {
            try {
                for (int i = 0; i < size; i++) {
                    _sum += fis.read();
                }
            } catch (Exception e) {}
        }
             
    参考资料:
    Peter Haggar: "Practical Java - Programming Language Guide".
    Addison Wesley, 2000, pp.81 – 83

    十四、对于boolean值,避免不必要的等式判断


    将一个boolean值与一个true比较是一个恒等操作(直接返回该boolean变量的值). 移走对于boolean的不必要操作至少会带来2个好处:
    1)代码执行的更快 (生成的字节码少了5个字节);
    2)代码也会更加干净 。

    例子:
    public class UEQ
    {
        boolean method (String string) {
            return string.endsWith ("a") == true;   // Violation
        }
    }

    更正:
    class UEQ_fixed
    {
        boolean method (String string) {
            return string.endsWith ("a");
        }
    }

    十五、对于常量字符串,用'String' 代替 'StringBuffer'


    常量字符串并不需要动态改变长度。
    例子:
    public class USC {
        String method () {
            StringBuffer s = new StringBuffer ("Hello");
            String t = s + "World!";
            return t;
        }
    }

    更正:
    把StringBuffer换成String,如果确定这个String不会再变的话,这将会减少运行开销提高性能。

    十六、用'StringTokenizer' 代替 'indexOf()' 和'substring()'


    字符串的分析在很多应用中都是常见的。使用indexOf()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。而使用StringTokenizer类来分析字符串则会容易一些,效率也会高一些。

    例子:
    public class UST {
        void parseString(String string) {
            int index = 0;
            while ((index = string.indexOf(".", index)) != -1) {
                System.out.println (string.substring(index, string.length()));
            }
        }
    }

    参考资料:
    Graig Larman, Rhett Guthrie: "Java 2 Performance and Idiom Guide"
    Prentice Hall PTR, ISBN: 0-13-014260-3 pp. 282 – 283

    十七、使用条件操作符替代"if (cond) return; else return;" 结构


    条件操作符更加的简捷
    例子:
    public class IF {
        public int method(boolean isDone) {
            if (isDone) {
                return 0;
            } else {
                return 10;
            }
        }
    }

    更正:
    public class IF {
        public int method(boolean isDone) {
            return (isDone ? 0 : 10);
        }
    }

    十八、使用条件操作符代替"if (cond) a = b; else a = c;" 结构


    例子:
    public class IFAS {
        void method(boolean isTrue) {
            if (isTrue) {
                _value = 0;
            } else {
                _value = 1;
            }
        }
        private int _value = 0;
    }

    更正:
    public class IFAS {
        void method(boolean isTrue) {
            _value = (isTrue ? 0 : 1);       // compact expression.
        }
        private int _value = 0;
    }

    十九、不要在循环体中实例化变量


    在循环体中实例化临时变量将会增加内存消耗

    例子:         
    import java.util.Vector;
    public class LOOP {
        void method (Vector v) {
            for (int i=0;i < v.size();i++) {
                Object o = new Object();
                o = v.elementAt(i);
            }
        }
    }
             
    更正:         
    在循环体外定义变量,并反复使用         
    import java.util.Vector;
    public class LOOP {
        void method (Vector v) {
            Object o;
            for (int i=0;i<v.size();i++) {
                o = v.elementAt(i);
            }
        }
    }

    二十、确定 StringBuffer的容量


    StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

    例子:         
    public class RSBC {
        void method () {
            StringBuffer buffer = new StringBuffer(); // violation
            buffer.append ("hello");
        }
    }
             
    更正:         
    为StringBuffer提供寝大小。         
    public class RSBC {
        void method () {
            StringBuffer buffer = new StringBuffer(MAX);
            buffer.append ("hello");
        }
        private final int MAX = 100;
    }
             
    参考资料:
    Dov Bulka, "Java Performance and Scalability Volume 1: Server-Side Programming
    Techniques" Addison Wesley, ISBN: 0-201-70429-3 p.30 – 31

    二十一、尽可能的使用栈变量


    如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static? local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
             
    例子:
    public class USV {
        void getSum (int[] values) {
            for (int i=0; i < value.length; i++) {
                _sum += value[i];           // violation.
            }
        }
        void getSum2 (int[] values) {
            for (int i=0; i < value.length; i++) {
                _staticSum += value[i];
            }
        }
        private int _sum;
        private static int _staticSum;
    }     
             
    更正:         
    如果可能,请使用局部变量作为你经常访问的变量。
    你可以按下面的方法来修改getSum()方法:         
    void getSum (int[] values) {
        int sum = _sum;  // temporary local variable.
        for (int i=0; i < value.length; i++) {
            sum += value[i];
        }
        _sum = sum;
    }
             
    参考资料:         
    Peter Haggar: "Practical Java - Programming Language Guide".
    Addison Wesley, 2000, pp.122 – 125

    二十二、不要总是使用取反操作符(!)


    取反操作符(!)降低程序的可读性,所以不要总是使用。

    例子:
    public class DUN {
        boolean method (boolean a, boolean b) {
            if (!a)
                return !a;
            else
                return !b;
        }
    }

    更正:
    如果可能不要使用取反操作符(!)

    二十三、与一个接口 进行instanceof操作


    基于接口的设计通常是件好事,因为它允许有不同的实现,而又保持灵活。只要可能,对一个对象进行instanceof操作,以判断它是否某一接口要比是否某一个类要快。

    例子:
    public class INSOF {
        private void method (Object o) {
            if (o instanceof InterfaceBase) { }  // better
            if (o instanceof ClassBase) { }   // worse.
        }
    }

    class ClassBase {}
    interface InterfaceBase {}
  • 软件测试技术还有多少要学?

    2008-11-07 11:16:56

    呢排上网,感觉找的测试资料都不是自己想要的..

    还是自己做测试时间太长时间,觉得测试知识都是太过于理论..

    其实我觉得实践是最好的体验方法,

    前提下,你要有这么一个机会!

    看着每年的毕业大军,我不知道,还可以说什么?

    其实发展教育是好事,但不能重量,不重质!

    或者有时会说得过激,

    会得罪某些人,

    但当你真的想得到一样东西,

    你就会用自己努力换来一个机会,

    机会是有的,

    面包是有的,

    但你只能有那么几个机会,

    生活,真的不能再为钱而工作,

    这不是一件好事!

    好的始终会来的,
    不好的也该来的..
    感叹一声:我还可以做什么?

  • 软件测试的艺术(精华)

    2008-11-04 11:39:53

    软件测试的艺术

    软件测试:
    一个过程或一系列过程,用来确定计算机代码完成了其应该完成的功能,不执行其不该有的操作。
    软件应该是可预测的、稳定的。
    第二章 软件测试的心理学和经济学
    软件测试心理学:
    测试是为了发现错误而执行程序的过程。
    成功的”测试:测试某段程序时发现错误,且该错误可修复或者本次测试可以最终确定再无其他可查出的错误,则被称作“成功的”测试。
    不成功的”测试:未能适当地对程序进行检查或未能找出错误的测试,被称为“不成功的”测试。
    几种错误的观点:
    软件测试就是证明软件不存在错误的过程。此为理想状况。
    软件测试就是证明“软件做了其应该做的”过程。忽略的软件做了不该做的。
    软件测试更适宜被视为试图发现程序中的错误的破坏性的过程。软件做了其应该做的,未做其不应该做的。
    软件测试的经济学:
    黑盒测试:称为数据驱动的测试或输入/输出驱动的测试。与程序的内部机制和结构完全无关。
    重点:发现程序不按其规范正确运行的环境条件。
    此方法若想发现所有的错误,判定标准:“穷举输入测试”。此不可能达到。有两方面含义:一是我们无法测试一个程序以确保它是无错的;二是要考虑软件测试的经济学问题。
    白盒测试:逻辑驱动测试。允许检查程序的内部结构。
    重点:将程序的每一条语句至少执行一次(穷举路径测试)。存在两个问题:
    程序中不同逻辑路径的数量可能达到天文数字;
    即使测试到程序中的所有路径,程序仍然可能存在着错误。此有三个原因:
    1.不能保证程序符合其设计规范:如将升序排列错编成降序排列。
    2.可能会因为缺少某些路径而存在的问题。
    3.可能不会暴露数据敏感错误。
    软件测试的原则:
    1.测试用例中一个必须部分是对预期输出或结果进行定义;
     一个测试用例包括两个部分:
       对程序的输入数据的描述;
    对程序在上述输入数据下的正确输出结果的精确描述。
     2.程序员应当避免测试自己编写的程序;
     3.编写软件的组织不应当测试自己编写的软件;
     4.应当彻底检查每一个测试的执行结果;
     5、测试用例的编写不仅应当根据有效和预料到的输入情况,而且也应当根据无效和未料到的输入情况;
     6.检查程序是否“未做其应该做的”和“做了其不应该做的”;
     7.应避免测试用例用后即弃,除非软件本身是一次性软件;
    保留测试用例,当程序其他部件发生更动后重新执行,就是所谓的“回归测试”。在人机交互方式的测试下,尤其会忽略这一问题。
     8.计划测试工作时不应默许假定不会发现错误;
     9、程序某部分存在更多错误的可能性,与该部分已发现错误的数量成正比;
      测试总是倾向于聚集存在,故对容易存在错误的部分进行额外的测试。
     10.软件测试是一项极富创造性、极具智力挑战性的工作。
    总结:三个重要的测试原则:
     软件测试是为发现错误而执行程序的过程。
     一个好的测试用例具有较高的发现某个尚未发现的错误的可能性。
     一个成功的测试用例能够发现某个尚未发现的错误。
    第三章、代码检查、走查与评审
    今天,并不是所有的软件测试人员都要阅读代码,但研读程序代码是测试工作的一部分。
    “人工测试”:开始于代码编码之后,基于计算机的测试开始之前使用的方法。是查找错误方面非常有效。其原因:
     错误发现越早,改正成本越低;
     程序员改正基于计算机发现的错误所犯的失误,要比改正早期发现的问题所犯的失误要更多。代码检查与走查:
    两种重要的人工测试方法。
    他们的共同点:要求人们组成一个小组来阅读或直观检查特定的程序。“头脑风暴会”
    优点:一旦发现错误,就能在代码中精确定位,降低调试成本。查出30%~70%的逻辑设计和编码错误。
    缺点:往往只能发现一些“简单”的错误。
    因此代码检查/走查与基于计算机的测试是互补关系。
    代码检查:
      以组为单位阅读代码,它是一系列规程和错误检查技术的集合。重点:在规程、所要填写的表格。
      一个代码检查小组由四人组成:
    一人发挥协调作用(称职的程序员):相当于质量控制工程师。无需对程序的细节很清楚;为代码检查分发材料,安排进程;在代码检查中起主导作用;记录发现的所有错误;确保所有错误随后得到改正。
    代码检查有两项工作:
     程序编码人员逐条语句讲述程序的逻辑结构。
     对者历来常见的编码错误列表分析程序。
    代码检查的优点:
     发现错误;
     程序员会得到编程风格、算法选择及编程技术等方面的反馈信息。
     早期发现程序中最易出错部分的方法之一。
    用于代码检查的错误列表:
      代码检查过程的重要部分:就是对照一份错误列表,来检查程序是否存在常见的错误。
    1. 数据引用错误
    是否引用的变量未赋值或未初始化?
    所有的数组引用,是否每一个下标的值都有相应维规定的界限之内?
    所有的数组引用,是否每一个下标的值都是整数?
    对所有的通过指针或引用变量的引用,当前引用的内存单元是否分配?即“虚调用”。
    如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性?
    变量的类型或属性是否与编译器所预期的一致?
    在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接的寻址错误?
    当使用指针或引用变量时,被引用的内存的属性是否与编译器所预期的一致?
    假如一个数据结构在多个过程或子程序中被引用,那么每个过程或子程序对该结构的定义是否都相同?
    如果字符串有索引,当对数组进行索引操作或下标引用,字符串的边界取值是否有“仅差一个”(off-by-one)的错误?
    对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?
    2. 数据声明错误
    是否所有的变量都进行了明确的声明?
    如果变量所有的属性在声明中没有明确说明,那么默认的属性能否被正确理解?
    如果变量在声明语句中被初始化,那么它的初始化是否正确?
    是否每个变量都被赋予了正确的长度和数据类型?
    变量的初始化是否与其存储空间的类型一致?
    是否存在着相似名称的变量?
    3. 运算错误
    是否存在不一致的数据类型的变量间运算?
    是否有混合模式的运算?
    是否有相同数据类型,不同字长变量间的运算?
    赋值语句的目标变量的数据类型是否小于右边表达式的数据类型或结果?
    在表达式的运算中是否存在表达式向上或向下溢出的情况?
    除法运算中的除数是否可能为0?
    如果计算机表达变量的基本方式是基于二进制的,那么运算结果是否不精确?
    在特定场合,变量的值是否超过了有意义的范围?
    对于包含一个以上操作符的表达式,赋值顺序和操作符的优先顺序是否正确?
    整数的运算是否有使用不当的情况,尤其是除法?如:2*i/2==i ?
    4. 比较错误
    是否有不同数据类型的变量之间的比较运算?
    是否有混合模式的比较运算,或不同长度的变量间的比较运算?
    比较运算符是否正确?
    每个布尔表达式所叙述的内容是否都正确?
    布尔运算符的操作数是否是布尔类型的?比较运算符和布尔运算符是否错误地混在一起了?
    在二进制的计算机上,是否有用二进制表示的小数或浮点数的比较运算?
    对于那些包含一个以上布尔运算的表达式,赋值顺序以及运算符的优先顺序是否正确?
    编译器计算布尔表达式的方式是否会对程序产生影响?
    5. 控制流程错误
    如果程序包含多条分支路径,索引变量的值是否会大于可能的分支数量?
    是否所有的循环最终都终止了?
    程序、模块或子程序是否最终都终止了?
    由于实际情况没有满足循环的入口条件,循环体是否有可能从未执行过?
    如果循环同时由迭代变量和一个布尔条件所控制,如果循环越界了,后果会如何?
    是否存在“仅差一个”的错误,如迭代数量恰恰多一次或少一次?
    如果编程语言中有语句组或代码块的概念,是否每一组语句都有一个明确的while语句,并且do语句也与其相应的语句组对应?
    是否存在不能穷尽的判断?
    6. 接口错误
    被调用模块接收到的形参数量是否等于调用模块发送的实参数量?另外,顺序是否正确?
    实参的属性是否与相应形参的属性相匹配?
    实参的量纲是否与对应形参的量纲相匹配?
    此模块传递给彼模块的实参数量,是否等于彼模块期望的形参数量?
    此模块传递给彼模块的实参的属性,是否与彼模块相应形参的属性相匹配?
    此模块传递给彼模块的实参的量纲,是否与彼模块相应形参的量纲相匹配?
    如果调用了内置函数,实参的数量、属性、顺序是否正确?
    如果一个模块或类有多个入口点,是否引用了与当前入口点无关的形参?
    是否有子程序改变了某个原本仅为输入值的形参?
    如果存在全局变量,在所有引用它们的模块中,它们的定义和属性是否相同?
    常数是否以实参形式传递过?
    7. 输入/ 输出错误
    如果对文件明确声明过,其属性是否正确?
    打开文件的语句中各项属性的设置是否正确?
    格式规范是否与I/O语句中的信息相吻合?
    是否有足够的可用内存空间,来保留程序将读取的文件?
    是否所有的文件在使用之前都打开了?
    是否所有的文件在使用之后都关闭了?
    是否判断文件结束的条件,并正确处理?
    对I/O出错情况处理是否正确?
    任何打印或显示的文本信息中是否存在拼写或语法错误?
    8. 其他检查
    如果编译器建立了一个标识符交叉引用列表,那么对该列表进行检查,查看是否有变量从未引用过,或仅被引用过一次?
    如果编译器建立了一个属性列表,那么对每一个变量的属性进行检查,确保没有赋予过不希望的默认属性值?
    如果程序编译通过了,但计算机提供了一个或多个“警告”或“提示”信息,应对此逐一进行认真检查。“警告”:编译器对程序某些操作的正确性有所怀疑。“提示”:可能会列出没有声明的变量,或者是不利于代码优化的用法。
    程序或模块是否具有足够的鲁棒性?即:它是否对其输入的合法性进行了检查?
    程序是否遗漏了某一功能?
    代码走查:
      代码检查和代码走查采用的错误检查技术不同,操作规程也有所不同。
      代码走查参与者:一个极富经验的程序员、一个程序设计语言专家、一个程序员新手、最终将维护程序的人员、一个来自其他不同项目的人员、一个来自该软件编程小组的程序员。
    桌面检查:
      桌面检查是人工查找错误的第三种过程。由单人进行的代码检查或代码走查:由一个人阅读程序,对照错误列表检查程序,对程序推演测试数据。
      效率相当低。
    同行评分:
      这种人工评审方法与程序测试并无关系,但与代码阅读的思想有关。
    总结:
      开发人员通常不会考虑的一种测试形式:人工测试。主要方法:
       利用错误列表进行代码走查;
       小组代码走查;
       桌面检查;
       同行评审。
    第四章、测试用例的设计
    软件测试最重要的因素是设计和生成有效的测试用例。
    由于时间和成本的约束,软件测试的最关键问题是:在所有可能的测试用例中,哪个子集最有可能发现最多的错误?
     随机输入测试:效率最低。
     黑盒测试方法:等价类划分、边界值分析、因果图分析、错误猜测
     白盒测试方法:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、多重条件覆盖。
    实际工作中,推荐先使用黑盒测试方法,然后视情况需要使用白盒测试方法。
    白盒测试:
      关注测试用例执行的程度或覆盖程序逻辑结构(源代码)的程度。
      逻辑覆盖测试:
       语句覆盖:有很大的不足,以至于它通常没有什么用处。
    判定覆盖或分支覆盖:较强一些的逻辑覆盖准则。要求编写足够的测试用例,使得每一个判断都至少有一个为真或为假的输出结果。
    判断覆盖通常可以满足语句覆盖。但有三种情况例外:
     程序中不存在判断。
     程序或子程序/方法有多重入口点。
     在ON单元里的语句。
    条件覆盖:比判断覆盖更强的准则。要求编写足够的测试用例确保将一个判断中的每一条件的所有可能的结果至少执行一次。包括ON单元的每一个入口点都至少调用一次。条件覆盖会使判断中的各个条件都取到两个结果“真”和“假”。
    判定/条件覆盖准则:要求设计出足够的测试用例,将一个判断中的每个条件的所有可能的结果至少执行一次,将每个判断的所有可能的结果至少执行一次,将每个入口点都至少调用一次。
     缺点:由于有些特定的条件会屏蔽掉其他条件,常常并不能全部都执行到。
    多重条件覆盖:要求编写足够的测试用例,将每个判定中的所有可能的条件结果的组合,以及所有的入口点都至少执行一次。
    显然,满足多重条件覆盖,就满足了判定覆盖或分支覆盖、条件覆盖、判定/条件覆盖准则。
    而且,在存在循环的情况下,多重条件覆盖所需要的测试用例的数量通常会远远小于其路径的数量。
    总之,对包含每个判断只存在一种条件的程序,最简单的测试准则就是设计出足够数量的测试用例:
    1、 将每个判断的所有结果都至少执行一次;
    2、 将所有的程序入口都至少调用一次;
    而对于包含多重条件判断的程序,则要求设计足够的测试用例,将每个判断所有可能的条件结果组合,以及所有的入口点都至少执行一次。
    等价划分
     精心挑选的测试用例应具备两个特性:
    1、严格控制测试用例的增加,减少为达到“合理测试”的某些即定目标而必须设计的其他测试用例的数量。即:使用较少的测试用例,体现尽可能多的不同的输入情况。
    2、它覆盖了大部分其他可能的测试用例。尽量将程序的输入范围进行划分,划分为有限数量的等价类。
     等价类划分方法设计测试用例有两个步骤:
    1、 确定等价类:
    有效等价类:代表对程序有效的输入;
    无效等价类:代表其他任何可能的不正确的输入条件。
    确定等价类的指导原则:
    a. 如果输入条件规定了一个取值范围,则应确定一个有效等价类,两个无效等价类。
    b. 如果输入条件规定取值的个数,那么应确定出一个有效等价类和两个无效等价类。
    c. 如果输入条件规定一个输入值的集合,而且有理由认为程序会对每个值进行不同的处理,那么应确定一个有效等价类和一个无效等价类。
    d. 如果樽俎输入条件规定了“必须是”的情况,那么应确定一个有效等价类和一个无效等价类。
    2、 生成测试用例。
    使用等价类来生成测试用例。其过程:
    a、 为每个等价类设置一个不同的编号;
    b、 编写新的测试用例,尽可能多地覆盖那些尚未被涵盖的有效等价类,直到所有的有效等价类都被测试用例所覆盖。
    c、 编写新的用例,覆盖一个且仅一个尚未被涵盖的无效等价类,直到所有的无效等价类都被测试用例所覆盖。
    边界值分析
     边界条件:是指输入和输出等价类中那些恰好处于边界、或超过边界、或在边界以下的状态。
     边界值分析方法与等价划分方法的不同点:
    1、与从等价类中挑选出任意一个元素作为代表不同,边界值分析需要选择一个或多个元素,以便等价类的每一个边界都经过一次测试;
    2、与仅仅关注输入条件不同,还需要考虑从结果空间设计测试用例。
     设计边界值分析方法的测试用例的一些通用指南:
    1、如果输入条件规定了一个输入值范围,那么应针对范围的边界设计测试用例,针对刚刚越界的情况设计无效输入测试用例。
    2、如果输入条件规定了 输入值的数量,那么应针对最小数量输入值、最多数量输入值、以及比最小数量少一个,比最大数量多一个的情况设计测试用例。
    3、对每个输出条件应用指南1,还要注意检查结果空间的边界,因为输入的边界并不代表是输出的边界。
    4、对每个输出条件应用指南2。
    5、如果程序的输入或输出是一个有序序列,则应特别注意该序列的第一个和最后一个元素。
    6、此外,还要发挥聪明才智找出其他的边界条件。
     边界值分析方法和等价划分之间的重要区别:边界值分析考察正处于等价划分边界或边界附近的状态。
     边界值分析方法常常使用得不好,因为边界条件可能非常微妙,常常很难确定。
    因果图
     边界值分析和等价划分的一个弱点:未对输入条件的组合进行分析。
     因果图有助于用一个系统的方法选择出高效的测试用例集,而且还可以指出规格说明的不完整性和不明确之处。其生成测试用例的过程如下:
      1、将规格说明分解为可执行的片段。
    2、确定规格说明中的因果关系。“因”:一个明确的输入条件或输入条件的等价类。“果”:指一个输出条件或系统转换。一旦因果关系被确定下来,每个“因”和“果”都被赋予一个唯一的编号。
    3、分析规格说明的语义内容,并将其转换为连接因果关系的布尔图。
    4、给图加上注解符合,说明由于语法或环境的限制而不能联系起来的“因”和“果”。
    5、通过仔细地跟踪图中的状态变化情况,将因果图转换成一个有限项的判定表,表中的每一列代表一个测试用例。
    6、将判定表指的列转换为测试用例。
     因果图方法是一个根据条件的组合而生成测试用例的系统性的方法。它确实能产生一组有效的测试用例,但通常它不能生成全部应该被确定的有效测试用例。而且也没有充分考虑边界条件。因果图可以考虑边界条件,但这会导致因果图急剧复杂化,因此最好单独考虑边界值分析。
     因果图方法难点在于:将因果图转化为判定表。
    错误猜测
     错误猜测是一项依赖于直觉的非正规的过程,因此很难描述出这种方法的规程。其基本思想:列举出可能犯的错误或错误易发情况的清单,然后依据清单来编写测试用例,检查特定的输入值中有0,或特定的输出值被强制为0的情况。另一思想:在阅读规格说明时联系程序员可能做的假设来确定测试用例。
    测试策略
     因为每一种测试方法可提供一组有用的测试用例,但不能单独提供一个完整的测试用例集,因此采用测试策略来合理组合。一组合理的策略如下:
      1、如果规格说明中包含输入条件组合的情况,应首先使用因果图分析法。
      2、在任何情况下都应该使用边界值分析方法。
      3、应为输入和输出确定有效和无效等价类。
      4、使用错误猜测技术增加更多的测试用例。
    5、针对上述测试用例集检查程序的逻辑结构。使用判定覆盖、条件覆盖、判定/条件覆盖或多重条件覆盖准则。
     上述策略并不能保证可发现所有的错误,但实践证明是一个合理的折中方案。
    第五章、模块(单元)测试
    模块测试(单元测试):是对程序中的单个子程序、或过程进行测试的过程。
    这样做有三个动机:
     1、它是一种管理组合的测试元素的手段。
     2、模块测试减轻了调试的难度,利于错误定位。
     3、模块测试通过为我们提供同时测试多个模块的可能,可将并行工程引入软件测试中。
    模块测试的目的:将模块的功能与定义模块的规格说明或接口规格说明进行比较。测试是为了揭示出模块与其规格说明存在着矛盾。
    模块测试包括三个方面:
     1、测试用例的设计方式。
     2、模块测试及集成的顺序。
     3、对执行模块测试的建议。
    测试用例设计
       需要使用两种类型的信息:模块的规格说明、模块的源代码。
       模块的规格说明:规定了模块的输入和输出参数以及模块的功能。
       模块测试方法:面向白盒测试。
    模块测试的测试用例设计过程:使用一种或多种白盒测试方法分析模块的逻辑结构,然后使用黑盒测试方法对照模块的规格说明以补充测试用例。
    说明:多重条件覆盖准则要优于其他准则,任何逻辑覆盖准则尚不足以胜任作为生成模块测试用例的唯一手段。
    增量测试
     在执行模块测试过程中,要考虑两点:
        1、如何设计一个有效的测试用例集。
        2、将模块组装成工作程序的方式。包括增量测试和非增量测试。
       两种增量测试策略:自顶向下的和自底向上的开发和测试过程。
    非增量测试(崩溃(big-bang)测试):先独立地测试每个模块,然后再将这些模块组装成完整的程序进行测试。
    增量测试(集成):先将下一步要测试的模块装到测试完成的模块集合中,然后再进行测试。
    测试单独的模块需要一个特殊的驱动模块(driver module)和一个或多个桩模块(stub module)
    结论:
      1、非增量测试工作量更多一些,而增量测试工作量少一些。
    2、若使用增量测试,可较早地发现模块中与不匹配接口,不正确假设相关的编程错误。而非增量测试只能到最后的组装测试才能看到。
    3、若使用增量测试,调试会更容易进行,更利于错误定位。
    4、增量测试会将测试进行得更彻底。
    5、非增量测试所占用的机器时间显得少一些。但需要更多的驱动模块和桩模块。
    6、模块测试开始阶段,若使用非增量测试,会有更多的机会进行并行操作。
    总之,增量测试相对更好一些。
    自顶向下测试和与自底向上测试
     “自顶向下的测试”、“自顶向下的开发”、“自顶向下的设计”:前两者是同义词,但“自顶向下的设计”是一个独立的概念,其可采用自底向上的方式进行增量测试。
     自底向上的测试常常会被错误地当作非增量测试。
     自顶向下的测试:
      从程序的顶部或初始模块开始测试。
    增量的唯一准则:要成为合乎条件的下一个模块,至少一个该模块的从属模块(调用它的模块)事先经过了测试。
    要点:桩模块的编写、采用什么样的形式将测试用例提交给程序。
    采用什么样的形式将测试用例提交给程序:测试数据是通过其一个或多个桩模块提交给模块的。如果被测模块仅仅调用桩模块一次,则需要编写多个桩模块版本,以此来提交多个测试用例。
    增量的指南:
     1、如果程序中存在关键部分,则关键部分应尽早添加进去。
     2、在设计模块序列时,应将I/O模块尽可能早的添加进来。
    自顶向下策略的缺陷:略。
     自底向上的测试:
      开始于程序中的终端模块。
    增量的唯一准则:要成为合乎条件的下一个模块,该模块的所有从属模块(它调用的模块)事先经过了测试。
    要点:驱动模块的编写。
    驱动模块编写:包含有效的测试输入、调用被测模块且将输出显示出来的模块。无需编写多个版本。
    增量的指南:
     如果程序中存在关键部分,则关键部分应尽早添加进去。
    不足:没有早期程序框架的优点。
    比较:
    增量测试策略 优点 缺点
    自顶向下 1、如果主要的缺陷发生在程序的顶层将非常有利。
    2、一旦引入I/O功能,提交测试用例会更容易。
    3、早期的程序框架可以进行演示,并可激发积极性。 1、必须开发桩模块。
    2、桩模块要比最初表现的更复杂。
    3、在引入I/O功能之前,向桩模块中引入测试用例比较困难。
    4、创建测试环境可能很难,甚至无法实现。
    5、观察测试输出很困难。
    6、使人误解设计和测试可以交迭进行。
    7、会导致特定模块测试的完成延后。
    自底向上 1、如果主要的缺陷发生在程序的底层将非常有利。
    2、测试环境比较容易建立。
    3、观察测试输出比较容易。 1、必须开发驱动模块
    2、直到最后一个模块添加进去,程序才形成一个整体。
    执行测试
    当测试用例造成模块输出的实际结果与预期结果不匹配的情况时,存在两个可能的解释:模块错误 or 预期的结果错误(测试用例不正确)。因此应对测试用例进行测试。
    自动化测试工具:可以降低对驱动模块的需求;流程分析工具可以列举出程序中的路径,找出从未被执行的语句。
    对预期输出进行定义是测试用例必不可少的部分。
    执行测试时,应该查找程序的副作用(不该执行的操作)。
    第六章、更高级别的测试
    当程序无法实现其最终用户要求的合理功能时,就发生了一个软件错误。
      软件开发过程在很大程度上是沟通有关最终程序的信息、并将信息从一种形式转换到另一种形式。因此,绝大部分软件错误都可以归因为信息沟通和转换时发生的故障、差错和干扰。
      模块测试:发现程序模块与其接口规格说明之间的不一致。
      功能测试:为了证明程序未能符合其外部规格说明。
      系统测试:为了证明软件产品与其初始目标不一致。
      
    集成测试:并不作为一个独立的测试步骤,而且在进行增量模块测试时,它是模块测试的隐含部分。
    功能测试:
      一个试图发现程序与其外部规格说明之间存在不一致的过程。
      外部规格说明:一份从最终用户的角度对程序行为的精确描述。
      功能测试属黑盒测试。对外部规格说明进行分析以获取测试用例集。方法:等价类划分、边界值分析、因果图分析、错误猜测。
    系统测试:
      最容易被错误理解,也是最困难的测试过程。并非是测试整个系统或程序功能的过程。而是将系统或程序与其初始目标进行比较。
      系统测试并不局限于系统,它是一个试图说明程序作为一个整体是如何不满足其目标的过程。如果产品没有一组书面的、可度量的目标,系统测试就无法进行。注意:不是与外部规格说明进行比较。
      系统测试有两个方面的作用:将程序与其目标和用户文档相比较、将用户文档与程序目标相比较。
    能力测试:
       判断目标文档提及的每一项能力是否都确实已经实现。
      容量测试:
       为了证明程序不能处理目标文档中规定的数据容量。
      强度测试:
    使程序承受高负载或强度的检验。即在很短的时间间隔内达到的数据或操作的数量峰值。
    易用性测试:
      1、每个用户界面是否都根据最终用户的智力、教育背景和环境要求而进行了调整?
      2、程序的输出是否有意义、不模糊且没有计算机的杂乱信息?
      3、错误诊断是否直接,用户是否需要有一定的经历才能理解它?
    4、整体的用户界面是否在语法、惯例、语义、格式、风格和缩写方面展现出了相当程度的概念完整性、基本的一致性和统一性?
      5、在准确性极为重要的环境里,输入中是否有足够的冗余信息?
      6、系统是否包含过多或不太可能用到的选项?
      7、对于所有的输入,系统是否返回了某些类型的即时确认信息?
      8、程序是否易于使用?
    安全性测试:
      设计测试用例来突破程序安全检查的过程。
    性能测试:
      在特定负载和配置环境下程序的响应。
    存储测试:
      设计测试用例来证明程序使用的内存和辅存的容量、以及临时文件或溢出文件的大小。
    配置测试:
    至少应该使用每一种类型的设备,以最大和最小的配置来测试程序。如软件本身的配置可忽略掉某些组件;运行在不同的操作系统、使用不同的Web浏览器等。
    兼容性/配置/转换测试:
      证明兼容性目标未被满足,转换过程并未生效。尤其是数据库升级。
    安装测试:
       是系统测试的一个重要部分。对自动安装系统而言,尤为重要。
       可靠性测试:
       测试软件或系统的平均故障间隔时间(MIBF)目标或合理的功能错误目标。
       可恢复性测试:
    如操作系统、数据库管理系统和远程处理系统等软件通常都有可恢复性目标,说明系统如何从程序错误、硬件失效和数据错误中恢复过来。系统测试的目标就是证明这些恢复机制不能够发挥作用。使平均恢复时间(MTTR)最小。
    适应性测试:
     软件可能有适应性或可维护性的目标。这些目标可能定义了系统提供的服务辅助功能,包括存储转存程序或诊断程序、调试明显问题的平均时间、维护过程以及内部业务文档的质量等。
    文档测试:
     需要检查用户文档的正确性。
    过程测试:
     必须对所有已规定的人工的操作过程进行测试。
    系统测试的执行:
     系统测试的关键是决定由谁来进行测试。唯一一个不能由开发机构来执行的测试。
    测试工作小组:几位系统测试专家、一位最终用户代表、一位人类工程学工程师、系统的设计者。
    验收测试:
    通常由程序的客户或最终用户来进行。不是软件开发机构的职责。将程序的实际操作与原始合同进行对照。验收测试最好的方法是设计测试用例,尽力证明程序没有满足合同的要求。
    安装测试:
     为了发现在安装过程中出现的错误。
      1.用户必须选择大量的选项。
      2.必须分配并加载文件和库。
      3.必须进行有效的硬件配置。
      4.软件可能要求网络连通,以便与其他软件连接。
    此外测试用例还要检查以确认已选的选项集合互不冲突。系统的所有部件全部存在,所有的文件已经创建并包含必须内容、硬件配置妥当等。
    测试的计划与控制:
     一个良好的测试计划包括:
       目标:定义每个测试阶段的目标。
       结束准则:规定每个测试阶段何时可以结束。
       进度:每个阶段的时间表。
       责任:每个阶段,应确定谁设计、编写和验证测试用例,谁来修改发现的软件错误。
      测试用例库及标准:用于确定、编写以及存储测试用例的系统方法。
       工具:需使用的测试工具。
       计算机时间:计划每个测试阶段所需的计算机时间。
       硬件配置:如何满足需求及何时满足。
      集成:定义程序如何组装在一起的方法。即:系统集成计划。
    跟踪步骤:跟踪测试进行中的方方面面,包括错误易发模块的定位,以及有关进度、资源和结束准则的进展评估。
    调试步骤:制定上报已发现错误、跟踪错误修改进程以及将修改部分加入系统中去的机制。
    回归测试:对程序作了功能改进或进行了修改后进行,其目的是判断程序的改动是否引起了程序其他方面的退步。通常重新执行测试用例中的某些子集。
    测试结束准则:
    软件测试过程中最难回答的一个问题。
    最常见的两个准则:
     1、用完了安排的测试时间后,测试便结束。
     2、当执行完所有测试用例都未发现错误,测试便结束。
    另外三类有用的准则:
     1、根据特定的测试用例设计技术。如:
    测试用例来源于:满足多重条件覆盖准则、及对模块接口规格说明进行边界值分析,所有测试用例都不成功。
    测试用例来源于:因果图分析、边界值分析、错误猜测,所有测试用例都不成功。
    存在三个问题:对那些无特定方法测试阶段无效;要依赖于主观度量;不同于设置一个目标再让测试人员选择最佳的实现方法。
     2、以确切的数量来描述结束测试的条件。
    强化了软件测试的定义。但存在两个问题:如何获得要发现的错误数量;利用以前程序的经验来预测出数字。
    独立的测试机构:
     雇用独立的公司进行软件测试。
    第七章、调试
    调试有两个步骤:
       1、错误定位;
       2、修改错误。
      虽然调试必不可少,但不受程序员欢迎,其原因:
       1、个人自尊会从中阻扰。
       2、热情耗尽。
       3、可能会迷失方向。
       4、必须自力更生。
    暴力法调试:
      可划分为三类:
       1、利用内存信息输出来调试。
        是最缺乏效率的调试,原因:
         难以在内存区域与源程序中的变量之间建立对应关系。
         即使对于复杂度较低的程序,内存信息输出会产生数量庞大的数据,大多与调试无关。
         内存信息输出显示的是程序的静态快照,无程序的动态状态。
    内存信息输出很少可以精确地在错误发生的地方产生,无法显示错误发生时程序状态。
    通过分析输出的内存信息来发现问题的方法并不太多。
       2、根据一般的“在程序中插入打印语句”建议来调试。
        比内存信息输出要好一些,但仍有很多缺点:
         不是鼓励我们去思考程序中的问题,而主要是一种碰运气的方法。
         它所产生的需要分析的数据量非常庞大。
    它要求我们修改程序,这些修改可能会掩盖错误、改变关键的时序关系或引入新的错误。
    它可能对小型程序有效。对大型程序,成本就相当高。而且对某些程序无法使用。
    3、 使用自动化的调试工具进行调试。
    其工作机制类似于在程序中插入打印语句,但并不修改程序本身。
    调试工具可设断点。
    暴力调试法的问题:忽略了思考过程。建议在其他的方法都失效的情况下,作为我们思考过程的补充,而不是替代方法。
    归纳法调试:
     步骤:
      1、确定相关数据。主要错误是未能将所有可用的数据或症状都考虑进来。
      2、组织数据。
      3、作出假设。研究线索之间的关系,利用线索结构作出关于错误原因的假设。
      4、证明假设。
    演绎法调试:
      步骤:
       1、列出所有可能的原因或假设。
       2、利用数据排除可能的原因。
       3、提炼剩下的假设。
       4、证明剩下的假设。
    回溯法调试:
      在小型程序中定位错误的一种有效的方法是沿着程序的逻辑结构回溯不正确的结果,直到找出程序逻辑出错的位置。
    测试法调试:
      使用测试用例来调试,目的是提供有用的信息,供定位某个被怀疑的错误之用。
      此处测试用例与供测试使用的测试用例存在区别:供测试的测试用例“胖”;而供调试的测试用例“瘦”。
    调试的原则:
      定位错误的原则:
       1、动脑筋:对错误症状的有关信息进行分析。
       2、如果遇到了僵局,就留到稍后解决。
       3、如果遇到了困境,就把问题描述给其他人听。
       4、仅将测试工具作为第二种手段
       5、避免使用试验法-仅将其作为最后的手段。
      修改错误的技术:
       1、存在一个缺陷的地方,很可能还存在其他缺陷。
       2、应纠正错误本身,而不仅是其症状。
       3、正确纠正错误的可能性并非100%
       4、正确修改错误的可能性随着程序规模的增加而降低。
       5、应意识改正错误会引入新错误的可能性。
       6、修改错误的过程也是临时回到设计阶段的过程。
       7、应修改源代码,而不是目标代码。
    错误分析
      调试可以告诉我们软件错误的本质,关于软件错误本质的信息可以为改进将来的设计、编码和测试过程提供有价值的反馈信息。
      错误出现在什么地方?需回溯研究程序文档和项目的历史。是最有价值的问题。
      谁制造了这个错误?
      哪些做得不正确?准确地判断出错误发生的原因。
      如何避免该错误的出现?
      为什么错误没有早些发现?
      该如何更早的发现错误?
    第八章、极限测试
    XP的开发方法的目的是在短时间内开发高质量的程序。XP模型高度依赖模块的单元和验收测试。这种形式的测试被称为极限测试(XT)。
    极限编程基础
      XP与传统的开发过程相比有不同之处:
    XP避免了大规模项目的综合症。XP的策划阶段将重点放在收集应用程序需求,而不是设计程序上。
    XP避免了编写不需要的功能。
    XP方法将精力集中在测试上。传统开发模型建议先编码,然后才生成测试接口;而XP首先生成单元测试用例,然后才编写代码通过测试。
    XP的12个核心实践可归纳为:
     1、聆听客户和其他程序员的谈话。
     2、与客户合作,开发应用程序的规格说明和测试用例。
     3、结对编码。
     4、测试代码库。
    XP有两个重要的原则:
     计划:XP的计划阶段与传统开发模型不同,通常将需求收集与应用设计结合起来。XP的计划重点是确定客户的应用需求,然后设计使用场景来满足客户的应用需求。通过生成使用场景,可以深入洞悉应用程序的目的和需求。此外,在验收测试中也可用到这些场景。
     极限编程的12个实践:
    实践 注释
    1、计划与需求分析 a将市场和业务开发人员集中起来,共同确认每个软件特征的最大商业价值。
    b 以使用场景的形式重新编写每个重要的软件特征
    c程序员估计完成每个使用场景的时间
    d 客户根据估计时间和商业价值选择软件的功能特征
    2、小规模、递增地发布 努力增加细微的、实在的、可增值的特征、频繁发布新版本
    3、系统隐喻 编程小组确认隐喻,便于建立命名规则和程序流程
    4、简要设计 实现最简单的设计,使代码通过单元测试。假设变更即将发生,因此不要在设计上花太多时间,只是不停的实现。
    5、连续测试 在编写模块之前就生成单元测试用例。模块只有通过单元测试之后才告完成。程序只有在通过所有的单元测试和验收测试之后才算完成。
    6、重构 清理和调整代码库,单元测试有助于确保在此过程中不破坏程序的功能。应在任何重构之后重新进行所有的单元测试。
    7、结对编程 两个程序员协同工作,在同一台机器开发代码库。可使代码进行实时检查,能极大地提高缺陷的发现率和纠正率。
    8、代码的集体所有权 所有代码归全体程序员所有,没有哪一个程序员只致力于开发某一个代码库。
    9、持续集成 每天在变更通过单元测试之后将其集成到代码库中。
    10、每周工作40小时 不允许加班。重大发布前一个星期例外。
    11、客户在现场 开发人员和编程小组可以随时接触客户,这样可快速、准确地解决问题,使开发不致于中断。
    12、按标准编码 所有的代码看上去必须一致。设计一个系统隐喻有助于满足该原则。
    XP方法目前不太接受。
    极限测试:概念
      极限测试方法强调连续测试。由单元测试和验收测试组成。目标都是确定程序中的错误。
      极限单元测试
       主要测试方法。有两个简单规则:
    所有代码模块在编码开始之前必须设计好单元测试用例。
    在产品发布之前必须通过单元测试。
     极限测试的单元测试与前面的单元测试的最大差别:极限测试中的单元测试必须在模块编码之前就设计和生成。
     在编码之前设计单元测试的好处:
      1、获得了代码将满足其规格说明的信心
      2、在开始编码之前,就展示了代码的最终结果
      3、更好地理解了应用程序的规格说明和需求
    4、可以先实现一些简单的设计,稍后再放心地重构代码以改善程序的性能,而无需担心破坏应用程序的规格说明。
     以上优点对获得对应用程序规格说明和需求的洞察和理解不应被低估。
      验收测试
       目的是判断应用程序是否满足如功能性和易用性等其他需求。
    极限测试的应用
      极限测试要求使用一个独立的黑盒测试方法,消除所有的偏见。
      测试用例设计(略)
      测试驱动器及其应用(略)
     小结
      极限编程:轻量级的开发过程,强调:沟通、计划和测试。
      极限测试重点:单元测试和验收测试。
      极限测试要求开始于程序编码之前,根据程序的规格说明设计测试配件。
    第九章、测试因特网应用系统
      因特网本质为C/S 结构。客户端:Web浏览器;服务器端:Web或应用服务器。
    电子商务的基本结构
      
      三层结构:
       第一层:Web服务器,又称“表示层”
       第二层:“业务层”,运行应用服务器。相关功能:
        1、事务处理
        2、用户身份鉴定
        3、数据确认
        4、程序日志
       第三层:“数据层”,从数据源(一个关系数据库管理系统RDBMS)中存储和获取数据。
    测试的挑战
      测试基于因特网的应用系统所遇到的挑战:
       1、用户群庞大且五花八门:
       2、业务环境
    3、测试环境
    4、地点
    5、安全性
    6、浏览器的兼容性
    7、网络连通性
    测试的策略(略)
      表示层的测试
      业务层的测试
      数据层的测试


     

  • 软件要不要系统正规测试(转载)

    2008-11-04 11:30:43

    这里讲的测试是指 通过系统的 正规的方法进行测试 如 软件黑盒,白盒测试。

        但其实国内很多软件被测试过的定义就是 有开发人员或者2-3个专门测试的员坐在板凳上,把软件从头到尾点一遍看看是否有错误。并且说“只要用户很难发现错误,就算测试通过了”。

        不过话说到头。软件测试的目的还只能是“只要用户很难发现错误,就算测试通过了”,任何一个公司的产品都不能保证绝对没有错误。

        我这里不是要讲测试的方法或者系统性的讨论。我是说我们是否要对所有 产品进行正规系统性测试呢。

        分以下几种情况

        1. 如果你是做 高端产品的。如开发工具,操作系统,浏览器。这个无可厚非。你不系统测试。晚上会被人套上麻袋痛打。

        2. 如果是应用软件。则 又要分2种情况。 银行或者政府软件。也是要系统性测试的。企业应用软件,如果是ERP那种,你不系统测试后果更惨。如果是小企业用的辅助软件,网站 ,如OA ,那么 很多IT公司都是由几个人进行点击测试就完了。因为老板一下子告诉你有5个项目这个月要交付给客户,换作是你 你会怎么办。

        3。做游戏软件 --- 根本不需要大测试,可以边公厕(公测),边开发,这叫发动网民一起来加班,并且不付工资。(开个玩笑。其实游戏软件的测试还是很系统性的。技术含量也是很高的。)

        4。搞互联网。 一般这样的人是经营网站。不卖。从理论上讲。自己搞互联网 。那网站抛头露面的机会多更应该系统的测试。其实不然。如果你是一个大型门户,你从开发到栏目推出可能只有5个小时。你还测试个啥。技术人员自己点点就可以了。出错了大不了自动转向到一个友好的界面上。

        5。自己接的私单。 我有个朋友就常接私单。他说单子量少的时候。也测试 不过也是自己点点。单子多的时候 根本不测试。运行一下,正常机子不死机就可以了。

        网友看了自己应该心里清楚了。软件到底要不要系统测试了。国情很重要,识实务者为俊杰。同时也要体谅辛勤劳作的程序员。软件出错不是应该的,但是绝对不是他们想要的。

    1

  • 性能测试(并发负载压力)测试分析

    2008-10-28 10:05:08

    性能测试(并发负载压力)测试分析

    分析原则:
        • 具体问题具体分析(这是由于不同的应用系统,不同的测试目的,不同的性能关注点)
        • 查找瓶颈时按以下顺序,由易到难。
        服务器硬件瓶颈-〉网络瓶颈(对局域网,可以不考虑)-〉服务器操作系统瓶颈(参数配置)-〉中间件瓶颈(参数配置,数据库,web服务器等)-〉应用瓶颈(SQL语句、数据库设计、业务逻辑、算法等)
        注:以上过程并不是每个分析中都需要的,要根据测试目的和要求来确定分析的深度。对一些要求低的,我们分析到应用系统在将来大的负载压力(并发用户数、数据量)下,系统的硬件瓶颈在哪儿就够了。
        • 分段排除法 很有效

    分析的信息来源:
        •1 根据场景运行过程中的错误提示信息
        •2 根据测试结果收集到的监控指标数据

    一.错误提示分析
    分析实例:
    1 •Error: Failed to connect to server "10.10.10.30:8080": [10060] Connection
      •Error: timed out Error: Server "10.10.10.30" has shut down the connection prematurely

      分析:
    •A、应用服务死掉。
       (小用户时:程序上的问题。程序上处理数据库的问题)
    •B、应用服务没有死
       (应用服务参数设置问题)
        例:在许多客户端连接Weblogic应用服务器被拒绝,而在服务器端没有错误显示,则有可能是Weblogic中的server元素的AcceptBacklog属性值设得过低。如果连接时收到connection refused消息,说明应提高该值,每次增加25%
    •C、数据库的连接
       (1、在应用服务的性能参数可能太小了 2、数据库启动的最大连接数(跟硬件的内存有关))

    2  Error: Page download timeout (120 seconds) has expired

    分析:可能是以下原因造成
    •A、应用服务参数设置太大导致服务器的瓶颈
    •B、页面中图片太多
    •C、在程序处理表的时候检查字段太大多

    二.监控指标数据分析
    1.最大并发用户数:
    应用系统在当前环境(硬件环境、网络环境、软件环境(参数配置))下能承受的最大并发用户数。
    在方案运行中,如果出现了大于3个用户的业务操作失败,或出现了服务器shutdown的情况,则说明在当前环境下,系统承受不了当前并发用户的负载压力,那么最大并发用户数就是前一个没有出现这种现象的并发用户数。
    如果测得的最大并发用户数到达了性能要求,且各服务器资源情况良好,业务操作响应时间也达到了用户要求,那么OK。否则,再根据各服务器的资源情况和业务操作响应时间进一步分析原因所在。

    2.业务操作响应时间:
    • 分析方案运行情况应从平均事务响应时间图和事务性能摘要图开始。使用“事务性能摘要”图,可以确定在方案执行期间响应时间过长的事务。
    • 细分事务并分析每个页面组件的性能。查看过长的事务响应时间是由哪些页面组件引起的?问题是否与网络或服务器有关?
    • 如果服务器耗时过长,请使用相应的服务器图确定有问题的服务器度量并查明服务器性能下降的原因。如果网络耗时过长,请使用“网络监视器”图确定导致性能瓶颈的网络问题

    3.服务器资源监控指标:
    内存:
        1 UNIX资源监控中指标内存页交换速率(Paging rate),如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。也可能是内存访问命中率低。
        2 Windows资源监控中,如果Process\Private Bytes计数器和Process\Working Set计数器的值在长时间内持续升高,同时Memory\Available bytes计数器的值持续降低,则很可能存在内存泄漏。

    内存资源成为系统性能的瓶颈的征兆:
        很高的换页率(high pageout rate);
        进程进入不活动状态;
        交换区所有磁盘的活动次数可高;
        可高的全局系统CPU利用率;
        内存不够出错(out of memory errors)

    处理器:
        1 UNIX资源监控(Windows操作系统同理)中指标CPU占用率(CPU utilization),如果该值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。如果服务器专用于SQL Server,可接受的最大上限是80-85%
        合理使用的范围在60%至70%。
        2 Windows资源监控中,如果System\Processor Queue Length大于2,而处理器利用率(Processor Time)一直很低,则存在着处理器阻塞。

    CPU资源成为系统性能的瓶颈的征兆:  
         很慢的响应时间(slow response time)
         CPU空闲时间为零(zero percent idle CPU)
         过高的用户占用CPU时间(high percent user CPU)
         过高的系统占用CPU时间(high percent system CPU)
        长时间的有很长的运行进程队列(large run queue size sustained over time)

    磁盘I/O:
        1 UNIX资源监控(Windows操作系统同理)中指标磁盘交换率(Disk rate),如果该参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。
        2 Windows资源监控中,如果 Disk Time和Avg.Disk Queue Length的值很高,而Page Reads/sec页面读取操作速率很低,则可能存在磁盘瓶径。

    I/O资源成为系统性能的瓶颈的征兆 :
         过高的磁盘利用率(high disk utilization)
        太长的磁盘等待队列(large disk queue length)
        等待磁盘I/O的时间所占的百分率太高(large percentage of time waiting for disk I/O)
        太高的物理I/O速率:large physical I/O rate(not sufficient in itself)
        过低的缓存命中率(low buffer cache hit ratio(not sufficient in itself))
        太长的运行进程队列,但CPU却空闲(large run queue with idle CPU)

    4.数据库服务器:
    SQL Server数据库:
        1 SQLServer资源监控中指标缓存点击率(Cache Hit Ratio),该值越高越好。如果持续低于80%,应考虑增加内存。
        2 如果Full Scans/sec(全表扫描/秒)计数器显示的值比1或2高,则应分析你的查询以确定是否确实需要全表扫描,以及SQL查询是否可以被优化。
        3 Number of Deadlocks/sec(死锁的数量/秒):死锁对应用程序的可伸缩性非常有害,并且会导致恶劣的用户体验。该计数器的值必须为0。
       4 Lock Requests/sec(锁请求/秒),通过优化查询来减少读取次数,可以减少该计数器的值。

    Oracle数据库:
      1 如果自由内存接近于0而且库快存或数据字典快存的命中率小于0.90,那么需要增加SHARED_POOL_SIZE的大小。
        快存(共享SQL区)和数据字典快存的命中率:
       select(sum(pins-reloads))/sum(pins) from v$librarycache;
        select(sum(gets-getmisses))/sum(gets) from v$rowcache;
        自由内存:    select * from v$sgastat where name=’free memory’;
    2 如果数据的缓存命中率小于0.90,那么需要加大DB_BLOCK_BUFFERS参数的值(单位:块)。
      缓冲区高速缓存命中率:
        select name,value from v$sysstat where name in ('db block gets’,
        'consistent gets','physical reads') ;
        Hit Ratio = 1-(physical reads / ( db block gets + consistent gets))
    3 如果日志缓冲区申请的值较大,则应加大LOG_BUFFER参数的值。
        日志缓冲区的申请情况 :
         select name,value from v$sysstat where name = 'redo log space requests' ;
    4 如果内存排序命中率小于0.95,则应加大SORT_AREA_SIZE以避免磁盘排序 。
       内存排序命中率 :
         select round((100*b.value)/decode((a.value+b.value), 0, 1, (a.value+b.value)), 2)from v$sysstat a, v$sysstat b where a.name='sorts (disk)' and b.name='sorts (memory)'

     

     

  • Yahoo!网站性能最佳体验的34条黄金守则

    2008-10-28 10:02:32

    Yahoo!的Exceptional Performance团队为改善Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。
    Excetional Performance团队总结出了一系列可以提高网站速度的方法。可以分为7大类34条。包括内容、服务器、cookie、CSS、Javascrīpt、图片、移动应用等七部分。

    其中内容部分一共十条建议:

    一、内容部分

    尽量减少HTTP请求
    减少DNS查找
    避免跳转
    缓存Ajxa
    推迟加载
    提前加载
    减少DOM元素数量
    用域名划分页面内容
    使frame数量最少
    避免404错误

    1、尽量减少HTTP请求次数
          终端用户响应的时间中,有80%用于下载各项内容。这部分时间包括下载页面中的图像、样式表、脚本、Flash等。通过减少页面中的元素可以减少HTTP请求的次数。这是提高网页速度的关键步骤。
          减少页面组件的方法其实就是简化页面设计。那么有没有一种方法既能保持页面内容的丰富性又能达到加快响应时间的目的呢?这里有几条减少HTTP请求次数同时又可能保持页面内容丰富的技术。

    合并文件是通过把所有的脚本放到一个文件中来减少HTTP请求的方法,如可以简单地把所有的CSS文件都放入一个样式表中。当脚本或者样式表在不同页面中使用时需要做不同的修改,这可能会相对麻烦点,但即便如此也要把这个方法作为改善页面性能的重要一步。

    CSS Sprites是减少图像请求的有效方法。把所有的背景图像都放到一个图片文件中,然后通过CSS的background-image和background-position属性来显示图片的不同部分;

    图片地图是把多张图片整合到一张图片中。虽然文件的总体大小不会改变,但是可以减少HTTP请求次数。图片地图只有在图片的所有组成部分在页面中是紧挨在一起的时候才能使用,如导航栏。确定图片的坐标和可能会比较繁琐且容易出错,同时使用图片地图导航也不具有可读性,因此不推荐这种方法;

    内联图像是使用data:URL scheme的方法把图像数据加载页面中。这可能会增加页面的大小。把内联图像放到样式表(可缓存)中可以减少HTTP请求同时又避免增加页面文件的大小。但是内联图像现在还没有得到主流浏览器的支持。

         减少页面的HTTP请求次数是你首先要做的一步。这是改进首次访问用户等待时间的最重要的方法。如同Tenni Theurer的他的博客Browser Cahe Usage - Exposed!中所说,HTTP请求在无缓存情况下占去了40%到60%的响应时间。让那些初次访问你网站的人获得更加快速的体验吧!

    2、减少DNS查找次数
            域名系统(DNS)提供了域名和IP的对应关系,就像电话本中人名和他们的电话号码的关系一样。当你在浏览器地址栏中输入
    http://www.dudo.org/时,DNS解析服务器就会返回这个域名对应的IP地址。DNS解析的过程同样也是需要时间的。一般情况下返回给定域名对应的IP地址会花费20到120毫秒的时间。而且在这个过程中浏览器什么都不会做直到DNS查找完毕。

           缓存DNS查找可以改善页面性能。这种缓存需要一个特定的缓存服务器,这种服务器一般属于用户的ISP提供商或者本地局域网控制,但是它同样会在用户使用的计算机上产生缓存。DNS信息会保留在操作系统的DNS缓存中(微软Windows系统中DNS Client Service)。大多数浏览器有独立于操作系统以外的自己的缓存。由于浏览器有自己的缓存记录,因此在一次请求中它不会受到操作系统的影响。

          Internet Explorer默认情况下对DNS查找记录的缓存时间为30分钟,它在注册表中的键值为DnsCacheTimeout。Firefox对DNS的查找记录缓存时间为1分钟,它在配置文件中的选项为network.dnsCacheExpiration(Fasterfox把这个选项改为了1小时)。

          当客户端中的DNS缓存都为空时(浏览器和操作系统都为空),DNS查找的次数和页面中主机名的数量相同。这其中包括页面中URL、图片、脚本文件、样式表、Flash对象等包含的主机名。减少主机名的数量可以减少DNS查找次数。

          减少主机名的数量还可以减少页面中并行下载的数量。减少DNS查找次数可以节省响应时间,但是减少并行下载却会增加响应时间。我的指导原则是把这些页面中的内容分割成至少两部分但不超过四部分。这种结果就是在减少DNS查找次数和保持较高程度并行下载两者之间的权衡了。

    3、避免跳转
    跳转是使用301和302代码实现的。下面是一个响应代码为301的HTTP头:
          HTTP/1.1 301 Moved Permanently
          Location:
    http://example.com/newuri
          Content-Type: text/html
          浏览器会把用户指向到Location中指定的URL。头文件中的所有信息在一次跳转中都是必需的,内容部分可以为空。不管他们的名称,301和302响应都不会被缓存除非增加一个额外的头选项,如Expires或者Cache-Control来指定它缓存。<meat />元素的刷新标签和Javascrīpt也可以实现URL的跳转,但是如果你必须要跳转的时候,最好的方法就是使用标准的3XXHTTP状态代码,这主要是为了确保“后退”按钮可以正确地使用。

          但是要记住跳转会降低用户体验。在用户和HTML文档中间增加一个跳转,会拖延页面中所有元素的显示,因为在HTML文件被加载前任何文件(图像、Flash等)都不会被下载。

          有一种经常被网页开发者忽略却往往十分浪费响应时间的跳转现象。这种现象发生在当URL本该有斜杠(/)却被忽略掉时。例如,当我们要访问http://astrology.yahoo.com/astrology 时,实际上返回的是一个包含301代码的跳转,它指向的是http://astrology.yahoo.com/astrology/  (注意末尾的斜杠)。在Apache服务器中可以使用Alias 或者 mod_rewrite或者the DirectorySlash来避免。

          连接新网站和旧网站是跳转功能经常被用到的另一种情况。这种情况下往往要连接网站的不同内容然后根据用户的不同类型(如浏览器类型、用户账号所属类型)来进行跳转。使用跳转来实现两个网站的切换十分简单,需要的代码量也不多。尽管使用这种方法对于开发者来说可以降低复杂程度,但是它同样降低用户体验。一个可替代方法就是如果两者在同一台服务器上时使用Alias和mod_rewrite和实现。如果是因为域名的不同而采用跳转,那么可以通过使用Alias或者mod_rewirte建立CNAME(保存一个域名和另外一个域名之间关系的DNS记录)来替代。

    4、可缓存的AJAX
          Ajax经常被提及的一个好处就是由于其从后台服务器传输信息的异步性而为用户带来的反馈的即时性。但是,使用Ajax并不能保证用户不会在等待异步的Javascrīpt和XML响应上花费时间。在很多应用中,用户是否需要等待响应取决于Ajax如何来使用。例如,在一个基于Web的Email客户端中,用户必须等待Ajax返回符合他们条件的邮件查询结果。记住一点,“异步”并不异味着“即时”,这很重要。

          为了提高性能,优化Ajax响应是很重要的。提高Ajxa性能的措施中最重要的方法就是使响应具有可缓存性,具体的讨论可以查看Add an Expires or a Cache-Control Header。其它的几条规则也同样适用于Ajax:
        Gizp压缩文件
        减少DNS查找次数
        精简Javascrīpt
        避免跳转
        配置ETags

         让我们来看一个例子:一个Web2.0的Email客户端会使用Ajax来自动完成对用户地址薄的下载。如果用户在上次使用过Email web应用程序后没有对地址薄作任何的修改,而且Ajax响应通过Expire或者Cacke-Control头来实现缓存,那么就可以直接从上一次的缓存中读取地址薄了。必须告知浏览器是使用缓存中的地址薄还是发送一个新的请求。这可以通过为读取地址薄的Ajax URL增加一个含有上次编辑时间的时间戳来实现,例如,&t=11900241612等。如果地址薄在上次下载后没有被编辑过,时间戳就不变,则从浏览器的缓存中加载从而减少了一次HTTP请求过程。如果用户修改过地址薄,时间戳就会用来确定新的URL和缓存响应并不匹配,浏览器就会重要请求更新地址薄。
            即使你的Ajxa响应是动态生成的,哪怕它只适用于一个用户,那么它也应该被缓存起来。这样做可以使你的Web2.0应用程序更加快捷。

    5、推迟加载内容
            你可以仔细看一下你的网页,问问自己“哪些内容是页面呈现时所必需首先加载的?哪些内容和结构可以稍后再加载?
            把整个过程按照onload事件分隔成两部分,Javascrīpt是一个理想的选择。例如,如果你有用于实现拖放和动画的Javascrīpt,那么它就以等待稍后加载,因为页面上的拖放元素是在初始化呈现之后才发生的。其它的例如隐藏部分的内容(用户操作之后才显现的内容)和处于折叠部分的图像也可以推迟加载
            工具可以节省你的工作量:YUI Image Loader可以帮你推迟加载折叠部分的图片,YUI Get utility是包含JS和 CSS的便捷方法。比如你可以打开Firebug的Net选项卡看一下Yahoo的首页。
            当性能目标和其它网站开发实践一致时就会相得益彰。这种情况下,通过程序提高网站性能的方法告诉我们,在支持Javascrīpt的情况下,可以先去除用户体验,不过这要保证你的网站在没有Javascrīpt也可以正常运行。在确定页面运行正常后,再加载脚本来实现如拖放和动画等更加花哨的效果。

    6、预加载
            预加载和后加载看起来似乎恰恰相反,但实际上预加载是为了实现另外一种目标。预加载是在浏览器空闲时请求将来可能会用到的页面内容(如图像、样式表和脚本)。使用这种方法,当用户要访问下一个页面时,页面中的内容大部分已经加载到缓存中了,因此可以大大改善访问速度。

    下面提供了几种预加载方法:
    无条件加载:触发onload事件时,直接加载额外的页面内容。以Google.com为例,你可以看一下它的spirit image图像是怎样在onload中加载的。这个spirit image图像在google.com主页中是不需要的,但是却可以在搜索结果页面中用到它。
    有条件加载:根据用户的操作来有根据地判断用户下面可能去往的页面并相应的预加载页面内容。在search.yahoo.com中你可以看到如何在你输入内容时加载额外的页面内容。
    有预期的加载:载入重新设计过的页面时使用预加载。这种情况经常出现在页面经过重新设计后用户抱怨“新的页面看起来很酷,但是却比以前慢”。问题可能出在用户对于你的旧站点建立了完整的缓存,而对于新站点却没有任何缓存内容。因此你可以在访问新站之前就加载一部内容来避免这种结果的出现。在你的旧站中利用浏览器的空余时间加载新站中用到的图像的和脚本来提高访问速度。

    7、减少DOM元素数量
            一个复杂的页面意味着需要下载更多数据,同时也意味着Javascrīpt遍历DOM的效率越慢。比如当你增加一个事件句柄时在500和5000个DOM元素中循环效果肯定是不一样的。
           大量的DOM元素的存在意味着页面中有可以不用移除内容只需要替换元素标签就可以精简的部分。你在页面布局中使用表格了吗?你有没有仅仅为了布局而引入更多的<div>元素呢?也许会存在一个适合或者在语意是更贴切的标签可以供你使用。
            YUI CSS utilities可以给你的布局带来巨大帮助:grids.css可以帮你实现整体布局,font.css和reset.css可以帮助你移除浏览器默认格式。它提供了一个重新审视你页面中标签的机会,比如只有在语意上有意义时才使用<div>,而不是因为它具有换行效果才使用它。
          DOM元素数量很容易计算出来,只需要在Firebug的控制台内输入:
    document.getElementsByTagName('*').length
            那么多少个DOM元素算是多呢?这可以对照有很好标记使用的类似页面。比如Yahoo!主页是一个内容非常多的页面,但是它只使用了700个元素(HTML标签)。

    8、根据域名划分页面内容
          把页面内容划分成若干部分可以使你最大限度地实现平行下载。由于DNS查找带来的影响你首先要确保你使用的域名数量在2个到4个之间。例如,你可以把用到的HTML内容和动态内容放在
    www.example.org上,而把页面各种组件(图片、脚本、CSS)分别存放在statics1.example.org和statics.example.org上。
    你可在Tenni Theurer和Patty Chi合写的文章Maximizing Parallel Downloads in the Carpool Lane找到更多相关信息。

    9、使iframe的数量最小
          ifrmae元素可以在父文档中插入一个新的HTML文档。了解iframe的工作理然后才能更加有效地使用它,这一点很重要。
    <iframe>优点:

    解决加载缓慢的第三方内容如图标和广告等的加载问题
    Security sandbox
    并行加载脚本
    <iframe>的缺点:

    即时内容为空,加载也需要时间
    会阻止页面加载
    没有语意

    10、不要出现404错误
          HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。
          有些站点把404错误响应页面改为“你是不是要找***”,这虽然改进了用户体验但是同样也会浪费服务器资源(如数据库等)。最糟糕的情况是指向外部Javascrīpt的链接出现问题并返回404代码。首先,这种加载会破坏并行加载;其次浏览器会把试图在返回的404响应内容中找到可能有用的部分当作Javascrīpt代码来执行。

     

    转载自:http://www.dudo.org/article.asp?id=215

      在本系列的第一节中,讲了提高网站性能中网站“内容”有关的10条原则。除了在网站在内容上的改进外,在网站服务器端上也有需要注意和改进的地方,它们包括:

    使用内容分发网络
    为文件头指定Expires或Cache-Control
    Gzip压缩文件内容
    配置ETag
    尽早刷新输出缓冲
    使用GET来完成AJAX请求

    11、使用内容分发网络
          用户与你网站服务器的接近程度会影响响应时间的长短。把你的网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度。但是首先我们应该做些什么呢?
          按地域布置网站内容的第一步并不是要尝试重新架构你的网站让他们在分发服务器上正常运行。根据应用的需求来改变网站结构,这可能会包括一些比较复杂的任务,如在服务器间同步Session状态和合并数据库更新等。要想缩短用户和内容服务器的距离,这些架构步骤可能是不可避免的。
          要记住,在终端用户的响应时间中有80%到90%的响应时间用于下载图像、样式表、脚本、Flash等页面内容。这就是网站性能黄金守则。和重新设计你的应用程序架构这样比较困难的任务相比,首先来分布静态内容会更好一点。这不仅会缩短响应时间,而且对于内容分发网络来说它更容易实现。
          内容分发网络(Content Delivery Network,CDN)是由一系列分散到各个不同地理位置上的Web服务器组成的,它提高了网站内容的传输速度。用于向用户传输内容的服务器主要是根据和用户在网络上的靠近程度来指定的。例如,拥有最少网络跳数(network hops)和响应速度最快的服务器会被选定。
          一些大型的网络公司拥有自己的CDN,但是使用像Akamai Technologies,Mirror Image Internet, 或者Limelight Networks这样的CDN服务成本却非常高。对于刚刚起步的企业和个人网站来说,可能没有使用CDN的成本预算,但是随着目标用户群的不断扩大和更加全球化,CDN就是实现快速响应所必需的了。以Yahoo来说,他们转移到CDN上的网站程序静态内容节省了终端用户20%以上的响应时间。使用CDN是一个只需要相对简单地修改代码实现显著改善网站访问速度的方法。

    12、为文件头指定Expires或Cache-Control
          这条守则包括两方面的内容:
    对于静态内容:设置文件头过期时间Expires的值为“Never expire”(永不过期)
    对于动态内容:使用恰当的Cache-Control文件头来帮助浏览器进行有条件的请求
          网页内容设计现在越来越丰富,这就意味着页面中要包含更多的脚本、样式表、图片和Flash。第一次访问你页面的用户就意味着进行多次的HTTP请求,但是通过使用Expires文件头就可以使这样内容具有缓存性。它避免了接下来的页面访问中不必要的HTTP请求。Expires文件头经常用于图像文件,但是应该在所有的内容都使用他,包括脚本、样式表和Flash等。
          浏览器(和代理)使用缓存来减少HTTP请求的大小和次数以加快页面访问速度。Web服务器在HTTP响应中使用Expires文件头来告诉客户端内容需要缓存多长时间。下面这个例子是一个较长时间的Expires文件头,它告诉浏览器这个响应直到2010年4月15日才过期。
          Expires: Thu, 15 Apr 2010 20:00:00 GMT
          如果你使用的是Apache服务器,可以使用ExpiresDefault来设定相对当前日期的过期时间。下面这个例子是使用ExpiresDefault来设定请求时间后10年过期的文件头:
          ExpiresDefault "access plus 10 years"
          要切记,如果使用了Expires文件头,当页面内容改变时就必须改变内容的文件名。依Yahoo!来说我们经常使用这样的步骤:在内容的文件名中加上版本号,如yahoo_2.0.6.js。
          使用Expires文件头只有会在用户已经访问过你的网站后才会起作用。当用户首次访问你的网站时这对减少HTTP请求次数来说是无效的,因为浏览器的缓存是空的。因此这种方法对于你网站性能的改进情况要依据他们“预缓存”存在时对你页面的点击频率(“预缓存”中已经包含了页面中的所有内容)。Yahoo!建立了一套测量方法,我们发现所有的页面浏览量中有75~85%都有“预缓存”。通过使用Expires文件头,增加了缓存在浏览器中内容的数量,并且可以在用户接下来的请求中再次使用这些内容,这甚至都不需要通过用户发送一个字节的请求。

    13、Gzip压缩文件内容
          网络传输中的HTTP请求和应答时间可以通过前端机制得到显著改善。的确,终端用户的带宽、互联网提供者、与对等交换点的靠近程度等都不是网站开发者所能决定的。但是还有其他因素影响着响应时间。通过减小HTTP响应的大小可以节省HTTP响应时间。
          从HTTP/1.1开始,web客户端都默认支持HTTP请求中有Accept-Encoding文件头的压缩格式:  
          Accept-Encoding: gzip, deflate
          如果web服务器在请求的文件头中检测到上面的代码,就会以客户端列出的方式压缩响应内容。Web服务器把压缩方式通过响应文件头中的Content-Encoding来返回给浏览器。
          Content-Encoding: gzip
          Gzip是目前最流行也是最有效的压缩方式。这是由GNU项目开发并通过RFC 1952来标准化的。另外仅有的一个压缩格式是deflate,但是它的使用范围有限效果也稍稍逊色。
          Gzip大概可以减少70%的响应规模。目前大约有90%通过浏览器传输的互联网交换支持gzip格式。如果你使用的是Apache,gzip模块配置和你的版本有关:Apache 1.3使用mod_zip,而Apache 2.x使用moflate。
          浏览器和代理都会存在这样的问题:浏览器期望收到的和实际接收到的内容会存在不匹配的现象。幸好,这种特殊情况随着旧式浏览器使用量的减少在减少。Apache模块会通过自动添加适当的Vary响应文件头来避免这种状况的出现。
          服务器根据文件类型来选择需要进行gzip压缩的文件,但是这过于限制了可压缩的文件。大多数web服务器会压缩HTML文档。对脚本和样式表进行压缩同样也是值得做的事情,但是很多web服务器都没有这个功能。实际上,压缩任何一个文本类型的响应,包括XML和JSON,都值得的。图像和PDF文件由于已经压缩过了所以不能再进行gzip压缩。如果试图gizp压缩这些文件的话不但会浪费CPU资源还会增加文件的大小。
          Gzip压缩所有可能的文件类型是减少文件体积增加用户体验的简单方法。

    14、配置ETag
          Entity tags(ETags)(实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制(“实体”就是所说的“内容”,包括图片、脚本、样式表等)。增加ETag为实体的验证提供了一个比使用“last-modified date(上次编辑时间)”更加灵活的机制。Etag是一个识别内容版本号的唯一字符串。唯一的格式限制就是它必须包含在双引号内。原始服务器通过含有ETag文件头的响应指定页面内容的ETag。
          HTTP/1.1 200 OK
          Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
          ETag: "10c24bc-4ab-457e1c1f"
          Content-Length: 12195
          稍后,如果浏览器要验证一个文件,它会使用If-None-Match文件头来把ETag传回给原始服务器。在这个例子中,如果ETag匹配,就会返回一个304状态码,这就节省了12195字节的响应。      GET /i/yahoo.gif HTTP/1.1
          Host: us.yimg.com
          If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
          If-None-Match: "10c24bc-4ab-457e1c1f"
          HTTP/1.1 304 Not Modified
          ETag的问题在于,它是根据可以辨别网站所在的服务器的具有唯一性的属性来生成的。当浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时ETag就会不匹配,这种情况对于使用服务器组和处理请求的网站来说是非常常见的。默认情况下,Apache和IIS都会把数据嵌入ETag中,这会显著减少多服务器间的文件验证冲突。
          Apache 1.3和2.x中的ETag格式为inode-size-timestamp。即使某个文件在不同的服务器上会处于相同的目录下,文件大小、权限、时间戳等都完全相同,但是在不同服务器上他们的内码也是不同的。
          IIS 5.0和IIS 6.0处理ETag的机制相似。IIS中的ETag格式为Filetimestamp:ChangeNumber。用ChangeNumber来跟踪IIS配置的改变。网站所用的不同IIS服务器间ChangeNumber也不相同。 不同的服务器上的Apache和IIS即使对于完全相同的内容产生的ETag在也不相同,用户并不会接收到一个小而快的304响应;相反他们会接收一个正常的200响应并下载全部内容。如果你的网站只放在一台服务器上,就不会存在这个问题。但是如果你的网站是架设在多个服务器上,并且使用Apache和IIS产生默认的ETag配置,你的用户获得页面就会相对慢一点,服务器会传输更多的内容,占用更多的带宽,代理也不会有效地缓存你的网站内容。即使你的内容拥有Expires文件头,无论用户什么时候点击“刷新”或者“重载”按钮都会发送相应的GET请求。
          如果你没有使用ETag提供的灵活的验证模式,那么干脆把所有的ETag都去掉会更好。Last-Modified文件头验证是基于内容的时间戳的。去掉ETag文件头会减少响应和下次请求中文件的大小。微软的这篇支持文稿讲述了如何去掉ETag。在Apache中,只需要在配置文件中简单添加下面一行代码就可以了:
          FileETag none

    15、尽早刷新输出缓冲
          当用户请求一个页面时,无论如何都会花费200到500毫秒用于后台组织HTML文件。在这期间,浏览器会一直空闲等待数据返回。在PHP中,你可以使用flush()方法,它允许你把已经编译的好的部分HTML响应文件先发送给浏览器,这时浏览器就会可以下载文件中的内容(脚本等)而后台同时处理剩余的HTML页面。这样做的效果会在后台烦恼或者前台较空闲时更加明显。
          输出缓冲应用最好的一个地方就是紧跟在<head />之后,因为HTML的头部分容易生成而且头部往往包含CSS和Javascrīpt文件,这样浏览器就可以在后台编译剩余HTML的同时并行下载它们。 例子:

          ... <!-- css, js -->
        </head>
        <?php flush(); ?>
        <body>
          ... <!-- content -->

    为了证明使用这项技术的好处,Yahoo!搜索率先研究并完成了用户测试。

    16、使用GET来完成AJAX请求
          Yahoo!Mail团队发现,当使用XMLHttpRequest时,浏览器中的POST方法是一个“两步走”的过程:首先发送文件头,然后才发送数据。因此使用GET最为恰当,因为它只需发送一个TCP包(除非你有很多cookie)。IE中URL的最大长度为2K,因此如果你要发送一个超过2K的数据时就不能使用GET了。
          一个有趣的不同就是POST并不像GET那样实际发送数据。根据HTTP规范,GET意味着“获取”数据,因此当你仅仅获取数据时使用GET更加有意义(从语意上讲也是如此),相反,发送并在服务端保存数据时使用POST。

     

    转载自:http://www.dudo.org/article.asp?id=216


     在第一部分和第二部分中我们分别介绍了改善网站性能中页面内容和服务器的几条守则,除此之外,Javascrīpt和CSS也是我们页面中经常用到的内容,对它们的优化也提高网站性能的重要方面:
    CSS:

    把样式表置于顶部
    避免使用CSS表达式(Expression)
    使用外部Javascrīpt和CSS
    削减Javascrīpt和CSS
    http://www.dudo.org/article.asp?id=216#link
    避免使用滤镜
    Javascrīpt

    把脚本置于页面底部
    使用外部Javascrīpt和CSS
    削减Javascrīpt和CSS
    剔除重复脚本
    减少DOM访问
    开发智能事件处理程序

    17、把样式表置于顶部
          在研究Yahoo!的性能表现时,我们发现把样式表放到文档的<head />内部似乎会加快页面的下载速度。这是因为把样式表放到<head />内会使页面有步骤的加载显示。
          注重性能的前端服务器往往希望页面有秩序地加载。同时,我们也希望浏览器把已经接收到内容尽可能显示出来。这对于拥有较多内容的页面和网速较慢的用户来说特别重要。向用户返回可视化的反馈,比如进程指针,已经有了较好的研究并形成了正式文档。在我们的研究中HTML页面就是进程指针。当浏览器有序地加载文件头、导航栏、顶部的logo等对于等待页面加载的用户来说都可以作为可视化的反馈。这从整体上改善了用户体验。
          把样式表放在文档底部的问题是在包括Internet Explorer在内的很多浏览器中这会中止内容的有序呈现。浏览器中止呈现是为了避免样式改变引起的页面元素重绘。用户不得不面对一个空白页面。
          HTML规范清楚指出样式表要放包含在页面的<head />区域内:“和<a />不同,<link />只能出现在文档的<head />区域内,尽管它可以多次使用它”。无论是引起白屏还是出现没有样式化的内容都不值得去尝试。最好的方案就是按照HTML规范在文档<head />内加载你的样式表。

    18、避免使用CSS表达式(Expression)
          CSS表达式是动态设置CSS属性的强大(但危险)方法。Internet Explorer从第5个版本开始支持CSS表达式。下面的例子中,使用CSS表达式可以实现隔一个小时切换一次背景颜色:
          background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
    如上所示,expression中使用了Javascrīpt表达式。CSS属性根据Javascrīpt表达式的计算结果来设置。expression方法在其它浏览器中不起作用,因此在跨浏览器的设计中单独针对Internet Explorer设置时会比较有用。
          表达式的问题就在于它的计算频率要比我们想象的多。不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次。给CSS表达式增加一个计数器可以跟踪表达式的计算频率。在页面中随便移动鼠标都可以轻松达到10000次以上的计算量。
          一个减少CSS表达式计算次数的方法就是使用一次性的表达式,它在第一次运行时将结果赋给指定的样式属性,并用这个属性来代替CSS表达式。如果样式属性必须在页面周期内动态地改变,使用事件句柄来代替CSS表达式是一个可行办法。如果必须使用CSS表达式,一定要记住它们要计算成千上万次并且可能会对你页面的性能产生影响。

    19、使用外部Javascrīpt和CSS
          很多性能规则都是关于如何处理外部文件的。但是,在你采取这些措施前你可能会问到一个更基本的问题:Javascrīpt和CSS是应该放在外部文件中呢还是把它们放在页面本身之内呢?
          在实际应用中使用外部文件可以提高页面速度,因为Javascrīpt和CSS文件都能在浏览器中产生缓存。内置在HTML文档中的Javascrīpt和CSS则会在每次请求中随HTML文档重新下载。这虽然减少了HTTP请求的次数,却增加了HTML文档的大小。从另一方面来说,如果外部文件中的Javascrīpt和CSS被浏览器缓存,在没有增加HTTP请求次数的同时可以减少HTML文档的大小。
          关键问题是,外部Javascrīpt和CSS文件缓存的频率和请求HTML文档的次数有关。虽然有一定的难度,但是仍然有一些指标可以一测量它。如果一个会话中用户会浏览你网站中的多个页面,并且这些页面中会重复使用相同的脚本和样式表,缓存外部文件就会带来更大的益处。
          许多网站没有功能建立这些指标。对于这些网站来说,最好的坚决方法就是把Javascrīpt和CSS作为外部文件引用。比较适合使用内置代码的例外就是网站的主页,如Yahoo!主页和My Yahoo!。主页在一次会话中拥有较少(可能只有一次)的浏览量,你可以发现内置Javascrīpt和CSS对于终端用户来说会加快响应时 间。
          对于拥有较大浏览量的首页来说,有一种技术可以平衡内置代码带来的HTTP请求减少与通过使用外部文件进行缓存带来的好处。其中一个就是在首页中内置Javascrīpt和CSS,但是在页面下载完成后动态下载外部文件,在子页面中使用到这些文件时,它们已经缓存到浏览器了。

    20、削减Javascrīpt和CSS
          精简是指从去除代码不必要的字符减少文件大小从而节省下载时间。消减代码时,所有的注释、不需要的空白字符(空格、换行、tab缩进)等都要去掉。在Javascrīpt中,由于需要下载的文件体积变小了从而节省了响应时间。精简Javascrīpt中目前用到的最广泛的两个工具是JSMin和YUI Compressor。YUI Compressor还可用于精简CSS。
          混淆是另外一种可用于源代码优化的方法。这种方法要比精简复杂一些并且在混淆的过程更易产生问题。在对美国前10大网站的调查中发现,精简也可以缩小原来代码体积的21%,而混淆可以达到25%。尽管混淆法可以更好地缩减代码,但是对于Javascrīpt来说精简的风险更小。
          除消减外部的脚本和样式表文件外,<scrīpt>和<style>代码块也可以并且应该进行消减。即使你用Gzip压缩过脚本和样式表,精简这些文件仍然可以节省5%以上的空间。由于Javascrīpt和CSS的功能和体积的增加,消减代码将会获得益处。

    21、用<link>代替@import
          前面的最佳实现中提到CSS应该放置在顶端以利于有序加载呈现。
          在IE中,页面底部@import和使用<link>作用是一样的,因此最好不要使用它。

    22、避免使用滤镜
          IE独有属性AlphaImageLoader用于修正7.0以下版本中显示PNG图片的半透明效果。这个滤镜的问题在于浏览器加载图片时它会终止内容的呈现并且冻结浏览器。在每一个元素(不仅仅是图片)它都会运算一次,增加了内存开支,因此它的问题是多方面的。
          完全避免使用AlphaImageLoader的最好方法就是使用PNG8格式来代替,这种格式能在IE中很好地工作。如果你确实需要使用AlphaImageLoader,请使用下划线_filter又使之对IE7以上版本的用户无效。

    23、把脚本置于页面底部
          脚本带来的问题就是它阻止了页面的平行下载。HTTP/1.1 规范建议,浏览器每个主机名的并行下载内容不超过两个。如果你的图片放在多个主机名上,你可以在每个并行下载中同时下载2个以上的文件。但是当下载脚本时,浏览器就不会同时下载其它文件了,即便是主机名不相同。
          在某些情况下把脚本移到页面底部可能不太容易。比如说,如果脚本中使用了document.write来插入页面内容,它就不能被往下移动了。这里可能还会有作用域的问题。很多情况下,都会遇到这方面的问题。
          一个经常用到的替代方法就是使用延迟脚本。DEFER属性表明脚本中没有包含document.write,它告诉浏览器继续显示。不幸的是,Firefox并不支持DEFER属性。在Internet Explorer中,脚本可能会被延迟但效果也不会像我们所期望的那样。如果脚本可以被延迟,那么它就可以移到页面的底部。这会让你的页面加载的快一点。

    24、剔除重复脚本
          在同一个页面中重复引用Javascrīpt文件会影响页面的性能。你可能会认为这种情况并不多见。对于美国前10大网站的调查显示其中有两家存在重复引用脚本的情况。有两种主要因素导致一个脚本被重复引用的奇怪现象发生:团队规模和脚本数量。如果真的存在这种情况,重复脚本会引起不必要的HTTP请求和无用的Javascrīpt运算,这降低了网站性能。
          在Internet Explorer中会产生不必要的HTTP请求,而在Firefox却不会。在Internet Explorer中,如果一个脚本被引用两次而且它又不可缓存,它就会在页面加载过程中产生两次HTTP请求。即时脚本可以缓存,当用户重载页面时也会产生额外的HTTP请求。
          除增加额外的HTTP请求外,多次运算脚本也会浪费时间。在Internet Explorer和Firefox中不管脚本是否可缓存,它们都存在重复运算Javascrīpt的问题。
          一个避免偶尔发生的两次引用同一脚本的方法是在模板中使用脚本管理模块引用脚本。在HTML页面中使用<scrīpt />标签引用脚本的最常见方法就是:
          <scrīpt type="text/javascrīpt" src="menu_1.0.17.js"></scrīpt>
    在PHP中可以通过创建名为insertscrīpt的方法来替代:
          <?php insertscrīpt("menu.js") ?>
    为了防止多次重复引用脚本,这个方法中还应该使用其它机制来处理脚本,如检查所属目录和为脚本文件名中增加版本号以用于Expire文件头等。

    25、减少DOM访问
          使用Javascrīpt访问DOM元素比较慢,因此为了获得更多的应该页面,应该做到:

    缓存已经访问过的有关元素
    线下更新完节点之后再将它们添加到文档树中
    避免使用Javascrīpt来修改页面布局
          有关此方面的更多信息请查看Julien Lecomte在YUI专题中的文章“高性能Ajax应该程序”。

    26、开发智能事件处理程序
          有时候我们会感觉到页面反应迟钝,这是因为DOM树元素中附加了过多的事件句柄并且些事件句病被频繁地触发。这就是为什么说使用event delegation(事件代理)是一种好方法了。如果你在一个div中有10个按钮,你只需要在div上附加一次事件句柄就可以了,而不用去为每一个按钮增加一个句柄。事件冒泡时你可以捕捉到事件并判断出是哪个事件发出的。
          你同样也不用为了操作DOM树而等待onload事件的发生。你需要做的就是等待树结构中你要访问的元素出现。你也不用等待所有图像都加载完毕。
          你可能会希望用DOMContentLoaded事件来代替onload,但是在所有浏览器都支持它之前你可使用YUI 事件应用程序中的onAvailable方法。
          有关此方面的更多信息请查看Julien Lecomte在YUI专题中的文章“高性能Ajax应该程序”。


    我们在前面的几节中分别讲了提高网站性能中内容、服务器、Javascrīpt和CSS等方面的内容。除此之外,图片和Coockie也是我们网站中几乎不可缺少组成部分,此外随着移动设备的流行,对于移动应用的优化也十分重要。这主要包括:
    Coockie:

    减小Cookie体积
    对于页面内容使用无coockie域名
    图片:

    优化图像
    优化CSS Spirite
    不要在HTML中缩放图像
    favicon.ico要小而且可缓存
    移动应用:

    保持单个内容小于25K
    打包组件成复合文本

    27、减小Cookie体积
          HTTP coockie可以用于权限验证和个性化身份等多种用途。coockie内的有关信息是通过HTTP文件头来在web服务器和浏览器之间进行交流的。因此保持coockie尽可能的小以减少用户的响应时间十分重要。
    有关更多信息可以查看Tenni Theurer和Patty Chi的文章“When the Cookie Crumbles”。这们研究中主要包括:

    去除不必要的coockie
    使coockie体积尽量小以减少对用户响应的影响
    注意在适应级别的域名上设置coockie以便使子域名不受影响
    设置合理的过期时间。较早地Expire时间和不要过早去清除coockie,都会改善用户的响应时间。
    28、对于页面内容使用无coockie域名
          当浏览器在请求中同时请求一张静态的图片和发送coockie时,服务器对于这些coockie不会做任何地使用。因此他们只是因为某些负面因素而创建的网络传输。所有你应该确定对于静态内容的请求是无coockie的请求。创建一个子域名并用他来存放所有静态内容。
          如果你的域名是
    www.example.org,你可以在static.example.org上存在静态内容。但是,如果你不是在www.example.org上而是在顶级域名example.org设置了coockie,那么所有对于static.example.org的请求都包含coockie。在这种情况下,你可以再重新购买一个新的域名来存在静态内容,并且要保持这个域名是无coockie的。Yahoo!使用的是ymig.com,YouTube使用的是ytimg.com,Amazon使用的是images-anazon.com等等。
          使用无coockie域名存在静态内容的另外一个好处就是一些代理(服务器)可能会拒绝对coockie的内容请求进行缓存。一个相关的建议就是,如果你想确定应该使用example.org还是
    www.example.org作为你的一主页,你要考虑到coockie带来的影响。忽略掉www会使你除了把coockie设置到*.example.org(*是泛域名解析,代表了所有子域名译者dudo注)外没有其它选择,因此出于性能方面的考虑最好是使用带有www的子域名并且在它上面设置coockie。

    29、优化图像
          设计人员完成对页面的设计之后,不要急于将它们上传到web服务器,这里还需要做几件事:

    你可以检查一下你的GIF图片中图像颜色的数量是否和调色板规格一致。 使用imagemagick中下面的命令行很容易检查:
    identify -verbose image.gif
    如果你发现图片中只用到了4种颜色,而在调色板的中显示的256色的颜色槽,那么这张图片就还有压缩的空间。
    尝试把GIF格式转换成PNG格式,看看是否节省空间。大多数情况下是可以压缩的。由于浏览器支持有限,设计者们往往不太乐意使用PNG格式的图片,不过这都是过去的事情了。现在只有一个问题就是在真彩PNG格式中的alpha通道半透明问题,不过同样的,GIF也不是真彩格式也不支持半透明。因此GIF能做到的,PNG(PNG8)同样也能做到(除了动画)。下面这条简单的命令可以安全地把GIF格式转换为PNG格式:
    convert image.gif image.png
    “我们要说的是:给PNG一个施展身手的机会吧!”
    在所有的PNG图片上运行pngcrush(或者其它PNG优化工具)。例如:
    pngcrush image.png -rem alla -reduce -brute result.png
    在所有的JPEG图片上运行jpegtran。这个工具可以对图片中的出现的锯齿等做无损操作,同时它还可以用于优化和清除图片中的注释以及其它无用信息(如EXIF信息):
    jpegtran -copy none -optimize -perfect src.jpg dest.jpg
    30、优化CSS Spirite

    在Spirite中水平排列你的图片,垂直排列会稍稍增加文件大小;
    Spirite中把颜色较近的组合在一起可以降低颜色数,理想状况是低于256色以便适用PNG8格式;
    便于移动,不要在Spirite的图像中间留有较大空隙。这虽然不大会增加文件大小但对于用户代理来说它需要更少的内存来把图片解压为像素地图。100x100的图片为1万像素,而1000x1000就是100万像素。

    31、不要在HTML中缩放图像
          不要为了在HTML中设置长宽而使用比实际需要大的图片。如果你需要:
    <img width="100" height="100" src="mycat.jpg" alt="My Cat" />
    那么你的图片(mycat.jpg)就应该是100x100像素而不是把一个500x500像素的图片缩小使用。

    32、favicon.ico要小而且可缓存
          favicon.ico是位于服务器根目录下的一个图片文件。它是必定存在的,因为即使你不关心它是否有用,浏览器也会对它发出请求,因此最好不要返回一个404 Not Found的响应。由于是在同一台服务器上,它每被请求一次coockie就会被发送一次。这个图片文件还会影响下载顺序,例如在IE中当你在onload中请求额外的文件时,favicon会在这些额外内容被加载前下载。
          因此,为了减少favicon.ico带来的弊端,要做到:

    文件尽量地小,最好小于1K
    在适当的时候(也就是你不要打算再换favicon.ico的时候,因为更换新文件时不能对它进行重命名)为它设置Expires文件头。你可以很安全地把Expires文件头设置为未来的几个月。你可以通过核对当前favicon.ico的上次编辑时间来作出判断。
    Imagemagick可以帮你创建小巧的favicon。

    33、保持单个内容小于25K
          这条限制主要是因为iPhone不能缓存大于25K的文件。注意这里指的是解压缩后的大小。由于单纯gizp压缩可能达不要求,因此精简文件就显得十分重要。
          查看更多信息,请参阅Wayne Shea和Tenni Theurer的文件“Performance Research, Part 5: iPhone Cacheability - Making it Stick”。

    34、打包组件成复合文本
          把页面内容打包成复合文本就如同带有多附件的Email,它能够使你在一个HTTP请求中取得多个组件(切记:HTTP请求是很奢侈的)。当你使用这条规则时,首先要确定用户代理是否支持(iPhone就不支持)。

     

  • 一个安全测试的checklist

    2008-10-28 09:58:37

    1. 不登录系统,直接输入登录后的页面的url是否可以访问

      2. 不登录系统,直接输入下载文件的url是否可以下载,如输入http://url/download?name=file是否可以下载文件file

      3. 退出登录后按后退按钮能否访问之前的页面

      4. ID/密码验证方式中能否使用简单密码。如密码标准为6位以上,字母和数字混合,不能包含ID,连续的字母或数字不能超过n位

      5. 重要信息(如密码,身份证号码,信用卡号等)在输入或查询时是否用明文显示;在浏览器地址栏里输入命令javascrīpt:alert(doucument.cookie)时是否有重要信息;在html源码中能否看到重要信息

      6. 手动更改URL中的参数值能否访问没有权限访问的页面。如普通用户对应的url中的参数为l=e,高级用户对应的url中的参数为l=s,以普通用户的身份登录系统后将url中的参数e改为s来访问本没有权限访问的页面

      7. url里不可修改的参数是否可以被修改

      8. 上传与服务器端语言(jsp、asp、php)一样扩展名的文件或exe等可执行文件后,确认在服务器端是否可直接运行

      9. 注册用户时是否可以以'--,' or 1=1 --等做为用户名

      10. 传送给服务器的参数(如查询关键字、url中的参数等)中包含特殊字符(','and 1=1 --,' and 1=0 --,'or 1=0 --)时是否可以正常处理

      11. 执行新增操作时,在所有的输入框中输入脚本标签(<scrīpt>alert("")</scrīpt>)后能否保存

      12. 在url中输入下面的地址是否可以下载:http://url/download.jsp?file=C:\windows\system32\drivers\etc\hosts,http://url/download.jsp?file=/etc/passwd

      13. 是否对session的有效期进行处理

      14. 错误信息中是否含有sql语句、sql错误信息以及web服务器的绝对路径等

      15. ID/密码验证方式中,同一个账号在不同的机器上不能同时登录

      16. ID/密码验证方式中,连续数次输入错误密码后该账户是否被锁定

      17. 新增或修改重要信息(密码、身份证号码、信用卡号等)时是否有自动完成功能(在form标签中使用autocomplete=off来关闭自动完成功能)

     

  • 要做好性能测试,该掌握些什么?

    2008-10-28 09:55:25

    1. 精通性能测试的基本概念,过程,方法论,了解性能工程;

    2. 精通1个商业性能测试工具+1个开源性能测试工具,知道工具可以做什么,不可以做什么,以及工具使用中常见的问题和解决思路;

    3. 扎实的计算机专业基础知识,包括计算机组成原理、操作系统、数据库原理、计算机网络原理;

    4. 熟悉至少1个常用的数据库产品,例如SQL Server或者 Oracle,能进行一般的数据库管理操作,熟悉SQL脚本的使用,熟悉常用的数据调优工具和常用的counter;

    5. 熟悉至少一个操作系统的原理,Windows或者Linux都可以,熟悉操作系统的体系架构、操作系统的重要基础概念,以及内存管理、存储/文件系统、驱动/硬件的管理、网络协议的实现及构成、性能的监控方法和原理,熟悉常用的counter;

    6. 熟悉至少一个web server 产品,例如apache,了解一般的配置和常用的counter;

    7. 熟悉至少一个应用服务器产品,例如tomcat,了解一般的配置,熟悉常用的服务器性能监控方法和原理,熟悉常用的counter;

    8. 至少熟悉TCP/IP协议,熟悉HTTP协议,至少见过并了解三层、四层交换或者路由器的使用和配置。了解常用的与网络性能相关的counter;

    9. 了解一般的大型企业应用的部署架构和应用架构;

    10. 了解知名大型web应用、高并发量、高流量、实时响应要求高的超大规模网站的架构和优化历程;

    11. 熟悉统计学的基础知识、常用分析方法以及实验设计方法,了解数学建模相关的知识;

    12. 熟悉专属行业的业务知识和用户场景,例如电信行业的OSS系统所涉及的业务知识和用户场景,证券交易系统所涉及的业务知识和用户场景;

    13. 大量的实际性能测试及优化经验;

    14. 积极的参与到各类圈子、社团的讨论和交流、分享中。

  • 路由器六大测试详解

    2008-10-20 17:44:20

    路由器是IP网络的核心设备,其性能的好坏直接影响IP网网络规模、网络稳定性以及网络可扩展性。路由器区别于一般简单的网络互连设备,在性能测试时还应该加上路由器特有的性能测试。

      路由器是IP网络的核心设备,其性能的好坏直接影响IP网网络规模、网络稳定性以及网络可扩展性。路由器区别于一般简单的网络互连设备,在性能测试时还应该加上路由器特有的性能测试。路由器在计算机网络中有着举足轻重的地位,是计算机网络的桥梁。通过它不仅可以连通不同的网络,还能选择数据传送的路径,并能阻隔非法的访问。路由器的配置对初学者来说,并不是件十分容易的事。

      (一)功能测试

      路由器功能通常可以划分为如下方面。

      (1)接口功能:该功能用作将路由器连接到网络。可以分为局域网接口及广域网接口两种。局域网接口主要包括以太网、令牌环、令牌总线、FDDI等网络接口。广域网接口主要包括E1/T1、E3/T3、DS3、通用串行口(可转换成X.21DTE/DCE、V.35DTE/DCE、RS232DTE/DCE、RS449DTE/DCE、EIA530DTE)等网络接口。(2)通信协议功能:该功能负责处理通信协议,可以包括TCP/IP、PPP、X.25、帧中继等协议。(3)数据包转发功能:该功能主要负责按照路由表内容在各端口(包括逻辑端口)间转发数据包并且改写链路层数据包头信息。(4)路由信息维护功能:该功能负责运行路由协议,维护路由表。路由协议可包括RIP、OSPF、BGP等协议。(5)管理控制功能:路由器管理控制功能包括五个功能,SNMP代理功能,Telnet服务器功能,本地管理、远端监控和RMON功能。通过多种不同的途径对路由器进行控制管理,并且允许纪录日志。(6)安全功能:用于完成数据包过滤,地址转换,访问控制,数据加密,防火墙,地址分配等功能。

      路由器对上述功能并非必要完全实现。但是由于路由器作为网络设备,存在最小功能集,对最小功能集所规定的功能,路由器必须支持。因为绝大多数功能测试可以由接口测试、性能测试、协议一致性测试和网管测试所函盖,所以路由器功能测试一般可以只对其他测试无法涵盖的功能作验证性测试。路由器功能测试一般采用远端测试法。

      (二)性能测试

      路由器是IP网络的核心设备,其性能的好坏直接影响IP网网络规模、网络稳定性以及网络可扩展性。由于IETF没有对路由器性能测试作专门规定,一般来说只能按照RFC2544( Benchmarking Methodology for Network Interconnect Devices)作测试。但路由器区别于一般简单的网络互连设备,在性能测试时还应该加上路由器特有的性能测试。例如路由表容量、路由协议收敛时间等指标。

      路由器性能测试应当包括下列指标。

      (1)吞吐量:测试路由器包转发的能力。通常指路由器在不丢包条件下每秒转发包的极限,一般可以采用二分法查找该极限点。(2)时延:测试路由器在吞吐量范围内从收到包到转发出该包的时间间隔。时延测试应当重复20次然后取其平均值。(3)丢包率:测试路由器在不同负荷下丢弃包占收到包的比例。不同负荷通常指从吞吐量测试到线速(线路上传输包的最高速率),步长一般使用线速的10%。(4)背靠背帧数:测试路由器在接收到以最小包间隔传输时不丢包条件下所能处理的最大包数。该测试实际考验路由器缓存能力,如果路由器具备线速能力(吞吐量=接口媒体线速),则该测试没有意义。(5)系统恢复时间:测试路由器在过载后恢复正常工作的时间。测试方法可以采用向路由器端口发送吞吐量110%和线速间的较小值,持续60秒后将速率下降到50%的时刻到最后一个丢包的时间间隔。如果路由器具备线速能力,则该测试没有意义。(6)系统复位:测试路由器从软件复位或关电重启到正常工作的时间间隔。正常工作指能以吞吐量转发数据。

      在测试上述RFC2544中规定的指标时应当考虑下列因素。

      帧格式:建议按照RFC2544所规定的帧格式测试;帧长:从最小帧长到MTU顺序递增,例如在以太网上采用64, 128, 256, 512, 1024, 1280, 1518字节;认证接收帧:排除收到的非测试帧,例如控制帧、路由更新帧等;广播帧:验证广播帧对路由器性能的影响,上述测试后在测试帧中夹杂1%广播帧再测试;管理帧:验证管理帧对路由器性能的影响,上述测试后在测试帧中夹杂每秒一个管理帧再测试;路由更新:路由更新即下一跳端口改变对性能的影响;过滤器:在设置过滤器条件下对路由器性能的影响,建议设置25个过滤条件测试;协议地址:测试路由器收到随机处于256个网络中的地址时对性能的影响;双向流量:测试路由器端口双向收发数据对性能的影响;多端口测试:考虑流量全连接分布或非全连接分布对性能的影响;多协议测试:考虑路由器同时处理多种协议对性能的影响;混合包长:除测试所建议的递增包长外,检查混合包长对路由器性能的影响,RFC2544除要求包含所有测试包长外没有对混合包长中各包长所占比例作规定。笔者建议按照实际网络中各包长的分布测试,例如在没有特殊应用要求时以太网接口上可采用60字节包50%,128字节包10%,256字节包15%,512字节包10%,1500字节包15%。除上述RFC2544建议的测试项外还建议测试如下内容。

      ①路由震荡:路由震荡对路由器转发能力的影响。路由震荡程度即每秒更新路由的数量可以依据网络条件而定。路由更新协议可采用BGP。②路由表容量:测试路由表大小。骨干网路由器通常运行BGP,路由表包含全球路由。一般来说要求超过10万条路由,建议通过采用BGP输入导出路由计数来测试。③时钟同步:在包含相应端口例如POS口的路由器上测试内钟精度以及同步能力。④协议收敛时间:测试路由变化通知到全网所用时间。该指标虽然与路由器单机性能有关,但是一般只能在网络上测试,而且会因配置改变而变化。可以在网络配置完成后通过检查该指标来衡量全网性能。测试时间应当根据具体项目以及测试目标而定。一般认为测试时间应当介于60秒到300秒之间。另外一般可以根据用户要求和测试目标作设定选择。路由器性能测试一般可采用远端测试法。

    (三)一致性测试

      路由器一致性测试通常采用“黑箱”方法,被测试设备IUT叫做“黑箱”。测试系统通过控制观察点PCO与被测试设备接口。

      不同的测试事件是通过不同的PCO来控制和观察的,按照其应答是否遵守规范,即定时关系和数据匹配限制,测试的结果可分为通过、失败、无结果3种。路由器是一种复杂的网络互连设备,需要在各个通信层上实现多种协议。例如相应的接口的物理层和链路层协议、IP/ICMP等互联网层协议、TCP/UDP等传输层协议、Telnet/SNMP等应用层协议以及RIP/OSPF/BGP等路由协议。

      协议一致性测试应当包含路由器所实现的所有协议。由于该测试内容繁多测试复杂,在测试中可以选择重要的协议以及所关心的内容测试。由于骨干网上路有器可能影响全球路由,所以在路由器测试中应特别重视路由协议一致性测试例如OSPF和BGP协议。由于一致性测试只能选择有限测试例测试,一般无法涵盖协议所有内容。所以即使通过测试也无法保证设备完全实现协议所有内容,所以最好的办法是在现实环境中试运行。路由器一致性测试一般采用分布式测试法或远端测试法。

      (四)互操作测试

      由于通信协议、路由协议非常复杂且拥有众多选项,实现同一协议的路由器并不能保证互通互操作。并且因为一致性测试能力有限,即使通过协议一致性测试也未必能保证完全实现协议。所以有必要对设备进行互操作测试。

      互操作测试实际上是将一致性测试中所用的仪表替换成需要与之互通互操作的设备,选择一些重要且典型的互连方式配置,观察两设备是否能按照预期正常工作。

      (五)稳定性、可靠性测试

      由于大多数路由器需要每天24小时,每周7天连续工作,作为Internet核心设备的骨干路由器的稳定性和可靠性尤其重要。所以用户需要了解露由器的稳定性和可靠性。

      路由器的稳定性和可靠性很难测试。一般可以通过两种途径的到:(1)厂家通过关键部件的可靠性以及备份程度计算系统可靠性;(2)用户或厂家通过大量相同产品使用中的故障率统计产品稳定性和可靠性。当然,用户也可以通过在一定时间内对试运行结果的要求来在一定程度上保证路由器的可靠性与稳定性。

      (六)网管测试

      网管测试一般测试网管软件对网络以及网络上设备的管理能力。由于路由器是IP网的核心设备,所以必须测试路由器对网管的支持度。如果路由器附带网管软件,可以通过使用所附带的网管软件来检查网管软件所实现的配置管理、安全管理、性能管理、计帐管理、故障管理、拓扑管理和视图管理等功能。如果路由器不附带网管软件,则应当测试路由器对SNMP协议实现的一致性以及对MIB实现的程度。由于路由器需要实现的MIB非常多,每个MIB都包含大量内容,很难对MIB实现完全测试。一般可以通过抽测重要的MIB项来检查路由器对MIB的实现情况。

  • 软件测试流程

    2008-10-18 16:31:24

    一、 新产品或工程管理流程
    1、 需求调研
    在软件需求分析阶段,测试人员从软件生命周期的需求阶段就开始介入在需求阶段的测试人员参与软件需求调研,以测试角度分析需求的可测性,可构思将来对其测试的方法、原则等;同时全面了解系统需求,从客户角度考虑软件测试需要达到的验证状态,即何些功能点需重点测试、何些无需,以便将来制定测试计划。
    2、 制定测试计划
    进行每一种测试之前,测试负责人要根据“产品定义书”及“总体设计说明”和“详细设计文档”制定“测试计划”,制定总体的测试计划,详细阐明本次测试目的、对象、方法、范围、过程、环境要求、接受标准以及测试人员和测试时间等内容,“测试计划”经过审查通过,才能实施。
    3、 需求Review
    开发在完成软件需求分析之后,会提交需求分析文档,测试人员根据需求调研所了解的需求以及产品需求说明文档等资料,对需求分析文档进行Review,检查文档是否满足了需求,是否与需求一致等等。
    4、 设计Review
    在软件分析设计阶段,测试人员参与设计讨论,了解系统的实现方式和原理,并对概要设计和详细设计提出自己的见解。设计结束之后,开发提交概要设计文档和详细设计文档,测试人员对设计进行Review,检查设计规划和实现方案是否合理,如果不合理,存在的问题是什么、如何改进等等。
    5、 测试设计
    在设计测试方案时,首先分解测试内容,对于一个复杂系统,通常可以分解成几个互相独立的子系统,正确地划分这些子系统及其逻辑组成部分和相互间的关系,可以降低测试的复杂性,减少重复和遗漏,也便于设计和开发测试用例,有效的组织测试,将系统分析人员的开发分析文档加工成以测试为角度的功能点分析文档,重要的是描述对系统分解后每个功能点逐一的校验描述,包括何种方法测试、何种数据测试、期望测试结果等。然后以功能点分析文档作为依据进行测试用例的设计,设计测试用例是关系到测试效果以至软件质量的关键性一步,也是一项非常细致的工作,根据对具体的北侧系统的分析和测试要求,逐步细化测试的范围和内容,设计具体的测试过程和数据,同时将结果写成可以按步执行的测试文档。每个测试用例必须包括以下几个部分:
    (1) 标题和编号
    (2) 测试的目标和目的
    (3) 输入和使用的数据和操作过程
    (4) 期望的输出结果
    (5) 其他特殊的环境要求、次序要求、时间要求等
    6、开发测试工具和准备测试数据
       在软件测试中,为了提高测试工作的效益和质量,只要条件许可,应尽可能采用计算机自动或半自动测试的方法,利用软件工具本身的优势来提高工作效率。
    7、测试执行
    当所有必需的测试准备工作都已完成,并且产品已经开发完毕并提交测试,则可以按照预定的测试计划和测试方案逐项进行测试。在测试过程中发现的任何与预期目标不符的现象和问题都必须详细记录下来,填写测试记录。为了能准确的找出问题产生的原因,及时的解决问题,保证测试工作的顺利进行,一般来说所发现的问题必须是能够重视的。
    8、回归测试
       在测试中发现的任何问题和错误都必须有一个明确的解决方法。一般来说,经过修改的软件可能仍然包含着错误,甚至引入了新的错误,因此,对于修改以后的程序和文档,按照修改的方法和影响的范围,必须重新进行有关的测试。另一方面,对于版本更新后的软件也必须进行同样的测试过程。
    9、测试分析报告
       测试结束后要及时地进行总结,对测试结果进行分析,由测试负责人提交“测试分析报告”。
    10、产品发布
       测试完毕,整理产品发布包和相关文档并发布。对于新产品来说,必要的文档必须包括:
    (1) 安装操作手册
    (2) 产品白皮书
    (3) 管理维护手册
    (4) 用户操作手册
    (5) 测试报告
    11、版本控制
    新版本软件发布之后,马上对代码进行质量控制。
    (1) Build Master给新版本的源代码打一个cvs tag,方便代码回滚check out。比如,发布版本为p2p3.3.2,则给该软件源代码也打一个与发布版本相同名字的tag p2p3.3.2。这样做的一个好处是,在目前的软件的基础上做了修改并发布新的版本后,如果需要check out某个版本的源代码,则可以通过这个版本的tag来check out,代码的修改可以在该版本上进行。
    (2) Build Master对新发布的软件源代码进行cvs lock,不允许开发人员在软件发布之后commit源代码,直到有新版本需求修改再给开发人员开放commit权限。这样做的好处是避免开发人员随意修改和commit源代码,确保源代码服务器上的源版本版本与当前最新的发布版本一致。
    二、 工程维护管理流程
    1、 收集新需求:新功能和不紧急的故障,其代码的修改操作不必马上进行,取而代之的是做好新需求与故障统计;对已经确认的故障也可以先在bug管理系统报bug,但只是记录,不需求马上修改。当然了,对于紧急的工程故障,需要马上修改和测试。
    2、 确认新需求:与工程人员或客户或产品经理确认新需求,确保需求被理解正确。
    3、 需求讨论:当需求与故障积累到一定数量或者工程有新版本需求,进行一次发布测试,在新版本开始修改之前把近期积累的需求与故障整理,与相关开发人员、测试人员、项目经理和测试经理讨论,确认哪些新功能可以实现、新功能的实现方法与业务流程、新功能开发修改时间、测试版本、测试时间与发布时间。
    4、 在bug跟踪管理系统报bug:确认所有需要修改的新功能和需求录入bug跟踪管理系统,并在bug跟踪管理系统中详细描述新功能需求和解决方法,同时整理相关bug列表,交付开发修改。
    5、 制定测试计划:
    A、 根据用户需求,定义并完善测试需求,作为测试的标准
    B、 确定重点测试事项,哪些功能需要重点测试
    C、 测试时间计划,并详细计划具体测试任务与时间
    D、 风险说明
    E、 测试准备,提前对测试环境和测试资源进行准备
    F、 发布具体时间
    G、 资源需求:包括测试人员、硬件需求、软件需求和培训计划
    6、 编写测试案例:根据功能需求编写测试案例
    7、 测试开发:开发自动测试脚本,补充自动测试案例
    8、 测试实施:按照测试计划进行测试,发现并申报bug
    9、 测试评估:
    A、 哪些需求通过了测试
    B、 有哪些遗留问题
    C、 测试效率评估
    D、 开发质量度量和评估
    E、 并根据评估编写测试报告
    10、 发布新版本:
    A、 编写新功能文档,给工程提供新功能说明
    B、 编写升级文档,给工程提供升级参考方案
    C、 软件发布,包括新版本软件、新功能文档、升级文档和测试报告
    11、 代码版本控制:新版本软件发布之后,马上对代码进行质量控制。
    A、 Build Master给新版本的源代码打一个cvs tag,方便代码回滚check out。比如,发布版本为p2p3.3.2,则给该软件源代码也打一个与发布版本相同名字的tag p2p3.3.2。这样做的一个好处是,在目前的软件的基础上做了修改并发布新的版本后,如果需要check out某个版本的源代码,则可以通过这个版本的tag来check out,代码的修改可以在该版本上进行。
    B、 Build Master对新发布的软件源代码进行cvs lock,不允许开发人员在软件发布之后commit源代码,直到有新版本需求修改再给开发人员开放commit权限。这样做的好处是避免开发人员随意修改和commit源代码,确保源代码服务器上的源版本版本与当前最新的发布版本一致。
  • JSP的特点和其它动态网页开发技术比较

    2008-10-18 16:26:43

    【转载】JSP的特点和其它动态网页开发技术比较
    JSP技术特点:

    1.将内容的生成和显示进行分离

    使用JSP技术,Web页面开发人员可以使用HTML或者XML标识来设计和格式化最终页面。使用JSP标识或者小脚本来生成页面上的动态内容。生成内容的逻辑被封装在标识和JavaBeans组件中,并且捆绑在小脚本中,所有的脚本在服务器端运行。如果核心逻辑被封装在标识和Beans中,那么其他人,如Web管理人员和页面设计者,能够编辑和使用JSP页面,而不影响内容的生成。

    在服务器端,JSP引擎解释JSP标识和小脚本,生成所请求的内容(例如,通过访问JavaBeans组件,使用JDBCTM技术访问数据库,或者包含文件),并且将结果以HTML(或者XML)页面的形式发送回浏览器。这有助于作者保护自己的代码,而又保证任何基于HTML的Web浏览器的完全可用性。

     2.强调可重用的组件

    绝大多数JSP页面依赖于可重用的,跨平台的组件(JavaBeans或者Enterprise JavaBeansTM组件)来执行应用程序所要求的更为复杂的处理。开发人员能够共享和交换执 行普通操作的组件,或者使得这些组件为更多的使用者或者客户团体所使用。基于组件的方法加速了总体开发过程,并且使得各种组织在他们现有的技能和优化结果的开发努力中得到平衡。

    3.采用标识简化页面开发

    Web页面开发人员不会都是熟悉脚本语言的编程人员。JavaServer Page技术封装了许多功能,这些功能是在易用的、与JSP相关的XML标识中进行动态内容生成所需要的。

    标准的JSP标识能够访问和实例化JavaBeans组件,设置或者检索组件属性,下载Applet,以及执行用其他方法更难于编码和耗时的功能。通过开发定制化标识库,JSP技术是可以扩展的。今后,第三方开发人员和其他人员可以为常用功能创建自己的标识库。这使得Web页面开发人员能够使用熟悉的工具和如同标识一样的执行特定功能的构件来工作。

    JSP技术很容易整合到多种应用体系结构中,以利用现存的工具和技巧,并且扩展到能够支持企业级的分布式应用。作为采用Java技术家族的一部分,以及Java 2(企业版体系结构)的一个组成部分,JSP技术能够支持高度复杂的基于Web的应用。

    由于JSP页面的内置脚本语言是基于Java编程语言的,而且所有的JSP页面都被编译成为Java Servlet,JSP页面就具有Java技术的所有好处,包括健壮的存储管理和安全性。

    作为Java平台的一部分,JSP拥有Java编程语言“一次编写,各处运行”的特点。随着越来越多的供应商将JSP支持添加到他们的产品中,您可以使用自己所选择的服务器和工具,更改工具或服务器并不影响当前的应用。

    与其它动态网页技术的比较:
    与传统的CGI方式相比

     

    a. 后台实现逻辑是基于Java Component的,具有跨平台的特点

    b. 将应用逻辑与页面表现分离,使得应用逻辑能够最大程度得到复用,从而提高开发效率

    c. 运行比CGI方式高,尤其对于数据库访问时,提供了连接池缓冲机制,使运行所需资源最小

    d. 安全,由于后台是完全基于Java技术的,安全性由Java的安全机制予以保障

    e. 由于与ASP很近似,不需要太多的编程知识就可以动手编写JSP

    f. 内置支持XML,使用XML从而使页面具有更强的表现力和减少编程工作量

     

    与Asp和php的比较

     

    目前,最常用的三种动态网页语言有ASP(Active Server Pages),JSP(Java Server Pges),PHP (Hypertext Preprocessor)。

     

    ASP全名Active Server Pages,是一个WEB服务器端的开发环境, 利用它可以产生和运行动态的、交互的、高性能的WEB服务应用程序。ASP采用脚本语言VB scrīpt(Java scrīpt)作为自己的开发语言。

     

    PHP是一种跨平台的服务器端的嵌入式脚本语言. 它大量地借用C,Java和Perl语言的语法, 并耦合PHP自己的特性,使WEB开发者能够快速地写出动态生成页面.它支持目前绝多数数据库。还有一点,PHP是完全免费的,不用花钱,你可以从PHP官方站点(http://www.php.net)自由下载。而且你可以不受限制地获得源码,甚至可以从中加进你自己需要的特色。

     

    JSP 是Sun公司推出的新一代站点开发语言,他完全解决了目前ASP,PHP的一个通病--脚本级执行(据说PHP4 也已经在Zend 的支持下,实现编译运行).Sun 公司借助自己在Java 上的不凡造诣,将Java 从Java 应用程序 和 Java Applet 之外,又有新的硕果,就是Jsp--Java Server Page。Jsp 可以在Serverlet和JavaBean的支持下,完成功能强大的站点程序。

     

    三者都提供在 HTML 代码中混合某种程序代码、由语言引擎解释执行程序代码的能力。但JSP代码被编译成 Servlet 并由 Java 虚拟机解释执行,这种编译操作仅在对 JSP页面的第一次请求时发生。在 ASP 、PHP、JSP 环境下, HTML 代码主要负责描述信息的显示样式,而程序代码则用来描述处理逻辑。普通的 HTML 页面只依赖于 Web 服务器,而 ASP 、PHP、JSP 页面需要附加的语言引擎分析和执行程序代码。程序代码的执行结果被重新嵌入到 HTML 代码中,然后一起发送给浏览器。 ASP 、PHP、 JSP三者都是面向 Web 服务器的技术,客户端浏览器不需要任何附加的软件支持。

     

    JSP vs ASP

     

    JSP跨平台,而且支持Apache, Netscape, IIS,IBM Http Server在内的所有主流Web Server (市场份额在85%以上),而ASP目前只支持NT+IIS(市场份额在20%左右);提供了更好的安全机制,这对于e-business这样的应用来说是至关重要的; JSP可以跨操作系统、Web Server和应用服务器,而ASP只限于NT+IIS;

     

    JSP是一个开放的标准,得到了Oracle, Netscape, IBM & WebLogic, Inprise等的支持;JSP的组件编写更为容易,而且JSP的性能由于ASP;

     

    JSP vs PHP

     

    JSP是一个业界标准,得到Sun,IBM,Oracle,BEA,Apache等 的支持,PHP只是一个开发组织并不强的free ware ;PHP的性能不好,是解释型的,JSP采用JIT编译后,和c不相上下,而且支持多线程; JSP支持的平台众多,从Win98,NT,Unix,Linux,FreeBSD到AS/400,OS/390,而PHP支持的平台有限; JSP可以利用JDBC和众多主流关系数据库连接,而PHP目前只支持MySql和Oracle等有限的几种; JSP中的组件,JavaBean和EJB开发非常容易,而且还可以在JSP中使用Java所有的类和功能。而PHP只能用C写一些功能有限的组件,而且编写较为复杂; 利用JSP可以支持EJB,以支持Transaction和CORBA标准,而且还可以支持LDAP,Message等服务,使得访问ERP,CICS,MQ等企业应用非常容易。而PHP在这方面先天不足,所以对于电子商务这样的Mission-critical的应用来说,PHP并不适合。

     

    性能比较

     

    有人做过试验,对这三种语言分别做循环性能测试及存取Oracle数据库测试。在循环性能测试中,JSP只用了令人吃惊的四秒钟就结束了20000*20000的循环。而ASP、PHP测试的是2000*2000循环(少一个数量级),却分别用了63秒和84秒。

     

    数据库测试中,三者分别对 Oracle 8 进行 1000 次 Insert,Update,Select,和Delete: Jsp 需要 13 秒,Php 需要 69 秒,ASP则 需要 73 秒。

     

    前景分析

     

    目前在国内PHP与ASP应用最为广泛。而JSP由于是一种较新的技术,国内采用的较少。但在国外,JSP已经是比较流行的一种技术,尤其是电子商务类的网站,多采用JSP。

     

    采用PHP的网站如新浪网(sina)、中国人(Chinaren)等,但由于PHP本身存在的一些缺点,使得它不适合应用于大型电子商务站点,而更适合一些小型的商业站点。

     

    首先,PHP缺乏规模支持。其次,缺乏多层结构支持。对于大负荷站点,解决方法只有一个:分布计算。数据库、应用逻辑层、表示逻辑层彼此分开,而且同层也可以根据流量分开,组成二维阵列。而PHP则缺乏这种支持。还有上面提到过的一点,PHP提供的数据库接口支持不统一,这就使得它不适合运用在电子商务中。

     

    ASP和JSP则没有以上缺陷,ASP可以通过Microsoft Windowsd的COM/DCOM获得ActiveX规模支持,通过DCOM和Transcation Server获得结构支持;JSP可以通过SUN Java的Java Class和EJB获得规模支持,通过EJB/CORBA以及众多厂商的Application Server获得结构支持。

     

    三者中,JSP应该是未来发展的趋势。世界上一些大的电子商务解决方案提供商都采用JSP/Servlet。比较出名的如IBM的E-business,它的核心是采用JSP/Servlet的WebSphere;西方另外一个非常著名的电子商务软件提供商,Intershop。它原来的产品Intershop1 2, 3, 4占据了主要的电子商务软件份额。它们都是通过CGI来提供支持 的。但去年10月后它推出了Enfinity,一个采用JSP/Servlet的电子商务Application Server,而且声言不再开发传统软件。

     

    JSP应用范围:

     

    JSP同PHP类似,几乎可以运行于所有平台。如Win NT,Linux,Unix. NT下IIS通过一 个插件,例如JRUN或者ServletExec,就能支持JSP。著名的Web服务器Apache已经能够支持JSP。由于Apache广泛应用在NT、Unix和Linux上,因此JSP有更广泛的运行平台。虽然现在NT操作系统占了很大的市场份额,但是在服务器方面Unix的优势仍然很大,而新崛起的Linux更是来势不小。从一个平台移植到另外一个平台,JSP和JavaBean甚至不用重新编译,因为Java字节码都是标准的与平台无关的。

     

  • 完全优化MySQL数据库性能的八大巧方法

    2008-10-18 16:18:49

    1、选取最适用的字段属性
            MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。例如,在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任务了。同样的,如果可以的话,我们应该使用MEDIUMINT而不是BIGIN来定义整型字段。

      另外一个提高效率的方法是在可能的情况下,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。

      对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。

      2、使用连接(JOIN)来代替子查询(Sub-Queries)

      MySQL从4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。例如,我们要将客户基本信息表中没有任何订单的客户删除掉,就可以利用子查询先从销售信息表中将所有发出订单的客户ID取出来,然后将结果传递给主查询,如下所示:

      DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )

      使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询可以被更有效率的连接(JOIN).. 替代。例如,假设我们要将所有没有订单记录的用户取出来,可以用下面这个查询完成:

      SELECT * FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )

      如果使用连接(JOIN).. 来完成这个查询工作,速度将会快很多。尤其是当salesinfo表中对CustomerID建有索引的话,性能将会更好,查询如下:

      SELECT * FROM customerinfo LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHERE salesinfo.CustomerID IS NULL

      连接(JOIN).. 之所以更有效率一些,是因为 MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。

      3、使用联合(UNION)来代替手动创建的临时表

      MySQL 从 4.0 的版本开始支持 UNION 查询,它可以把需要使用临时表的两条或更多的 SELECT 查询合并的一个查询中。在客户端的查询会话结束的时候,临时表会被自动删除,从而保证数据库整齐、高效。使用 UNION 来创建查询的时候,我们只需要用 UNION作为关键字把多个 SELECT 语句连接起来就可以了,要注意的是所有 SELECT 语句中的字段数目要想同。下面的例子就演示了一个使用 UNION的查询。

      SELECT Name, Phone FROM client UNION SELECT Name, BirthDate FROM author
      UNION
      SELECT Name, Supplier FROM product

      4、事务

      尽管我们可以使用子查询(Sub-Queries)、连接(JOIN)和联合(UNION)来创建各种各样的查询,但不是所有的数据库操作都可以只用一条或少数几条SQL语句就可以完成的。更多的时候是需要用到一系列的语句来完成某种工作。但是在这种情况下,当这个语句块中的某一条语句运行出错的时候,整个语句块的操作就会变得不确定起来。设想一下,要把某个数据同时插入两个相关联的表中,可能会出现这样的情况:第一个表中成功更新后,数据库突然出现意外状况,造成第二个表中的操作没有完成,这样,就会造成数据的不完整,甚至会破坏数据库中的数据。要避免这种情况,就应该使用事务,它的作用是:要么语句块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的一致性和完整性。事物以BEGIN 关键字开始,COMMIT关键字结束。在这之间的一条SQL操作失败,那么,ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。

      BEGIN;

      INSERT INTO salesinfo SET CustomerID=14;

      UPDATE inventory SET Quantity=11

      WHERE item='book';

      COMMIT;

      事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。

      5、锁定表

      尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。由于在事务执行的过程中,数据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户

      来使用,事务造成的影响不会成为一个太大的问题;但假设有成千上万的用户同时访问一个数据库系统,例如访问一个电子商务网站,就会产生比较严重的响应延迟。

      其实,有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务的功能。

      LOCK TABLE inventory WRITE
      SELECT Quantity FROM inventory
      WHEREItem='book';
      ...

      UPDATE inventory SET Quantity=11
      WHEREItem='book';
      UNLOCK TABLES

      这里,我们用一个 SELECT 语句取出初始数据,通过一些计算,用 UPDATE 语句将新值更新到表中。包含有 WRITE 关键字的 LOCK TABLE 语句可以保证在 UNLOCK TABLES 命令被执行之前,不会有其它的访问来对 inventory 进行插入、更新或者删除的操作。

      6、使用外键

      锁定表的方法可以维护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。例如,外键可以保证每一条销售记录都指向某一个存在的客户。在这里,外键可以把customerinfo 表中的CustomerID映射到salesinfo表中CustomerID,任何一条没有合法CustomerID的记录都不会被更新或插入到salesinfo中。

      CREATE TABLE customerinfo
      (
       CustomerID INT NOT NULL ,
       PRIMARY KEY ( CustomerID )
      ) TYPE = INNODB;
      CREATE TABLE salesinfo
      (
       SalesID INT NOT NULL,
       CustomerID INT NOT NULL,
       PRIMARY KEY(CustomerID, SalesID),
       FOREIGN KEY (CustomerID) REFERENCES customerinfo
       (CustomerID) ON DELETECASCADE
      ) TYPE = INNODB;

      注意例子中的参数“ON DELETE CASCADE”。该参数保证当 customerinfo 表中的一条客户记录被删除的时候,salesinfo 表中所有与该客户相关的记录也会被自动删除。如果要在 MySQL 中使用外键,一定要记住在创建表的时候将表的类型定义为事务安全表 InnoDB类型。该类型不是 MySQL 表的默认类型。定义的方法是在 CREATE TABLE 语句中加上 TYPE=INNODB。如例中所示。

      7、使用索引

      索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(), MIN()和ORDERBY这些命令的时候,性能提高更为明显。那该对哪些字段建立索引呢?一般说来,索引应建立在那些将用于JOIN, WHERE判断和ORDER BY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说,出现大量重复值是很有可能的情况,例如customerinfo中的“province”.. 字段,在这样的字段上建立索引将不会有什么帮助;相反,还有可能降低数据库的性能。我们在创建表的时候可以同时创建合适的索引,也可以使用ALTER TABLE或CREATE INDEX在以后创建索引。此外,MySQL

      从版本3.23.23开始支持全文索引和搜索。全文索引在MySQL 中是一个FULLTEXT类型索引,但仅能用于MyISAM 类型的表。对于一个大的数据库,将数据装载到一个没有FULLTEXT索引的表中,然后再使用ALTER TABLE或CREATE INDEX创建索引,将是非常快的。但如果将数据装载到一个已经有FULLTEXT索引的表中,执行过程将会非常慢。

      8、优化的查询语句

      绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。下面是应该注意的几个方面。首先,最好是在相同类型的字段间进行比较的操作。在MySQL 3.23版之前,这甚至是一个必须的条件。例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较。其次,在建有索引的字段上尽量不要使用函数进行操作。

      例如,在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。所以,下面的两个查询虽然返回的结果一样,但后者要比前者快得多。

      SELECT * FROM order WHERE YEAR(OrderDate)<2001;
      SELECT * FROM order WHERE OrderDate<"2001-01-01";

      同样的情形也会发生在对数值型字段进行计算的时候:

      SELECT * FROM inventory WHERE Amount/7<24;
      SELECT * FROM inventory WHERE Amount<24*7;

      上面的两个查询也是返回相同的结果,但后面的查询将比前面的一个快很多。第三,在搜索字符型字段时,我们有时会使用 LIKE 关键字和通配符,这种做法虽然简单,但却也是以牺牲系统性能为代价的。例如下面的查询将会比较表中的每一条记录。

      SELECT * FROM books
      WHERE name like "MySQL%"

      但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:

      SELECT * FROM books
      WHERE name>="MySQL"and name<"MySQM"

      最后,应该注意避免在查询中让MySQL进行自动类型转换,因为转换过程也会使索引变得不起作用。

  • Oracle新手最常碰到的6个错误及解决方案

    2008-10-18 16:07:31

    没有人会否认Oracle是全球最有影响的数据库产品之一;不过好的东西似乎总不是那么好用(初看起来如此),甚至有些无情--总会给layman们一个个无情的错误号。下面是我个人的总结,条条有用,希望能给初学者一点启示。

    关于“好的东西似乎总不是那么好用(初看起来如此)”的一个笑话:在参加 IBM DB2 512、513培训前,在校园网上下载到了安装程序,不过任凭我们几个同学研究个半天,也不知哪个文件是安装文件,竟没有安装成功。最后,一致认为:看来这个培训真是太有必要了!事后,才知道--我们下载的是4linux的!

    1、ORA-12541:TNS:没有监听器

    原因:没有启动监听器或者监听器损坏。如果是前者,使用命令net start OracleOraHome81TNSListener(名字可能有出入)即可;如果是后者,则使用“Net8 Configuration Assistant”工具向导之“监听程序配置”增加一个监听器即可(基本不用写任何信息,一路OK。在添加之前可能需要把所有的监听器先删除!)

    2、ORA-12500:TNS:监听程序无法启动专用服务器进程

    ORA-12560:TNS:协议适配器错误

    原因:ORACLE的数据库服务没有启动。使用命令net start ORACLESERVICEORADB(ORADB为数据库名字)即可。如果仍没有解决,请继续向下看。

    3、如果数据库服务启动失败,则很有可能是其注册表项值损坏,最好的做法是以下两步:

    1)ORADIM -DELETE -SID oradb 删除数据库服务项

    2)ORADIM -NEW -SID oradb 新增数据库服务项

      注:这个过程中如果出错,就重启计算机!

    4、ORA-12154:TNS:能解析服务名

    原因:ORACLE的网络服务名没有正确配置。请使用“Net8 Configuration Assistant”工具向导之“本地网络服务名配置”配置TNS即可。如果仍没有解决,请继续向下看。

    5、ORA-1034 :TNS:ORACLE不可用

    原因:ORACLE的数据库服务正确启动,但是数据库没有打开!

    使用命令:

      1)svrmgrl 启动服务管理器

      2)connect internal 以internal身份登陆

      3)startup 打开数据库

    6、ORA-12560:TNS:协议适配器错误(顽固性的)

    原因:未知。

    解决:必杀技--打开“Windows任务管理器”,杀死ORACLE.exe及ORADIM.exe进程,书写自己的ora_startup.bat,执行之!

     

     

  • Tomcat集群与负载均衡

    2008-10-11 15:01:21

    在进入集群系统架构探讨之前,先定义一些专门术语:
    1. 集群(Cluster):是一组独立的计算机系统构成一个松耦合的多处理器系统,它们之间通过网络实现进程间的通信。应用程序可以通过网络共享内存进行消息传送,实现分布式计算机。
    2. 负载均衡(Load Balance):先得从集群讲起,集群就是一组连在一起的计算机,从外部看它是一个系统,各节点可以是不同的操作系统或不同硬件构成的计算机。如一个提供Web服务的集群,对外界来看是一个大Web服务器。不过集群的节点也可以单独提供服务。
    3. 特点:在现有网络结构之上,负载均衡提供了一种廉价有效的方法扩展服务器带宽和增加吞吐量,加强网络数据处理能力,提高网络的灵活性和可用性。集群系统(Cluster)主要解决下面几个问题:
    高可靠性(HA):利用集群管理软件,当主服务器故障时,备份服务器能够自动接管主服务器的工作,并及时切换过去,以实现对用户的不间断服务。
    高性能计算(HP):即充分利用集群中的每一台计算机的资源,实现复杂运算的并行处理,通常用于科学计算领域,比如基因分析,化学分析等。
    负载平衡:即把负载压力根据某种算法合理分配到集群中的每一台计算机上,以减轻主服务器的压力,降低对主服务器的硬件和软件要求。

    目前比较常用的负载均衡技术主要有:
      1. 基于DNS的负载均衡
      通过DNS服务中的随机名字解析来实现负载均衡,在DNS服务器中,可以为多个不同的地址配置同一个名字,而最终查询这个名字的客户机将在解析这个名字时得到其中一个地址。因此,对于同一个名字,不同的客户机会得到不同的地址,他们也就访问不同地址上的Web服务器,从而达到负载均衡的目的。

      2. 反向代理负载均衡 (如Apache+JK2+Tomcat这种组合)
      使用代理服务器可以将请求转发给内部的Web服务器,让代理服务器将请求均匀地转发给多台内部Web服务器之一上,从而达到负载均衡的目的。这种代理方式与普通的代理方式有所不同,标准代理方式是客户使用代理访问多个外部Web服务器,而这种代理方式是多个客户使用它访问内部Web服务器,因此也被称为反向代理模式。

      3. 基于NAT(Network Address Translation)的负载均衡技术 (如Linux Virtual Server,简称LVS)
      网络地址转换为在内部地址和外部地址之间进行转换,以便具备内部地址的计算机能访问外部网络,而当外部网络中的计算机访问地址转换网关拥有的某一外部地址时,地址转换网关能将其转发到一个映射的内部地址上。因此如果地址转换网关能将每个连接均匀转换为不同的内部服务器地址,此后外部网络中的计算机就各自与自己转换得到的地址上服务器进行通信,从而达到负载分担的目的。

    介绍完上面的集群技术之后,下面就基于Tomcat的集群架构方案进行说明:

    上面是采用了Apache httpd作为web服务器的,即作为Tomcat的前端处理器,根据具体情况而定,有些情况下是不需要Apache httpd作为 web 服务器的,如系统展现没有静态页面那就不需要Apache httpd,那时可以直接使用Tomcat作为web 服务器来使用。使用Apache httpd主要是它在处理静态页面方面的能力比Tomcat强多了。
    1、 用户的网页浏览器做完本地 DNS和企业授权的DNS之的请求/响应后,这时候企业授权的DNS(即21cn BOSS DNS)会给用户本地的DNS服务器提供一个NAT请求分配器(即网关)IP。


    2、 NAT分配器,它会根据特定的分配算法,来决定要将连接交给哪一台内部 Apache httpd来处理请求。大多数的NAT请求分配器提供了容错能力:根据侦测各种WEB服务器的失效状况,停止将请求分配给已经宕掉的服务器。并且有些分配器还可以监测到WEB服务器机器的负载情况,并将请求分配给负载最轻的服务器等等。Linux Virtual Server是一个基于Linux操作系统上执行的VS-NAT开源软件套件,而且它有丰富的功能和良好的说明文件。商业硬件解决方案 Foundry Networks的ServerIron是目前业界公认最佳的请求分配器之一。


    3、 Apache httpd + Mod_JK2在这里是作为负载均衡器,那为什么要做集群呢?如果集群系统要具备容错能力,以便在任何单一的硬件或软件组件失效时还能100%可用,那么集群系统必须没有单点故障之忧。所以,不能只架设一台有mod_jk2的Apache httpd,因为如果 httpd或mod_jk2失效了,将不会再有请求被会送交到任何一个Tomcat 实例。这种情况下,Apache httpd就是瓶劲,特别在访问量大的网站。


    4、 Mod_JK2负载均衡与故障复原,决定把Apache httpd当成web服务器,而且使用mod_jk2将请求传送给Tomcat,则可以使用mod_jk2的负载均衡与容错功能。在集群系统中,带有mod_jk2的Apache httpd可以做的事情包括:
    A、 将请求分配至一或多个Tomcat实例上
    你可以在mod_jk2的workers.properties文件中,设定许多Tomcat实例,并赋于每个实例一个lb_factor值,以作为请求分配的加权因子。


    B、 侦测Tomcat实例是否失败
    当Tomcat实例的连接器服务不再响应时,mod_jk2会及时侦测到,并停止将请求送给它。其他的Tomcat实例则会接受失效实例的负载。


    C、 侦测Tomcat实例在失效后的何时恢复
    因连接器服务失效,而停止将请求分配给Tomcat实例之后,mod_jk2会周期性地检查是否已恢复使用性,并自动将其加入现行的Tomcat实例池中。


    5、 Tomcat中的集群原理是通过组播的方式进行节点的查找并使用TCP连接进行会话的复制。这里提示一下就是,对每个请求的处理,Tomcat都会进行会话复制,复制后的会话将会慢慢变得庞大。


    6、 Mod_jk2同时支持会话亲和和会话复制。在tomcat 5中如何实现会话亲和和会话复制?把server.xml中的标签去掉就实现会话亲和,把标签加上就实现会话复制。


    7、 会话亲和:就是表示来自同会话的所有请求都由相同的Tomcat 实例来处理,这种情况下,如果Tomcat实例或所执行的服务器机器失效,也会丧失Servlet的会话数据。即使在集群系统中执行更多的Tomcat实例,也永远不会复制会话数据。这样是提高集群性能的一种方案,但不具备有容错能力了。


    8、 使用会话复制,则当一个Tomcat实例宕掉时,由于至少还有另一个Tomcat实例保有一份会话状态数据,因而数据不会丧失。但性能会有所降低。 

  • 性能测试(并发负载压力)测试分析---转载

    2008-10-11 14:54:36

    分析原则:

     

    • 具体问题具体分析(这是由于不同的应用系统,不同的测试目的,不同的性能关注点)

     

    • 查找瓶颈时按以下顺序,由易到难。

     

              服务器硬件瓶颈

              网络瓶颈(对局域网,可以不考虑)

              服务器操作系统瓶颈(参数配置)

              中间件瓶颈(参数配置,数据库, web 服务器等)

              应用瓶颈( SQL 语句、数据库设计、业务逻辑、算法等)

     

        注:以上过程并不是每个分析中都需要的,要根据测试目的和要求来确定分析的深度。对一些要求低的,我们分析到应用系统在将来大的负载压力(并发用户数、数据量)下,系统的硬件瓶颈在哪儿就够了。

     

    • 分段排除法 很有效

     

    分析的信息来源:

              • 1 根据场景运行过程中的错误提示信息

              • 2 根据测试结果收集到的监控指标数据

     

    一.错误提示分析

     

    分析实例:

    1     • Error: Failed to connect to server “ 10.10.10 .30:8080 ″ : [10060] Connection

    • Error: timed out Error: Server “ 10.10.10 .30 ″ has shut down the connection prematurely

    分析:

    • A 、应用服务死掉。

    (小用户时:程序上的问题。程序上处理数据库的问题)

    • B 、应用服务没有死

    (应用服务参数设置问题)

     

        例:在许多客户端连接 Weblogic 应用服务器被拒绝,而在服务器端没有错误显示,则有可能是 Weblogic 中的 server 元素的 AcceptBacklog 属性值设得过低。如果连接时收到 connection refused 消息,说明应提高该值,每次增加 25 %

     

    • C 、数据库的连接

     

    (1 、在应用服务的性能参数可能太小了 2 、数据库启动的最大连接数(跟硬件的内存有关) )

     

    2 Error: Page download timeout (120 seconds) has expired

     

    分析:可能是以下原因造成

     

              • A 、应用服务参数设置太大导致服务器的瓶颈

              • B 、页面中图片太多

              • C 、在程序处理表的时候检查字段太大多

     

    二.监控指标数据分析

     

    1 .最大并发用户数:

     

    应用系统在当前环境(硬件环境、网络环境、软件环境(参数配置))下能承受的最大并发用户数。

     

              在方案运行中,如果出现了大于 3 个用户的业务操作失败,或出现了服务器 shutdown 的情况,则说明在当前环境下,系统承受不了当前并发用户的负载压力,那么最大并发用户数就是前一个没有出现这种现象的并发用户数。

              如果测得的最大并发用户数到达了性能要求,且各服务器资源情况良好,业务操作响应时间也达到了用户要求,那么 OK 。否则,再根据各服务器的资源情况和业务操作响应时间进一步分析原因所在。

     

    2 .业务操作响应时间:

     

              • 分析方案运行情况应从平均事务响应时间图和事务性能摘要图开始。使用“事务性能摘要”图,可以确定在方案执行期间响应时间过长的事务。

              • 细分事务并分析每个页面组件的性能。查看过长的事务响应时间是由哪些页面组件引起的?问题是否与网络或服务器有关?

              • 如果服务器耗时过长,请使用相应的服务器图确定有问题的服务器度量并查明服务器性能下降的原因。如果网络耗时过长,请使用“网络监视器”图确定导致性能瓶颈的网络问题

     

    3 .服务器资源监控指标:

     

    内存:

     

    1 UNIX 资源监控中指标内存页交换速率( Paging rate ),如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。也可能是内存访问命中率低。

     

    2 Windows 资源监控中,如果 Process\Private Bytes 计数器和 Process\Working Set 计数器的值在长时间内持续升高,同时 Memory\Available bytes 计数器的值持续降低,则很可能存在内存泄漏。

     

    内存资源成为系统性能的瓶颈的征兆 :

     

              很高的换页率 (high pageout rate);

              进程进入不活动状态 ;

              交换区所有磁盘的活动次数可高 ;

              可高的全局系统 CPU 利用率 ; 

              内存不够出错 (out of memory errors)

     

    处理器:

     

    1 UNIX 资源监控( Windows 操作系统同理)中指标 CPU 占用率( CPU utilization ),如果该值持续超过 95% ,表明瓶颈是 CPU 。可以考虑增加一个处理器或换一个更快的处理器。如果服务器专用于 SQL Server, 可接受的最大上限是 80-85% 

     

    合理使用的范围在 60% 至 70% 。

     

    2 Windows 资源监控中,如果 System\Processor Queue Length 大于 2 ,而处理器利用率( Processor Time )一直很低,则存在着处理器阻塞。

     

    CPU 资源成为系统性能的瓶颈的征兆 : 

     

              很慢的响应时间 (slow response time) 

              CPU 空闲时间为零 (zero percent idle CPU) 

              过高的用户占用 CPU 时间 (high percent user CPU) 

              过高的系统占用 CPU 时间 (high percent system CPU) 

              长时间的有很长的运行进程队列 (large run queue size sustained over time)

     

    磁盘 I/O :

     

    1 UNIX 资源监控( Windows 操作系统同理)中指标磁盘交换率( Disk rate ),如果该参数值一直很高,表明 I/O 有问题。可考虑更换更快的硬盘系统。

     

    2 Windows 资源监控中,如果 Disk Time 和 Avg.Disk Queue Length 的值很高,而 Page Reads/sec 页面读取操作速率很低,则可能存在磁盘瓶径。

     

    I/O 资源成为系统性能的瓶颈的征兆 :

     

              过高的磁盘利用率 (high disk utilization) 

              太长的磁盘等待队列 (large disk queue length) 

              等待磁盘 I/O 的时间所占的百分率太高 (large percentage of time waiting for disk I/O) 

              太高的物理 I/O 速率 :large physical I/O rate(not sufficient in itself) 

              过低的缓存命中率 (low buffer cache hit ratio(not sufficient in itself)) 

              太长的运行进程队列,但 CPU 却空闲 (large run queue with idle CPU)

     

    4 .数据库服务器:

     

    SQL Server 数据库:

     

    1 SQLServer 资源监控中指标缓存点击率( Cache Hit Ratio ),该值越高越好。如果持续低于 80% ,应考虑增加内存。

     

    2 如果 Full Scans/sec (全表扫描 / 秒)计数器显示的值比 1 或 2 高,则应分析你的查询以确定是否确实需要全表扫描,以及 SQL 查询是否可以被优化。  

     

    3 Number of Deadlocks/sec( 死锁的数量 / 秒 ) :死锁对应用程序的可伸缩性非常有害,并且会导致恶劣的用户体验。该计数器的值必须为 0 。

     

    4 Lock Requests/sec( 锁请求 / 秒 ) ,通过优化查询来减少读取次数,可以减少该计数器的值。

     

    Oracle 数据库:

     

    1 如果自由内存接近于 0 而且库快存或数据字典快存的命中率小于 0.90 ,那么需要增加 SHARED_POOL_SIZE 的大小。

     

    快存(共享 SQL 区)和数据字典快存的命中率:  

     

    select(sum(pins-reloads))/sum(pins) from v$librarycache; 

     

    select(sum(gets-getmisses))/sum(gets) from v$rowcache; 

     

    自由内存: select * from v$sgastat where name= ’ free memory ’ ; 

     

    2 如果数据的缓存命中率小于 0.90 ,那么需要加大 DB_BLOCK_BUFFERS 参数的值(单位:块)。

     

    缓冲区高速缓存命中率:

     

    select name,value from v$sysstat where name in (’db block gets’,

     

    ‘ consistent gets’,'physical reads’) ;

     

    Hit Ratio = 1-(physical reads / ( db block gets + consistent gets))

     

    3 如果日志缓冲区申请的值较大,则应加大 LOG_BUFFER 参数的值。

     

    日志缓冲区的申请情况 :

     

    select name,value from v$sysstat where name = ‘redo log space requests’ ;

     

    4 如果内存排序命中率小于 0.95 ,则应加大 SORT_AREA_SIZE 以避免磁盘排序 。

     

    内存排序命中率 :

     

    select round((100*b.value)/decode((a.value+b.value), 0, 1, (a.value+b.value)), 2)from v$sysstat a, v$sysstat b where a.name=’sorts (disk)’ and b.name=’sorts (memory)’

     

    注:上述 SQL Server 和 Oracle 数据库分析,只是一些简单、基本的分析,特别是 Oracle 数据库的分析和优化,是一门专门的技术,进一步的分析可查相关资料。
  • 【转载】大型网站的架构设计问题

    2008-10-10 10:40:34

    【转载】大型网站的架构设计问题
    在CSDN上看到一篇文章讨论大型高并发负载网站的系统架构问题,作者提出了几点建议:

    1. HTML静态化,这可以通过CMS自动实现;

    2. 图片服务器分离(类似的,在视频网站中,视频文件也应独立出来);

    3. 数据库集群和库表散列,Oracle、MySQL等DBMS都有完美的支持;

    4. 缓存,比如使用Apache的Squid模块,或者是开发语言的缓存模块,;

    5. 网站镜像;

    6. 负载均衡。

    作者将负载均衡称为“是大型网站解决高负荷访问和大量并发请求采用的终极解决办法”,并提出“一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群”。在实践时可以考虑建立应用服务器集群和Web服务器集群,应用服务器集群可以采用Apache+Tomcat集群和WebLogic集群等,Web服务器集群可以用反向代理,也可以用NAT的方式,或者多域名解析均可。

    从提升网站性能的角度出发,静态资源不应和应用服务器放在一起,数据库服务器也应尽量独立开来。在典型的MVC模式中,由谁来完成数据逻辑处理的,对系统性能有着至关重要的影响。以Java EE为例,在OO的设计思想中,我们强调系统的抽象、重用、可维护性,强调下层的更改不会扩散到上层逻辑,强调系统移植的便捷性,因而往往存在一种过分抽象的问题,比如在Hibernate的基础上再加入一层DAO的设计。另外一方面,却会忽视利用DBMS本身的优秀特性(存储过程、触发器)来完成高效的数据处理。诚然,如果客户要求将数据从Oracle移植到MySQL,那么DBMS特性的东西越少,移植便越容易。但事实上,在实践中,提出类似移植要求的情况非常少见,因此在做架构设计时,不一定为了这种潜在的需求而大幅牺牲系统的性能与稳定性。此外,我不建议采用分布式数据库管理结构,这样带来的开销太大,数据维护也是个头痛的问题,尽可能采用集中式的数据管理。

    在商业系统中,算法逻辑本身并不复杂,在这种情况下,程序设计本身的好坏不会对系统的性能造成致命的影响。重要的影响因素反而变为软件系统架构本身。在传统的CORBA、J2EE、DCOM等对象模型中,我们看到专家们对分布式对象计算的理论偏好,但实践证明,对象的分布带来的恶劣影响远远胜过其积极意义。这也是现在轻量级的开发框架受推崇的一个重要原因。如果能用简单的,就不要用复杂的,例如能够用Python、RoR完成的任务,是否一定要用Java来做?我看未必。对于用户来说,他们关心的不是采用什么先进的技术,而是我们提供的产品能否满足他的需求。而且,Python、RoR这些开发工具已经强大到足以应对大部分网站应用,在各种缓存系统的帮助下,在其他技术的协调配合下,完全能够胜任高负载高并发的网站访问任务。

    在HTML静态化方面,如果是对于更新相对较少的页面,可以这样处理,例如新闻、社区通告、或者类似与淘宝网的产品分类信息。但若数据更新频繁,这样做的意义便不大。

    网站镜像是个传统的技术,更高级的应用来自流媒体领域的CDN(Content Delivery Network),CDN的概念可以由流媒体数据扩展到图片、视频文件等静态资源的传输。不过,在电子商务领域,很少有这样的应用。

  • 成功经验宝典100则(转载)

    2008-10-10 10:19:55


    成功经验宝典100则
    1、王宗立说:每天早上游泳(输入正面潜意识)是他成为亿万富豪的关键。在游泳过程中,输入正面潜意识,使其每天都保持巅峰状态。
    2、最重要的是要养成习惯,立即行动。感动之后是行动。一点总比没有好,晚做总比不做好。
    3、要养成运动的习惯,要养成早起的习惯。运动能激发无限的魅力,会使一个人感觉起来非常自信。所以我要自己保持持续的运动状态。让自己一早起来就很巅峰的状态。很多情况是越文明,生活越糜烂。而你看王永庆,台湾的经营之神,虽然年龄高达86岁,但还是每天5点半起床,跑5000公尺,多年来一直坚持。朝气——POWER.能量就是魅力,气宇非凡。早起,不要为自己找理由,什么我没休息够,我昨天好累啊,等等。
    4、仅仅知道还不够,关键是要不断地训练。训既是教育,练既是练习。
    5、学校不教两件事情,一是不教谈恋爱,怎样找个好老婆怎样嫁个好老公。二是学校不教怎样**,学校给人的教育是追求金钱意味着罪恶,人为财死,鸟为食亡,财富是万恶之源。
    6、成功者与失败者的差别在于时间管理,运用时间的方法。
    7、你可以主宰你自己的命运!!!下定决心争取过自己想要的生活。清楚自己的生活目的。你需要拥有自己的梦想。
    一部电影,《楚门秀》,楚门伯班(金凯瑞饰)老是觉得他一直受到监视。他没想到这竟然是真的。从他呱呱落地开始的三十年来,楚门伯班就是史上播映最久、最受欢迎的记录片肥皂剧的主角,他居住的理想小镇海景镇居然是一个庞大的摄影棚,而他的亲朋好友和他每天碰到的人全都是职业演员。他生命中的一举一动分秒都曝露在隐藏在各处的摄影镜头面前。这就是「楚门的世界」,全球上亿观众都注意着他的一举一动,而他自己却不自知。
    然后经过三十年的浑噩生活后,楚门终于感到他的生活有点不对劲,当他发现他就像是活在玻璃罐里的蝴蝶时,他决定要不计代价地逃离海景镇。但是他必须面对「楚门的世界」的创始人、制作人和导演克里斯托,并且克服他内心最大的恐惧,才能突破藩篱,获得自由他在内心对自己说,NO! I DONT WANT!(不!我不要过这种生活,我不要过这种受别人操纵的生活!)王宗立借这个例子是想说明,一个人的命运是没有人能够操纵的,只要他下定决心,而且用生命去争取,他就可以去争取他想要的东西,过他想要的生活。你也有一合录影带,1天24小时,记录你一生,你的导演是谁呢,你是也在过一种别人操纵的生活呢?你的生活是否是在于达成别人的目的的一种工具而已呢,而不是在过你想要的生活的做对的事情,起而行动,下定决心,用生命去争取!
    你满不满意你自己的剧本,你敢不敢梦想5年后的你?
    亚洲首富孙正义有句名言——最初所拥有的只是梦想和毫无根据的自信而已,但是所有的一切都从这里开始。
    8、销售是世界上最赚钱的工作。
    王宗立,21岁,财富达300亿,选择业务工作。
    这个世界上收入最高的工作就是业务。他说:说服任何人,帮我做任何事。
    销售,什么是销售,就是说明、教育、帮助别人作决定。需要三大能力:开发客户,网罗干部,缔结业务。
    21岁,16个月的时间赚了300万,然后4个月赔光22岁赚了700万,半年赔光,销售房子,帮助别人做决定。人喜欢别人帮他做决定。不管是选衣服,交异性朋友还是选吃什么东西,你都希望别人替你做决定。
    一个女人如果有两个男朋友,她该选择哪一个?如果你是其中之一,你要帮她下决定,你该如何说服她要她选择你?
    二次创业失败,失败了没关系,重要的是学到了东西没有。成功就是交学费,早交晚交而已。越早交就交得越少。
    在人生中必须得有一个自己又爱又敬又怕的人。他的这个又爱又敬又怕的人是他父亲。
    我赔过近千万的钱,最重要的教训——千万别随便转换跑道。我见过太多的转型(转行)失败的人。扩张是另一种形态的转型(转行)。
    9、人要成功需有三本——本人,本钱,本事。本人是指要亲自去了解你所做的业务(产品和服务,甚至具体到每一个细节),本钱就是要有资本,本事是指你要有你的核心专长,核心的竞争力。
    一个人要成功,要有很多的贵人。 8位数字与9位数字相差一万倍。
    亿万富翁靠经营管理,靠大智慧,靠忍。
    老板的大忌:全天下的男人都会犯下的错误是色,英雄难过美人关。很多人有钱到一半,就会享受,开始酒池肉林,百花丛中有花就堪折,这样很快就会财富消散,因为赚钱不是加减法而是乘除法,来得快去得也会更快。所以做领导还要有忧患意识。
    10、人生不在于机会而在于选择。人生的命运就取决于你一刹那所做的决定。
    我做了哪些选择,以致于有我辉煌的成就——23岁月入百万,26岁成为亿万富翁,28岁收购成功杂志,两岸三地不同形态的业务?首先要选个好的工作和职业。
    (1)、宁为牛后,不为鸡首。1993年24岁时,日子非常不错,在忠孝东路有900平米的办公楼,销售房地产,遇到事业瓶颈,因为无法copy销售模式,好象个人打拼一样,没有未来愿景。而会**的人都有一套模式。象麦当劳,只要按照他的这套模式,copy一下,就能赚很多很多的钱,或者有一套模式让下属ALONG依循就可以赚钱了。必须要有一个KNOW HOW历史学家分析说,日本之所以会成功是因为明治维新和大化革新。所以学会**比现在**更重要。
    (2)、底子比面子更重要,收入比头衔更重要,实务经验比虚名更重要,识时务者为俊杰。看得到的结果比幻想的未来更重要。幻想的未来是假的。怎样销售?说服?怎样卖东西?卖咖啡是在卖感觉,卖那种走在咖啡厅外面就问到浓浓的香味,进去之后看到那些摆设和文化气息,卖咖啡是在卖文化。说的是星巴克咖啡厅。
    其次要找个好的伴侣。他说他娶了一个好老婆。你要做应该做的事而不是你喜欢做的事情。我老婆很会欣赏我的优点,很会崇拜我看你的眼神就让你找到自信。 演讲后会很正面的评价我没有人不喜欢赞美,人的肯定来自于很多人的肯定,你想要别人赞美你你也要去赞美别人。我老婆的优点就是会鼓励、赞美、肯定和欣赏我同时她是节省的女人。失败的婚姻会让人处于低潮,所以选老婆要选能助夫荫子的人。不要找一个勉强的老婆(老公),这种婚姻是不会幸福的,他(或者她)绝对会带给你人生的负面的东西。你所爱的人,你要感觉到他(她)也很爱你。她爱你的程度甚于你或至少与你相当。你也许只是so so喜欢她,她却要very much喜欢你,不要找自己一相情愿喜欢的女人,否则你不会高枕无忧。
    再次,关键是要激发潜能,忠于原主。他自己的例子。95年,他的原来的老板,议员落选,新闻传媒的消息,造成很多负面的影响,属下的61家中60家都众叛亲离,只有王宗立他没有,因为他说他实在找不出更好的理由离开,经营状况很不错, 使那个老板很感动,要他立即承诺如果能马上开出12张支票共计 7.2亿的单子,将给非常优厚的利润,……
    这样呢,他说人生就是算和赌,他觉得自己算准了,虽然心理也不是非常有把握,但觉得非常值得赌一把,这样他的财富一下由千万富翁变成亿万富翁。那段时间的压力非常大,但是,要创造压力,享受压力。这样才能成功!
    11、均衡式的发展。训练很贵,不训练更贵。
    12、改变命运很重要的三个关键。其中之一是选择好的老师非常重要。众人生死全看你,力挽狂澜只一人。要想人前显贵,必先人后受罪。霸王别姬,甘之如饴。少年得志大不幸。乐极生悲。5000年来的魔咒。骄傲就会停止学习,要高而不危。每个人都有4张A,只是有些人幸运早翻到而已,而道路很漫长,要时常停下来思考,不要跨太大的步骤,地雷。他作过3个重要的决策。良师有很多包括负面的,要从负面的东西看到学习到,从失败的人的经历里也能学习到很多东西,意见值多少钱?不可限量。衷心的劝告。人不会永远都有好运气。
    齐恒公,管仲,好酒会使寡人亡国吗,好色会使寡人亡国吗,好郊游会使寡人亡国吗,管仲说都不会,只有远贤臣近小人才会使你亡国。
    13、要心怀一颗感恩的心。
    14、怎么系统运用潜意识?马修史维的方法。
    15、欧那西斯的方法。看到任何人,经历任何事,每天晚上用本子记下。以决定下一次怎样花时间在他身上。这个不象学校教的有教无类,不能以貌取人,而真理是say no,懂得拒绝。待人处世一定要因人而异,要学会拒绝否则会浪费时间,要交你应该交的朋友而不是你喜欢交的朋友。
    欧那西斯说,要成功需要盟友,要非常大的成功就需要敌人,战友。康熙敬三碗酒,第三杯是向他的敌人敬的。他说如果没有这些人,就不会成就的大事业。所以说益友可能是竞争对手,要学会向竞争对手学习很多的东西。
    16、功课不重要,一定要灵活。因为交际手腕高的人会更成功。
    17、如何分辨朋友,选择朋友?选择战友,选择敌人?如何选择环境,创造环境?他讲了他的三个女朋友。第一个非常爱玩,第二个非常情绪化,多愁善感,负面的情绪非常多的人。第三个女朋友是说相信他会大富大贵,有非凡前途的人。崇拜,鼓励,相信他的人。我相信我就能看见18、会学习比肯学习愿意学习来得更重要。前车之鉴,后车之履。要试着去教别人你想要学的东西。
    19、每一个决定不是离成功越来越远就是离成功越来越近。思想决定态度,态度决定语言,语言决定行为,行为养成习惯,习惯形成性格,性格决定命运。
    20、苦并不可怕,怕就怕苦得没有代价。
    21、如何做领导统御?科学家是把简单的东西复杂化,企业家是把复杂的东西简单化。管理团队就是连锁人,大量copy,东方不败的葵花宝典,木兰诗背下来,销售房地产的脚本交战手册,实战手册。
    领导统御的秘诀——四句话,开发,复制,管理,交换。
    开发客户,公司来做,教业务员去做。复制:让每一个人都会做。管理:统一的去管理,团队成功。一个企业里有三种人,攻城者,开疆辟域。守城者,守天下。教练者,教育部长,复制的工作。管理就是整合不同类型的人。交换就是资源共享,集体学习,绝不否认每一个个体的价值。
    22、如何选项目?要看适合不适合你。你的核心专长,核心竞争力是什么?
    怎样融资?借钱?银行的钱是借给有钱的人而不是需要钱的人。天上下雨地上滑,自己跌倒自己爬。所以你要塑造自己被利用的价值,你的可被利用的价值是什么?保——呆人。
    23、如何管理好人才?识才,留才,养才,用才。识才——不要找一个完美无缺的人,没有这种人。留才——心静而后定,心定而后安,心安而后求知求财。养才——舍得对你的员工投资,投资!把员工当作你的资产。员工是最宝贵的资产,人是无价之宝。外国企业平均花3-5%去培训他的员工,而中国的企业平均只花 0.03 -0.05%用来培训员工。用才——就是要把人才摆在适当的位置。
    24、不管做什么都要有销售通路。
    25、任何企业都有穷人,成功的企业家不应该停止不前。
    26、行善与行孝——这是人生的两件不能等待的事情。
    27、为什么要成功比怎样成功更重要!!!
    28、世界上没有笨人,笨人都是骂出来的。所以一个赞美鼓励的家庭很重要。
    如何选择环境?一等人创造环境,二等人跟随环境,三等人抱怨环境。要输入正面积极的关于环境的潜意识信息。所有与我有关的一切都必将欣欣向荣,不论白天与夜晚,所有与我有关的一切都必将欣欣向荣。用潜意识营造一个积极的环境,一个特别的know how.
    每一天都有86400秒,如果你把每天的86400秒换算成86400块钱,如果没有用掉的话,会蒸发掉的,你会不会珍惜这些时间?王永庆一分钟赚6万块。年龄不能代表一切。激发潜能既是有效运用时间的最佳方法。安东尼罗宾说你每分每秒都要做最有生产力的事情。
    29、我使用人才的方法是,他有10分才能,不会给他7分的活,而要相反,这样才能激发他的潜能。
    30、一日之计在于昨晚。做最重要的事情。所谓的最重要的事情是指非自己亲自出马不可的事情,要思考3次,不要去做那些仅仅是因为自己喜欢做的事情。每天晚上安排6件重要的事情。缔造高度的压力。辛苦不可怕,关键是辛苦要值得。要创造压力并享受压力。
    31、每周一星。稀有性,不可替代性。
    32、学习催眠最重要的方法是as if(假装)。
    33、一个人与自己人性对抗的力量越强就越能取得成功。晚起床,熬夜,吃宵夜,吸烟等都是坏习惯。一定要养成运动的好习惯。慢跑或游泳都很好。会让你两眼炯炯有神。使你每天都是热情效益有力量的一天。每天起床之后对自己说:生命多美好暗示性的语言:我喜欢健康,我喜欢保持优美的身材,我知道我追求成功……34、当你有足够的理由,你就会作出不可思议的事情。每个人都要自问:我现在为了自己成功的人生,可以作出什么样的决定?
    35、人才最难找!
    36、四到——知道、悟到、做到、得到。
    37、要做那些危险而享受的事情。红色代表赚钱、竞争、占有欲和掌控性。兰色代表人群、party、放松等等。绿色代表证据、数据、精确性。黄色代表使命感、义工、帮助人。
    38、学习——为自己,为身边的人,为千千万万。
    39、你为什么能赚10万美金?原因有三个。第一是你的习惯让你的收入没办法提升。包括决策的习惯、时间管理的习惯等等。第二是你所交的朋友,要交比你强的人。第三提升你核心圈的人的品质如你管理的团队的品质。
    40、知道不够多,复习很重要。学习的秘诀在于所谓的六圈哲学:100%——50%——25%——12%——6%——3%,任何人不能成功是因为没人跟100%的人学习。所以我们要尽量的跟100%的人学习,跟最优秀的学习。接近那个100%的人。
    41、台基集团的企业文化——孝顺,感恩,存钱,竞争。早会,演讲竞赛,每日一星。欧那西斯说一个人要获得巨大的成功必须有敌人,需要竞争才行。
    42、成功的法则是拿来记住的。
    43、教育训练者是使命传播者。
    44、人不可能永远处在颠峰状态,那么怎样克服低潮沮丧和消极的心态呢?当你遇到挑战时,你要想你是在高速飞行,从而才会遇到不可或缺的空气的阻力,从南京到北京,你尽可以走路慢悠悠的走去,那样不会遇到象飞机高速飞行一样遇到的阻力,但是你的速度很慢很慢。恐怕要花半年时间才能到达目的地。
    45、不遭人忌是庸才。
    46、好的环境是鼓风炉。POWER能量。当你走出去,你会遇到挑战,你会遇到拒绝,会有泼冷水的,虽然你开始还象720度的烧得通红的木炭,但一遇到冷水又会逐渐降温。只有你内心的力量使你自己变成一个鼓风炉,你才又会慢慢升温到100度,200度,300度,500度,最后又达到甚至750度的火红的木炭。你应该如何作到这一点呢???你要一遇到这些挑战,一遇到沮丧的时候,你要马上在心中说,I AM& nbspFIRE ,你牺牲了自己,照亮了别人。你想别人赞美,就要赞美别人,你想别人鼓励,就要鼓励别人,你想别人帮助,就帮助别人。
    47、心理学家的实验。一只狗,被穷追,不断的被追,直到倒在地上,嘴冒白沫,然后抽取其血液,有疲劳毒素在里面,用这些毒素注射在一只刚吃饱的活蹦乱跳的狼狗身上,立即要昏昏欲睡,为什么?因为血液总是会疲劳的。人有两个器官是永远不会痛的,一个是头发和指甲另一个是肝脏,如果肝脏会痛这人肯定完了。
    48、惟有坚持百忍,才能无所不能。
    49、天下有两难,登天难求人更难;世间有两苦,黄连苦,贫穷更苦;世上有两险,江湖险人心更险。所以要做最坏的打算。水能载舟亦能覆舟。一切都要能看得开,只有你自己不会背叛你自己,所以要投资你自己。你要爱你自己,要爱跟你有血缘关系的亲人。世上还有两薄:春冰薄,人情更保所以要塑造自己永不被替代的价值,永远被利用的价值。不要怪别人背叛你,你要怪自己没有创造自己被利用的环境。但你真的要坚持百忍才能立于不败之地,才能无所不能……处于低潮时,我会想,如果是王永庆他会怎么做?知其难,忍其苦,测其险,耐其薄,可处世也。
    50、感恩,精进,严谨。
    51、记住别人任何的压力都不会压跨你,只有自己的压力会毁灭你自己。你要自己去调试自己的心灵。方法中,音乐电影的方法对于调试的帮助很大。用音乐治疗自己的痛苦。
    52、人一定要克服自己的沮丧。
    53、没有不景气,只有不争气。巧克力精神——巧妙地克服阻力。
    54、OPT与OPM——运用别人的时间与金钱。
    55、王宗立的座右铭有三条。1、在生命的历程中要告诉自己,软弱的是时候要坚强,恐惧的是时候要勇敢,迷惑的时候要明智,抓不住的时候就要放手,真正的胜利是活在自己的心中。2、冷静地面对一切问题,积极不断地超越自我,惜福永不消极怠惰,活在当下就是最美。3、上帝赐给我镇定和沉着,让我接受不可改变的事情;上帝赐给我勇气和力量,让我改变我有能力改变的事情;上帝赐给我智慧,让我去分辨哪些事情是我有能力改变的,哪些事情是我无法改变的。
    56、为什么要冷静?做业务很辛苦的,要很善于处理危机的。
    57、做业务的三大法宝——走出去,说出来,把钱收回来。
    58、可怜之人必有可恨之处。
    59、什么是大智慧,就是怎样运用心灵的智慧,心灵的力量。哀莫大于心死。大部分人都会很沮丧。
    60、寒冰不能断流水,枯木也能再逢春。
    61、要善于运用心灵的力量。有了它,跌倒了再爬起来,失败了再成功。
    62、罗伯特清崎的投资理财,四象限理论。E,S,B,I.穷爸爸——公家机关,最讲排场,请最多人,花最多的钱,讲气派。富爸爸——企业,私人企业。企业是花最少的钱要创造最大的效益,没有获利的企业是最大的罪恶。因为没有获利的企业会造成很多问题家庭。
    63、并不是读书读得很多就会很有钱。
    64、过安定的生活有两种办法一种是在30岁之前赚了足够的钱,比如说30个亿,然后把这些钱放在银行,投资基金等。第二种是永远不要冒险,安心做一个雇员, 有职业保障但是真的有职业保障吗?没有!!!那些所谓的有职业保障的人只不过是在做钱的黑奴。你是否一辈子在为钱做奴隶。为钱而工作?
    65、你是为生活而工作还是为工作而生活?如果你认为你的工作是享受,那么你就是在为工作而生活,否则的话,你是在为生活而工作。你要为了生活而工作?NO!
    66、你所拥有的就是最好的。只要是你的就是最好的。
    67、S象限里是自由职业者。是做业务,赚奖金收入的人。刚开始时建立通路。
    王想建立的事业。把消费者变成销售者,把销售者变成领导者,管理者。如果不会销售就不会赚钱。
    68、怎样学会销售?走出去,说出来,把钱收回来。
    69、销售的重点是开发客户,缔结业务。这就需要1、专业知识,关于产品和服务的知识。2、要知道顾客购买我的产品的至少5大理由?把这些理由背得很熟很熟。3、要提供证据,提供见证者。4、要知道CLOSE的技巧。敢于帮助别人下决定。
    70、客户说NO是很正常的,业务最大的困难在于胆量,接下来的开场白,产品介绍等等等。万般草木皆兵器,资源,看到人在走路就如同钱在向你招手。
    71、B,利用别人的时间来帮你赚钱。人有四种,消费者——销售者——管理者——领导者。销售者是说明教育帮助顾客下决定的人。领导者是解说者。
    72、怎样说服顾客,当你把产品形容得并使客户相信使得客户认为价值超过价格时,就成交了。价值超过价格就不贵。
    73、要立大志才能做大事。领导者就是说服,说明,教育,帮助别人下决定的人。
    74、 I象限的人,是投资者资本家。利用钱来赚钱的人。投资致富法则,沃伦巴菲特的秘诀——第一个法则,绝对不能赔钱。就是说不能在股票价格低于你当初的买入价时抛出。一定要等最好的时机。逆向思考法则。没有投资智慧,只有理财EQ.那么怎么作到处变不惊?少赔就好。第二条,绝对不要忘记第一个法则。切记切记切记!
    75、世界上最恐怖的力量是复利。世界上没有聪明不聪明之分,只有懂与不懂。
    76、如何增加人生效率?
    77、一定不能满足于现状,要巨观而不是微观。
    78、老板发现员工剽窃了他的智慧,资产等时怎么办?他不要想不开,你也可以挖别的企业的人才。网罗别人的员工,学习别人的智慧。创造你公司的不可被替代性。对于夫妻来说也是如此,要创造你在你老婆(老公)心目中不可被替代性。而不是一双玉臂钱人枕,半点朱唇万人尝。
    79、人生最痛苦的事情莫过于开创和从低潮走向高潮。调整的方法是不要钻牛角尖,而是用另外一个来代替。用催眠录音带,马修史维的方法。
    80、放松,放松,毫不批判的接受成功者的指令。
    81、时间管理,成功者成功的原因之一就是很会管理时间。把事情分为四类,A——很重要又很急的,B——很重要但不很急,如运动,健康检查,看书学习,上课等, C——很急但不重要,因人而异,如女朋友要我下班接她等等。这些也许可以要别人去替你做。D——既不着急也不重要。关键点是如何区分B和C类的事情。急或重要是针对目标和价值观而言的。把第二天自己要做的事情6大项,在每晚做好计划。王宗立做中层管理者一般有以下6大件事情:1、召集员工激励员工。2、邀约一组客户,去拜访说服,如果没有至少要去做问卷调查一组CASE.3、帮助我的干部CLOSE一个客户。4、帮助我的干部救一个客户。救要退货的。5、有些情绪不好的员工要鼓励激发他。6、在公司亲自演示一个产品说明会。培训示范作用。身系公司生死一线之间。
    82、如果一天做6件重要的事,那么一个月就能做180件重要的事情,一年能做2190件事情,你能不成功吗?
    83、养成两个习惯。准备好两个小本子,一个专门用于记那些你当天你遇到的人,和事情。另一个用于记你明天要做的6件事情。
    84、一点总比没有好,晚做总比不做好。要做最重要的事情。
    85、关于时间管理的,是安东尼罗宾的老师亚伯拉罕的课程。人有三种时间:Focus day焦点日,专门用于处理与实现最重要的目标有关的事情。在焦点日不做任何事除了最重要的事情之外。Buffer day:准备日:不怕没有机会,就怕没有准备。准备日是比如说去上课,去培训,去交一些朋友。等等。不是去缔结业务去收钱,但是去做之前的准备工作。Free& nbspday:自由日,休息,与家人在一起。奖励,平衡等。
    86、人有四种,人物,人才,人手,人渣。
    87、全天下最长的距离是别人的钱包到你的钱包的距离。
    88、马修史维:只要是正面的,有力量的对你有帮助的,那么DO IT NOW!
    89、行善行孝感恩这三件事情都不能等,不然就没有机会了。
    90、当别人泼你冷水时,轻视你,嘲笑你,侮辱你,打击你,为难你时,你不但不要骂他,责怪他,相反你要感谢他,因为他不仅在你沮丧时,在你的油箱里加满了油,让你一路勇往直前冲到底。
    91、凡事没有任何意义,除非你赋予它定义。
    92、人人都不是在推销产品,而是在推销自己。
    93、投资大脑,回报率最高。
    94、完美主义会杀人。不要等准备好了再说,差不多就要去做。完美主义会打断习惯。凡事最怕开头,有了开头就会继续,有继续就会养成习惯,习惯就会成自然,自然就是美。
    95、相信就会看见。一般人是看见了才相信。所以信念很重要。
    96、人无法成功的原因只有两个:懒惰和惧怕。人有三大最怕:火,高处往下跳,在公众面前演讲。
    97、不要自己挣不到钱,就希望别人也破产。要创造好的环境,要做正面的暗示:无论白天与夜晚,所有与我有关的一切都必将欣欣向荣。
    98、一等人创造环境,二等人跟随环境,三等人抱怨环境。
    99、如果你有足够的理由,当你遇到令你兴奋得发抖的机会,你体内的火山就会自动爆发,你心灵的巨人就会被唤醒。
    100、凡事皆正面,能量永不减。

  • 软件测试面试问答大全(2)

    2008-10-09 15:26:31

    11. 您在从事性能测试工作时, 是否使用过一些测试工具?如果有,请试述该工具的工作原理,并以一个具体的工作中的例子描述该工具是如何在实际工作中应用的。

       目前市场上的性能测试的工具种类很多,可以简单的划分为以下几种:负载压力测试工具、资源监控工具、故障定位工具以及调优工具。

    主流负载性能测试工具

    负载性能测试工具的原理通常是通过录制、回放脚本、模拟多用户同时访问被测试系统,制造负载,产生并记录各种性能指标,生成分析结果,从而完成性能测试的任务。

            主流的负载性能测试工具有:

            QA LoadCompuware公司的QALoad是客户/服务器系统、企业资源配置(ERP)和电子商务应用的自动化负载测试工具。QALoadQACenter性能版的一部分,它通过可重复的、真实的测试能够彻底地 度量应用的可扩展性和性能。QACenter汇集完整的跨企业的自动测试产品,专为提高软件质量而设计。QACenter可以在整个开发生命周期、跨越多 种平台、自动执行测试任务。

            SilkPerformer:一种在工业领域最高级的企业级负载测试工具。它可以模仿成千上万的用户在多协议和 多计算的环境下工作。不管企业电子商务应用的规模大小及其复杂性,通过SilkPerformer,均可以在部署前预测它的性能。可视的用户化界面、实时 的性能监控和强大的管理报告可以帮助我们迅速的解决问题,例如加快产品投入市场的时间,通过最小的测试周期保证系统的可靠性,优化性能和确保应用的可扩充 性。

            LoadRunner:一种较高规模适应性的,自动负载测试工具,它能预测系统行为,优化性能。LoadRunner强调的是整个企业的系统,它通过模拟 实际用户的操作行为和实行实时性能监测,来帮助您更快的确认和查找问题。此外,LoadRunner 能支持最宽范的协议和技术,为您的特殊环境,量身定做地提供解决方案。

            WebRunner:是RadView公司推出的一个性能测试和分析工具,它让web应用程序开发者自动执行压力测试;webload通过模拟真实用户的 操作,生成压力负载来测试web的性能,用户创建的是基于javascrīpt的测试脚本,称为议程agenda,用它来模拟客户的行为,通过执行该脚本 来衡量web应用程序在真实环境下的性能。

    免费测试工具:

            OpenSTA:开源项目,功能强大,自定义功能设置完备,但设置通过scrīpt来完成。必须学习scrīpt编写

            WASWeb Application Stress Tool):微软的工具,输出结果是纯文本的。

    主流商用负载性能工具的比较图如下:

    属性

    LoadRunner

    QALoad

    WebLoad

    出品公司

    HP(Mercury)

    Compuware

    Radview

    价格

    昂贵

    较贵

    一般

    安装配置的复杂性

    简单

    简单

    一般

    操作性

    较复杂

    简单

    简单

    支持测试对象

    各种中间件/数据库/应用服务器的性能监控/企业架构(j2ee和.net)的测试

    客户/服务器系统、企业资源配置(ERP)和电子商务应用

    Web Application

    支持平台

    windows,unixlinux

    HP-UX, IBM AIX,Sun Solaris, Linux, NT/2k

    Unix Windows

    支持数据库

    DB2,SQLserver,
    Orcale,Sybase

    ADO, DB2,Oracle,Sybase,
    SQLserver,Odbc

    ADO,DB2,Oracle,Sybase,
    SQLserver,Odbc

    支持协议 

    web,http(s),soap,streaming,
    wap,winsock,xml

    http,ssl,soap,xml,
    streaming,media

    xml,java,ejb,
    activex,wap,http,snmp,
    real/m$streaming

    脚本语言

    类似C++

    C/C++和VC++

    Javascrīpt

    自动数据生成

    Y

    Y

    Y

    脚本调试

    Y

    Y

    Y

    报表定制功能

    Y

    Y

    Y

    功能点

    创建虚拟用户,创建真实的负载,定位性能问题,分析结果以精确定位问题所在,重复测试保证系统发布的高性能等

    预测系统性能、通过重复测试寻找瓶颈问题、从控制中心管理全局负载测试、快速创建仿真的测试、验证应用的可扩展性。

    强大的专业网站性能测试,虚拟多用户

    虚拟用户上限数量

    成千上万

    成百上千

    理论上无限,不过受机器的限制,同时运行太多影响结果的准确性

    公司网址

    Http://www.merc-int.com

    http://www.compuware-china.com

    http://www

     

     

    12. 您认为性能测试工作的目的是什么?做好性能测试工作的关键是什么?

    目的:是验证软件系统是否能够达到用户提出的性能指标,同时发现软件系统中存在的性能瓶颈,优化软件,最后起到优化系统的目的。

    包括以下几个方面

    1.评估系统的能力,测试中得到的负荷和响应时间数据可以被用于验证所计划的模型的能力,并帮助作出决策。

    2.识别体系中的弱点:受控的负荷可以被增加到一个极端的水平,并突破它,从而修复体系的瓶颈或薄弱的地方。

    3.系统调优:重复运行测试,验证调整系统的活动得到了预期的结果,从而改进性能。

    检测软件中的问题:长时间的测试执行可导致程序发生由于内存泄露引起的失败,揭示程序中的隐含的问题或冲突。

    4.验证稳定性(resilience)可靠性(reliability):在一个生产负荷下执行测试一定的时间是评估系统稳定性和可靠性是否满足要求的唯一方法。

    性能测试类型包括负载测试,强度测试,容量测试

    负载测试:负载测试是一种性能测试指数据在超负荷环境中运行,程序是否能够承担。

    强度测试 强度测试是一种性能测试,他在系统资源特别低的情况下软件系统运行情况。

    容量测试:确定系统可处理同时在线的最大用户数 

    观察指标:

    性能测试主要是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。

     

    13. 在您以往的工作中,一条软件缺陷(或者叫Bug)记录都包含了哪些内容?如何提交高质量的软件缺陷(Bug)记录?

    当在测试过程中出现了测试人员无法解释的事件时,将给出一个问题报告。问题报告中记录该事件的详细情况和以下条目。

    问题标识、作者、发布/构建版本号、打开日期、关闭日期、问题作用域、缺陷或补充、

    测试环境、缺陷类型、缺陷发现人、缺陷如何发现、缺陷指派给的人、优先级、重要性、状态。

    其他用来对测试过程和结果进行交流的测试报告包括测试用例日志、测试日志总结报告、系统总结报告等。测试用例日志记录了将要执行的某个测试类型的测试用例。同时也记录了测试的结果,为测试日志总结报告提供了详细的依据,并为重构测试提供了可能(如果需要的话)。

    测试日志总结报告记录了测试人员日志中的测试用例,这些尚未完成或者已经完成的测试用例用于状态报告和度量标准收集。

    应该为每个主要的测试事件准备一个系统总结报告。有时系统总结报告也会概述所有的测试。下面列出了通常包含的主要部分:通用信息(描述测试目标、测试环境、参考信息),测试结果和发现(描述每个测试),软件功能和发现,以及分析和测试总结。

     

     

    14. 您以往所从事的软件测试工作中,是否使用了一些工具来进行软件缺陷(Bug)的管理?如果有,请结合该工具描述软件缺陷(Bug)跟踪管理的流程。

    缺陷能够引起软件运行时产生的一种不希望或不可接受的外部行为结果,软件测试过程简单说就是围绕缺陷进行的,对缺陷的跟踪管理一般而言需要达到以下的目标:

          a,确保每个被发现的缺陷都能够被解决;
          b,
    这里解决的意思不一定是被修正,也可能是其他处理方式(例如,在下一个版本中修正或是不修正),总之,对每个被发现的BUG的处理方式必须能够在开发组织中达到一致;
          c,
    收集缺陷数据并根据缺陷趋势曲线识别测试过程的阶段;决定测试过程是否结束有很多种方式,通过缺陷趋势曲线来确定测试过程是否结束是常用并且较为有效的一种方式;
          d,
    收集缺陷数据并在其上进行数据分析,作为组织的过程财富。

          上述的第一条是最受到重视的一点,在谈到缺陷跟踪管理时,一般人都会马上想到这一条,然而对第二和第三条目标却很容易忽视。其实,在一个运行良好的组织中,缺陷数据的收集和分析是很重要的,从缺陷数据中可以得到很多与软件质量相关的数据。

    Bug管理的一般流程:

      测试人员提交新的Bug入库,错误状态为New

      高级测试人员验证错误,如果确认是错误,分配给相应的开发人员,设置状态为Open。如果不是错误,则拒绝,设置为Declined状态。

        开发人员查询状态为OpenBug,如果不是错误,则置状态为Declined;如果是Bug则修复并置状态为Fixed。不能解决的Bug,要留下文字说明及保持BugOpen状态。

        对于不能解决和延期解决的Bug,不能由开发人员自己决定,一般要通过某种会议(评审会)通过才能认可。

        测试人员查询状态为FixedBug,然后验证Bug是否已解决,如解决置Bug的状态为

    Closed,如没有解决置状态为Reopen

     

    15. 您认为在测试人员同开发人员的沟通过程中, 如何提高沟通的效率和改善沟通的效果?维持测试人员同开发团队中其他成员良好的人际关系的关键是什么?

     

    16. 在您以往的测试工作中, 最让您感到不满意或者不堪回首的事情是什么?您是如何来对待这些事情的?

     

    17. 在即将完成这次笔试前, 您是否愿意谈一些自己在以往的学习和工作中获得的工作经验和心得体会?(可以包括软件测试、过程改进、软件开发或者与此无关的其他方面)

     

    18.你对测试最大的兴趣在哪里?为什么?

      最大的兴趣就是测试有难度,有挑战性!做测试越久越能感觉到做好测试有多难。曾经在无忧测试网上看到一篇文章,是关于如何做好一名测试工程师。一共罗列了1112点,有部分是和人的性格有关,有部分需要后天的努力。但除了性格有关的12点我没有把握,其他点我都很有信心做好它。

      刚开始进入测试行业时,对测试的认识是从无忧测试网上了解到的一些资料,当时是冲着做测试需要很多技能才能做的好,虽然入门容易,但做好很难,比开发更难,虽然当时我很想做开发(学校专业课我基本上不缺席,因为我喜欢我的专业),但看到测试比开发更难更有挑战性,想做好测试的意志就更坚定了。

      不到一年半的测试工作中,当时的感动和热情没有减退一点(即使环境问题以及自身经验,技术的不足,做测试的你一定也能理解)。

      我觉得做测试整个过程中有2点让我觉得很有难度(对我来说,有难度的东西我就非常感兴趣),第一是测试用例的设计,因为测试的精华就在测试用例的设计上了,要在版本出来之前,把用例写好,用什么测试方法写?(也就是测试计划或测试策略),如果你刚测试一个新任务时,你得花一定的时间去消化业务需求和技术基础,业务需求很好理解(多和产品经理和开发人员沟通就能达到目的),而技术基础可就没那么简单了,这需要你自觉的学习能力,比如说网站吧,最基本的技术知识你要知道网站内部是怎么运作的的,后台是怎么响应用户请求的?测试环境如何搭建?这些都需要最早的学好。至少在开始测试之前能做好基本的准备,可能会遇到什么难题?需求细节是不是没有确定好?这些问题都能在设计用例的时候发现。

      第二是发现BUG的时候了,这应该是测试人员最基本的任务了,一般按测试用例开始测试就能发现大部分的bug,还有一部分bug需要测试的过程中更了解所测版本的情况获得更多信息,补充测试用例,测试出bug。还有如何发现bug?这就需要在测试用例有效的情况下,通过细心和耐心去发现 bug了,每个用例都有可能发现bug,每个地方都有可能出错,所以测试过程中思维要清晰(测试过程数据流及结果都得看仔细了,bug都在里面发现的)。如何描述bug也很有讲究,bug在什么情况下会产生,如果条件变化一点点,就不会有这个bug,以哪些最少的操作步骤就能重现这个bug,这个bug产生的规律是什么?如果你够厉害的话,可以帮开发人员初步定位问题。

     

    19. 你的测试职业发展是什么?

      测试经验越多,测试能力越高。所以我的职业发展是需要时间累积的,一步步向着高级测试工程师奔去。而且我也有初步的职业规划,前3年累积测试经验,按如何做好测试工程师的1112点要求自己,不断的更新自己改正自己,做好测试任务。

     

    20. 你自认为测试的优势在哪里?

      优势在于我对测试坚定不移的信心和热情,虽然经验还不够,但测试需要的基本技能我有信心在工作中得以发挥。

  • 软件测试面试问答大全(1)

    2008-10-09 15:25:22

    01. 为什么要在一个团队中开展软件测试工作?

      因为没有经过测试的软件很难在发布之前知道该软件的质量,就好比ISO质量认证一样,测试同样也需要质量的保证,这个时候就需要在团队中开展软件测试的工作。在测试的过程发现软件中存在的问题,及时让开发人员得知并修改问题,在即将发布时,从测试报告中得出软件的质量情况。

     

    02. 您在以往的测试工作中都曾经具体从事过哪些工作?其中最擅长哪部分工作?

      我曾经做过web测试,后台测试,客户端软件,其中包括功能测试,性能测试,用户体验测试。最擅长的是功能测试

     

    03. 您所熟悉的软件测试类型都有哪些?请试着分别比较这些不同的测试类型的区别与联系(如功能测试、性能测试……)

      测试类型有:功能测试,性能测试,界面测试。

      功能测试在测试工作中占的比例最大,功能测试也叫黑盒测试。是把测试对象看作一个黑盒子。利用黑盒测试法进行动态测试时,需要测试软件产品的功能,不需测试软件产品的内部结构和处理过程。采用黑盒技术设计测试用例的方法有:等价类划分、边界值分析、错误推测、因果图和综合策略。

      性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。

      界面测试,界面是软件与用户交互的最直接的层,界面的好坏决定用户对软件的第一印象。而且设计良好的界面能够引导用户自己完成相应的操作,起到向导的作用。同时界面如同人的面孔,具有吸引用户的直接优势。设计合理的界面能给用户带来轻松愉悦的感受和成功的感觉,相反由于界面设计的失败,让用户有挫败感,再实用强大的功能都可能在用户的畏惧与放弃中付诸东流。

      区别在于,功能测试关注产品的所有功能上,要考虑到每个细节功能,每个可能存在的功能问题。性能测试主要关注于产品整体的多用户并发下的稳定性和健壮性。界面测试更关注于用户体验上,用户使用该产品的时候是否易用,是否易懂,是否规范(快捷键之类的),是否美观(能否吸引用户的注意力),是否安全(尽量在前台避免用户无意输入无效的数据,当然考虑到体验性,不能太粗鲁的弹出警告)?做某个性能测试的时候,首先它可能是个功能点,首先要保证它的功能是没问题的,然后再考虑该功能点的性能测试

     

    04.您认为做好测试用例设计工作的关键是什么?

    白盒测试用例设计的关键是以较少的用例覆盖尽可能多的内部程序逻辑结果

    黑盒法用例设计的关键同样也是以较少的用例覆盖模块输出和输入接口。不可能做到完全测试,以最少的用例在合理的时间内发现最多的问题

     

    05. 请试着比较一下黑盒测试、白盒测试、单元测试、集成测试、系统测试、验收测试的区别与联系。

     

      黑盒测试:已知产品的功能设计规格,可以进行测试证明每个实现了的功能是否符合要求。

      白盒测试:已知产品的内部工作过程,可以通过测试证明每种内部操作是否符合设计规格要求,所有内部成分是否以经过检查。

     

      软件的黑盒测试意味着测试要在软件的接口处进行。这种方法是把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。因此黑盒测试又叫功能测试或数据驱动测试。黑盒测试主要是为了发现以下几类错误:

      1、是否有不正确或遗漏的功能?

      2、在接口上,输入是否能正确的接受?能否输出正确的结果?

      3、是否有数据结构错误或外部信息(例如数据文件)访问错误?

      4、性能上是否能够满足要求?

      5、是否有初始化或终止性错误?

     

      软件的白盒测试是对软件的过程性细节做细致的检查。这种方法是把测试对象看做一个打开的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序状态,确定实际状态是否与预期的状态一致。因此白盒测试又称为结构测试或逻辑驱动测试。白盒测试主要是想对程序模块进行如下检查:

      1、对程序模块的所有独立的执行路径至少测试一遍。

      2、对所有的逻辑判定,取“真”与取“假”的两种情况都能至少测一遍。

      3、在循环的边界和运行的界限内执行循环体。

      4、测试内部数据结构的有效性,等等。

     

      单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。单元测试是由程序员自己来完成,最终受益的也是程序员自己。可以这么说,程序员有责任编写功能代码,同时也就有责任为自己的代码编写单元测试。执行单元测试,就是为了证明这段代码的行为和我们期望的一致。

      集成测试(也叫组装测试,联合测试)是单元测试的逻辑扩展。它的最简单的形式是:两个已经测试过的单元组合成一个组件,并且测试它们之间的接口。从这一层意义上讲,组件是指多个单元的集成聚合。在现实方案中,许多单元组合成组件,而这些组件又聚合成程序的更大部分。方法是测试片段的组合,并最终扩展进程,将您的模块与其他组的模块一起测试。最后,将构成进程的所有模块一起测试。

      系统测试是将经过测试的子系统装配成一个完整系统来测试。它是检验系统是否确实能提供系统方案说明书中指定功能的有效方法。(常见的联调测试)系统测试的目的是对最终软件系统进行全面的测试,确保最终软件系统满足产品需求并且遵循系统设计。

      验收测试是部署软件之前的最后一个测试操作。验收测试的目的是确保软件准备就绪,并且可以让最终用户将其用于执行软件的既定功能和任务。验收测试是向未来的用户表明系统能够像预定要求那样工作。经集成测试后,已经按照设计把所有的模块组装成一个完整的软件系统,接口错误也已经基本排除了,接着就应该进一步验证软件的有效性,这就是验收测试的任务,即软件的功能和性能如同用户所合理期待的那样。

     

    06. 测试计划工作的目的是什么?测试计划工作的内容都包括什么?其中哪些是最重要的?

      软件测试计划是指导测试过程的纲领性文件,包含了产品概述、测试策略、测试方法、测试区域、测试配置、测试周期、测试资源、测试交流、风险分析等内容。借助软件测试计划,参与测试的项目成员,尤其是测试管理人员,可以明确测试任务和测试方法,保持测试实施过程的顺畅沟通,跟踪和控制测试进度,应对测试过程中的各种变更。

    测试计划和测试详细规格、测试用例之间是战略和战术的关系,测试计划主要从宏观上规划测试活动的范围、方法和资源配置,而测试详细规格、测试用例是完成测试任务的具体战术。所以其中最重要的是测试测试策略和测试方法(最好是能先评审)

     

    07. 您认为做好测试计划工作的关键是什么?

      1. 明确测试的目标,增强测试计划的实用性

      编写软件测试计划得重要目的就是使测试过程能够发现更多的软件缺陷,因此软件测试计划的价值取决于它对帮助管理测试项目,并且找出软件潜在的缺陷。因此,软件测试计划中的测试范围必须高度覆盖功能需求,测试方法必须切实可行,测试工具并且具有较高的实用性,便于使用,生成的测试结果直观、准确

      2.坚持“5W”规则,明确内容与过程

      “5W”规则指的是“What(做什么)”、“Why(为什么做)”、“When(何时做)”、“Where(在哪里)”、“How(如何做)”。利用“5W”规则创建软件测试计划,可以帮助测试团队理解测试的目的(Why),明确测试的范围和内容(What),确定测试的开始和结束日期(When),指出测试的方法和工具(How),给出测试文档和软件的存放位置(Where)。

      3.采用评审和更新机制,保证测试计划满足实际需求

    测试计划写作完成后,如果没有经过评审,直接发送给测试团队,测试计划内容的可能不准确或遗漏测试内容,或者软件需求变更引起测试范围的增减,而测试计划的内容没有及时更新,误导测试执行人员。

      4. 分别创建测试计划与测试详细规格、测试用例

      应把详细的测试技术指标包含到独立创建的测试详细规格文档,把用于指导测试小组执行测试过程的测试用例放到独立创建的测试用例文档或测试用例管理数据库中。测试计划和测试详细规格、测试用例之间是战略和战术的关系,测试计划主要从宏观上规划测试活动的范围、方法和资源配置,而测试详细规格、测试用例是完成测试任务的具体战术。

     

    08. 您所熟悉的测试用例设计方法都有哪些?请分别以具体的例子来说明这些方法在测试用例设计工作中的应用。

      1.等价类划分

      划分等价类: 等价类是指某个输入域的子集合.在该子集合中,各个输入数据对于揭露程序中的错误都是等效的.并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试.因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件,就可以用少量代表性的测试数据.取得较好的测试结果.等价类划分可有两种不同的情况:有效等价类和无效等价类.

      2.边界值分析法

      边界值分析方法是对等价类划分方法的补充。测试工作经验告诉我,大量的错误是发生在输入或输出范围的边界上,而不是发生在输入输出范围的内部.因此针对各种边界情况设计测试用例,可以查出更多的错误.

      使用边界值分析方法设计测试用例,首先应确定边界情况.通常输入和输出等价类的边界,就是应着重测试的边界情况.应当选取正好等于,刚刚大于或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值作为测试数据.

    3.错误推测法

      基于经验和直觉推测程序中所有可能存在的各种错误, 从而有针对性的设计测试用例的方法.

      错误推测方法的基本思想: 列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试用例. 例如, 在单元测试时曾列出的许多在模块中常见的错误. 以前产品测试中曾经发现的错误等, 这些就是经验的总结. 还有, 输入数据和输出数据为0的情况. 输入表格为空格或输入表格只有一行. 这些都是容易发生错误的情况. 可选择这些情况下的例子作为测试用例.

    4.因果图方法

      前面介绍的等价类划分方法和边界值分析方法,都是着重考虑输入条件,但未考虑输入条件之间的联系, 相互组合等. 考虑输入条件之间的相互组合,可能会产生一些新的情况. 但要检查输入条件的组合不是一件容易的事情, 即使把所有输入条件划分成等价类,他们之间的组合情况也相当多. 因此必须考虑采用一种适合于描述对于多种条件的组合,相应产生多个动作的形式来考虑设计测试用例. 这就需要利用因果图(逻辑模型). 因果图方法最终生成的就是判定表. 它适合于检查程序输入条件的各种组合情况.

     

    09. 请以您以往的实际工作为例详细的描述一次测试用例设计的完整的过程。

      就说最近的这次网站功能的测试吧

      首先:得到相关文档(需求文档和设计文档),理解需求和设计设计思想后,想好测试策略(测试计划简单点就OK了),考虑到测试环境,测试用例,测试时间等问题。

      第二步:设计测试用例,测试策略是:把网站部分的功能点测试完,然后在进行系统测试(另外个模块呢有另一个测试人员负责,可以进行联调测试),网站模块的测试基本是功能测试和界面测试(用户并发的可能性很小,所以不考虑):这次的网站的输入数据呢是使用数据库中的某张表记录,如果表中某一数据记录中新加进来的(还没有被处理的,有个标志位),网站启动后会立刻去刷那张表,得到多条数据,然后在进行处理。处理过程中,会经历3个步骤,网站才算完成了它的任务。有3个步骤呢,就可以分别对  这3个步骤进行测试用例的设计,尽量覆盖到各种输入情况(包括数据库中的数据,用户的输入等),得出了差不多50个用例。界面测试,也就是用户看的到的地方,包括发送的邮件和用户填写资料的页面展示。

      第三步:搭建测试环境(为什么这个时候考虑测试环境呢?因为我对网站环境已经很熟了,只有有机器能空于下来做该功能测试就可以做了),因为网站本身的环境搭建和其他的系统有点不同,它需要的测试环境比较麻烦,需要web服务器(Apache,tomcat),不过这次需求呢,网站部分只用到了tomcat,所以只要有tomcat即可

      第四步:执行测试

     

    10. 您以往是否曾经从事过性能测试工作?如果有,请尽可能的详细描述您以往的性能测试工作的完整过程。

      是的,曾经做过网站方面的性能测试,虽然做的时间并不久(2个月吧),当时呢,是有位网站性能测试经验非常丰富的前辈带着我一起做。

    性能测试类型包括负载测试,强度测试,容量测试等

      负载测试:负载测试是一种性能测试指数据在超负荷环境中运行,程序是否能够承担。

      强度测试: 强度测试是一种性能测试,他在系统资源特别低的情况下软件系统运行情况

      容量测试:确定系统可处理同时在线的最大用户数 

      在网站流量逐渐加大的情况下,开始考虑做性能测试了,首先要写好性能测试计划,根据运营数据得出流量最大的页面(如果是第一次的话,一般是首页,下载页,个人帐户页流量最大,而且以某种百分比),

     

      Web服务器指标指标:

      * Avg Rps: 平均每秒钟响应次数=总请求时间 / 秒数;

      * Successful Rounds:成功的请求;

      * Failed Rounds :失败的请求;

      * Successful Hits :成功的点击次数;

      * Failed Hits :失败的点击次数;

      * Hits Per Second :每秒点击次数;

      * Successful Hits Per Second :每秒成功的点击次数;

      * Failed Hits Per Second :每秒失败的点击次数;

      * Attempted Connections :尝试链接数;

    现在准备面试软件测试的工作,既然下定决心,就从现在起将收集到的软件测试面试的所有问答陆续发到博客上,供大家参考指正,一起努力,一起进步!~

  • 性能测试指标及其注意地方(转载)

    2008-10-09 15:19:55


    性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。
    一、概述

          性能测试在软件的质量保证中起着重要的作用,它包括的测试内容丰富多样。中国软件评测中心将性能测试概括为三个方面:应用在客户端性能的测试、应用在网络上性能的测试和应用在服务器端性能的测试。通常情况下,三方面有效、合理的结合,可以达到对系统性能全面的分析和瓶颈的预测。

        ·应用在客户端性能的测试

      应用在客户端性能测试的目的是考察客户端应用的性能,测试的入口是客户端。它主要包括并发性能测试、疲劳强度测试、大数据量测试和速度测试等,其中并发性能测试是重点。

          并发性能测试是重点

      并发性能测试的过程是一个负载测试和压力测试的过程,即逐渐增加负载,直到系统的瓶颈或者不能接收的性能点,通过综合分析交易执行指标和资源监控指标来确定系统并发性能的过程。负载测试(Load Testing)是确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统组成部分的相应输出项,例如通过量、响应时间、CPU负载、内存使用等来决定系统的性能。负载测试是一个分析软件应用程序和支撑架构、模拟真实环境的使用,从而来确定能够接收的性能过程。压力测试(Stress Testing)是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。

      并发性能测试的目的主要体现在三个方面:以真实的业务为依据,选择有代表性的、关键的业务操作设计测试案例,以评价系统的当前性能;当扩展应用程序的功能或者新的应用程序将要被部署时,负载测试会帮助确定系统是否还能够处理期望的用户负载,以预测系统的未来性能;通过模拟成百上千个用户,重复执行和运行测试,可以确认性能瓶颈并优化和调整应用,目的在于寻找到瓶颈问题。

      当一家企业自己组织力量或委托软件公司代为开发一套应用系统的时候,尤其是以后在生产环境中实际使用起来,用户往往会产生疑问,这套系统能不能承受大量的并发用户同时访问? 这类问题最常见于采用联机事务处理(OLTP)方式数据库应用、Web浏览和视频点播等系统。这种问题的解决要借助于科学的软件测试手段和先进的测试工具。

          举例说明:电信计费软件

      众所周知,每月20日左右是市话交费的高峰期,全市几千个收费网点同时启动。收费过程一般分为两步,首先要根据用户提出的电话号码来查询出其当月产生费用,然后收取现金并将此用户修改为已交费状态。一个用户看起来简单的两个步骤,但当成百上千的终端,同时执行这样的操作时,情况就大不一样了,如此众多的交易同时发生,对应用程序本身、操作系统、中心数据库服务器、中间件服务器、网络设备的承受力都是一个严峻的考验。决策者不可能在发生问题后才考虑系统的承受力, 预见软件的并发承受力, 这是在软件测试阶段就应该解决的问题。

      目前,大多数公司企业需要支持成百上千名用户,各类应用环境以及由不同供应商提供的元件组装起来的复杂产品,难以预知的用户负载和愈来愈复杂的应用程序,使公司担忧会发生投放性能差、用户遭受反应慢、系统失灵等问题。其结果就是导致公司收益的损失。

      如何模拟实际情况呢? 找若干台电脑和同样数目的操作人员在同一时刻进行操作,然后拿秒表记录下反应时间?这样的手工作坊式的测试方法不切实际,且无法捕捉程序内部变化情况,这样就需要压力测试工具的辅助。

      测试的基本策略是自动负载测试,通过在一台或几台PC机上模拟成百或上千的虚拟用户同时执行业务的情景,对应用程序进行测试,同时记录下每一事务处理的时间、中间件服务器峰值数据、数据库状态等。通过可重复的、真实的测试能够彻底地度量应用的可扩展性和性能,确定问题所在以及优化系统性能。预先知道了系统的承受力,就为最终用户规划整个运行环境的配置提供了有力的依据。

          并发性能测试前的准备工作

      测试环境:配置测试环境是测试实施的一个重要阶段,测试环境的适合与否会严重影响测试结果的真实性和正确性。测试环境包括硬件环境和软件环境,硬件环境指测试必需的服务器、客户端、网络连接设备以及打印机/扫描仪等辅助硬件设备所构成的环境;软件环境指被测软件运行时的操作系统、数据库及其他应用软件构成的环境。

      一个充分准备好的测试环境有三个优点:一个稳定、可重复的测试环境,能够保证测试结果的正确;保证达到测试执行的技术需求;保证得到正确的、可重复的以及易理解的测试结果。

      测试工具:并发性能测试是在客户端执行的黑盒测试,一般不采用手工方式,而是利用工具采用自动化方式进行。目前,成熟的并发性能测试工具有很多,选择的依据主要是测试需求和性能价格比。著名的并发性能测试工具有QALoad、LoadRunner、Benchmark Factory和Webstress等。这些测试工具都是自动化负载测试工具,通过可重复的、真实的测试,能够彻底地度量应用的可扩展性和性能,可以在整个开发生命周期、跨越多种平台、自动执行测试任务,可以模拟成百上千的用户并发执行关键业务而完成对应用程序的测试。

      测试数据:在初始的测试环境中需要输入一些适当的测试数据,目的是识别数据状态并且验证用于测试的测试案例,在正式的测试开始以前对测试案例进行调试,将正式测试开始时的错误降到最低。在测试进行到关键过程环节时,非常有必要进行数据状态的备份。制造初始数据意味着将合适的数据存储下来,需要的时候恢复它,初始数据提供了一个基线用来评估测试执行的结果。

      在测试正式执行时,还需要准备业务测试数据,比如测试并发查询业务,那么要求对应的数据库和表中有相当的数据量以及数据的种类应能覆盖全部业务。

      模拟真实环境测试,有些软件,特别是面向大众的商品化软件,在测试时常常需要考察在真实环境中的表现。如测试杀毒软件的扫描速度时,硬盘上布置的不同类型文件的比例要尽量接近真实环境,这样测试出来的数据才有实际意义。

          并发性能测试的种类与指标

      并发性能测试的种类取决于并发性能测试工具监控的对象,以QALoad自动化负载测试工具为例。软件针对各种测试目标提供了DB2、DCOM、ODBC、ORACLE、NETLoad、Corba、QARun、SAP、SQLServer、Sybase、Telnet、TUXEDO、UNIFACE、WinSock、WWW、Java scrīpt等不同的监控对象,支持Windows和UNIX测试环境。

      最关键的仍然是测试过程中对监控对象的灵活应用,例如目前三层结构的运行模式广泛使用,对中间件的并发性能测试作为问题被提到议事日程上来,许多系统都采用了国产中间件,选择Java scrīpt监控对象,手工编写脚本,可以达到测试目的。

      采用自动化负载测试工具执行的并发性能测试,基本遵循的测试过程有:测试需求与测试内容,测试案例制定,测试环境准备,测试脚本录制、编写与调试,脚本分配、回放配置与加载策略,测试执行跟踪,结果分析与定位问题所在,测试报告与测试评估。

      并发性能测试监控的对象不同,测试的主要指标也不相同,主要的测试指标包括交易处理性能指标和 UNIX资源监控。其中,交易处理性能指标包括交易结果、每分钟交易数、交易响应时间(Min:最小服务器响应时间;Mean:平均服务器响应时间;Max:最大服务器响应时间;StdDev:事务处理服务器响应的偏差,值越大,偏差越大;Median:中值响应时间;90%:90%事务处理的服务器响应时间)、虚拟并发用户数。

          应用实例:“新华社多媒体数据库 V1.0”性能测试

      中国软件评测中心(CSTC)根据新华社技术局提出的《多媒体数据库(一期)性能测试需求》和GB/T 17544《软件包质量要求和测试》的国家标准,使用工业标准级负载测试工具对新华社使用的“新华社多媒体数据库 V1.0”进行了性能测试。

      性能测试的目的是模拟多用户并发访问新华社多媒体数据库,执行关键检索业务,分析系统性能。

      性能测试的重点是针对系统并发压力负载较大的主要检索业务,进行并发测试和疲劳测试,系统采用B/S运行模式。并发测试设计了特定时间段内分别在中文库、英文库、图片库中进行单检索词、多检索词以及变检索式、混合检索业务等并发测试案例。疲劳测试案例为在中文库中并发用户数200,进行测试周期约8小时的单检索词检索。在进行并发和疲劳测试的同时,监测的测试指标包括交易处理性能以及 UNIX(Linux)、Oracle、Apache资源等。

      测试结论:在新华社机房测试环境和内网测试环境中,100M带宽情况下,针对规定的各并发测试案例,系统能够承受并发用户数为200的负载压力,最大交易数/分钟达到78.73,运行基本稳定,但随着负载压力增大,系统性能有所衰减。

      系统能够承受200并发用户数持续周期约8小时的疲劳压力,基本能够稳定运行。

      通过对系统UNIX(Linux)、Oracle和Apache资源的监控,系统资源能够满足上述并发和疲劳性能需求,且系统硬件资源尚有较大利用余地。

      当并发用户数超过200时,监控到HTTP 500、connect和超时错误,且Web服务器报内存溢出错误,系统应进一步提高性能,以支持更大并发用户数。

      建议进一步优化软件系统,充分利用硬件资源,缩短交易响应时间。

          疲劳强度与大数据量测试

      疲劳测试是采用系统稳定运行情况下能够支持的最大并发用户数,持续执行一段时间业务,通过综合分析交易执行指标和资源监控指标来确定系统处理最大工作量强度性能的过程。

      疲劳强度测试可以采用工具自动化的方式进行测试,也可以手工编写程序测试,其中后者占的比例较大。

      一般情况下以服务器能够正常稳定响应请求的最大并发用户数进行一定时间的疲劳测试,获取交易执行指标数据和系统资源监控数据。如出现错误导致测试不能成功执行,则及时调整测试指标,例如降低用户数、缩短测试周期等。还有一种情况的疲劳测试是对当前系统性能的评估,用系统正常业务情况下并发用户数为基础,进行一定时间的疲劳测试。

      大数据量测试可以分为两种类型:针对某些系统存储、传输、统计、查询等业务进行大数据量的独立数据量测试;与压力性能测试、负载性能测试、疲劳性能测试相结合的综合数据量测试方案。大数据量测试的关键是测试数据的准备,可以依靠工具准备测试数据。

      速度测试目前主要是针对关键有速度要求的业务进行手工测速度,可以在多次测试的基础上求平均值,可以和工具测得的响应时间等指标做对比分析。

          ·应用在网络上性能的测试

      应用在网络上性能的测试重点是利用成熟先进的自动化技术进行网络应用性能监控、网络应用性能分析和网络预测。

          网络应用性能分析

      网络应用性能分析的目的是准确展示网络带宽、延迟、负载和TCP端口的变化是如何影响用户的响应时间的。利用网络应用性能分析工具,例如Application Expert,能够发现应用的瓶颈,我们可知应用在网络上运行时在每个阶段发生的应用行为,在应用线程级分析应用的问题。可以解决多种问题:客户端是否对数据库服务器运行了不必要的请求?当服务器从客户端接受了一个查询,应用服务器是否花费了不可接受的时间联系数据库服务器?在投产前预测应用的响应时间;利用Application Expert调整应用在广域网上的性能;Application Expert能够让你快速、容易地仿真应用性能,根据最终用户在不同网络配置环境下的响应时间,用户可以根据自己的条件决定应用投产的网络环境。

          网络应用性能监控

      在系统试运行之后,需要及时准确地了解网络上正在发生什么事情;什么应用在运行,如何运行;多少 PC正在访问LAN或WAN;哪些应用程序导致系统瓶颈或资源竞争,这时网络应用性能监控以及网络资源管理对系统的正常稳定运行是非常关键的。利用网络应用性能监控工具,可以达到事半功倍的效果,在这方面我们可以提供的工具是Network Vantage。通俗地讲,它主要用来分析关键应用程序的性能,定位问题的根源是在客户端、服务器、应用程序还是网络。在大多数情况下用户较关心的问题还有哪些应用程序占用大量带宽,哪些用户产生了最大的网络流量,这个工具同样能满足要求。

          网络预测

      考虑到系统未来发展的扩展性,预测网络流量的变化、网络结构的变化对用户系统的影响非常重要。根据规划数据进行预测并及时提供网络性能预测数据。我们利用网络预测分析容量规划工具PREDICTOR可以作到:设置服务水平、完成日网络容量规划、离线测试网络、网络失效和容量极限分析、完成日常故障诊断、预测网络设备迁移和网络设备升级对整个网络的影响。

      从网络管理软件获取网络拓扑结构、从现有的流量监控软件获取流量信息(若没有这类软件可人工生成流量数据),这样可以得到现有网络的基本结构。在基本结构的基础上,可根据网络结构的变化、网络流量的变化生成报告和图表,说明这些变化是如何影响网络性能的。 PREDICTOR提供如下信息:根据预测的结果帮助用户及时升级网络,避免因关键设备超过利用阀值导致系统性能下降;哪个网络设备需要升级,这样可减少网络延迟、避免网络瓶颈;根据预测的结果避免不必要的网络升级。

          ·应用在服务器上性能的测试

      对于应用在服务器上性能的测试,可以采用工具监控,也可以使用系统本身的监控命令,例如Tuxedo中可以使用Top命令监控资源使用情况。实施测试的目的是实现服务器设备、服务器操作系统、数据库系统、应用在服务器上性能的全面监控,测试原理如下图。

    UNIX资源监控指标和描述

      监控指标 描述
      平均负载 系统正常状态下,最后60秒同步进程的平均个数
      冲突率 在以太网上监测到的每秒冲突数
      进程/线程交换率 进程和线程之间每秒交换次数
      CPU利用率 CPU占用率(%)
      磁盘交换率 磁盘交换速率
      接收包错误率 接收以太网数据包时每秒错误数
      包输入率 每秒输入的以太网数据包数目
      中断速率 CPU每秒处理的中断数
      输出包错误率 发送以太网数据包时每秒错误数
      包输入率 每秒输出的以太网数据包数目
      读入内存页速率 物理内存中每秒读入内存页的数目
      写出内存页速率 每秒从物理内存中写到页文件中的内存页数
       目或者从物理内存中删掉的内存页数目
      内存页交换速率 每秒写入内存页和从物理内存中读出页的个数
      进程入交换率 交换区输入的进程数目
      进程出交换率 交换区输出的进程数目
      系统CPU利用率 系统的CPU占用率(%)
      用户CPU利用率 用户模式下的CPU占用率(%)
      磁盘阻塞 磁盘每秒阻塞的字节数

    二、为什么进行性能测试?

          目的是验证软件系统是否能够达到用户提出的性能指标,同时发现软件系统中存在的性能瓶颈,优化软件,最后起到优化系统的目的。

          包括以下几个方面

    1.评估系统的能力,测试中得到的负荷和响应时间数据可以被用于验证所计划的模型的能力,并帮助作出决策。
    2.识别体系中的弱点:受控的负荷可以被增加到一个极端的水平,并突破它,从而修复体系的瓶颈或薄弱的地方。
    3.系统调优:重复运行测试,验证调整系统的活动得到了预期的结果,从而改进性能。
    检测软件中的问题:长时间的测试执行可导致程序发生由于内存泄露引起的失败,揭示程序中的隐含的问题或冲突。
    4.验证稳定性(resilience)可靠性(reliability):在一个生产负荷下执行测试一定的时间是评估系统稳定性和可靠性是否满足要求的唯一方法。

          性能测试类型包括负载测试,强度测试,容量测试等

          负载测试:负载测试是一种性能测试指数据在超负荷环境中运行,程序是否能够承担。

          强度测试: 强度测试是一种性能测试,他在系统资源特别低的情况下软件系统运行情况。

          容量测试:确定系统可处理同时在线的最大用户数 

          观察指标:

          性能测试主要是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。

          在实际中作中我们经常会对两种类型软件进行测试:bs和cs,这两方面的性能指标一般需要哪些内容呢?

    Bs结构程序一般会关注的通用指标如下(简):

    Web服务器指标指标:

    * Avg Rps: 平均每秒钟响应次数=总请求时间 / 秒数;

    * Avg time to last byte per terstion (mstes):平均每秒业务角本的迭代次数 ,有人会把这两者混淆;

    * Successful Rounds:成功的请求;

    * Failed Rounds :失败的请求;

    * Successful Hits :成功的点击次数;

    * Failed Hits :失败的点击次数;

    * Hits Per Second :每秒点击次数;

    * Successful Hits Per Second :每秒成功的点击次数;

    * Failed Hits Per Second :每秒失败的点击次数;

    * Attempted Connections :尝试链接数;

    CS结构程序,由于一般软件后台通常为数据库,所以我们更注重数据库的测试指标:

    * User 0 Connections :用户连接数,也就是数据库的连接数量;

    * Number of deadlocks:数据库死锁;

    * Butter Cache hit :数据库Cache的命中情况

          当然,在实际中我们还会察看多用户测试情况下的内存,CPU,系统资源调用情况。这些指标其实是引申出来性能测试中的一种:竞争测试。什么是竞争测试,软件竞争使用各种资源(数据纪录,内存等),看他与其他相关系统对资源的争夺能力。

          我们知道软件架构在实际测试中制约着测试策略和工具的选择。如何选择性能测试策略是我们在实际工作中需要了解的。一般软件可以按照系统架构分成几种类型:

    c/s

    client/Server 客户端/服务器架构

    基于客户端/服务器的三层架构

    基于客户端/服务器的分布式架构

    b/s

    基于浏览器/Web服务器的三层架构

    基于中间件应用服务器的三层架构l

    基于Web服务器和中间件的多层架构l

     

Open Toolbar