收集天下好文,各位朋友尽情发言。

发布新日志

  • 学好性能测试需要搞懂的问题

    2011-04-22 15:49:59

  • javascript中javascript:void(0) 的意思

    2011-01-12 10:28:58

  • Asp - SQL注入防范方法[最终篇]

    2011-01-09 23:46:40

  • Asp - SQL注入原理及防范[高级篇]

    2011-01-09 23:45:48

  • Asp - SQL注入原理及防范[中级篇]

    2011-01-09 23:45:00

  • Asp - SQL注入原理及防范[入门篇]

    2011-01-09 23:44:06

  • SQL注入原理详细分析

    2011-01-09 23:42:16

  • 关于oracle 去掉重复数据问题

    2011-01-07 11:27:55

  • Ivy与Ant的基本介绍(4)

    2010-11-18 12:37:33

    Ivy与Ant的基本介绍(4)
    2009-02-03 14:30
    前面的几篇文章,主要想介绍一些ivy的东西,但是一说ant,就啰嗦了那么多。一直没有进入正题,现在就开始吧。关于ivy和maven的区别和优缺点就不多说了,可以上网上查看一些。如果对maven感兴趣,可以看一下前面有关maven的博客

    首先,下载ivy,下载地址为:http://ant.apache.org/ivy/download.cgi 我现在的版本是2.0。然后将ivy-2.0.0.jar拷贝到ANT_HOME的lib目录下。我的lib目录为:C:\apache-ant-1.7.1\lib

    例子1:jar包版本控制以及拷贝到lib目录
    >> build.xm文件
    <?xml version="1.0"?>
    <project name="antwebproject" default="run" xmlns:ivy="antlib:org.apache.ivy.ant" basedir="e:/antTemp">
        <property name="lib.dir" value="lib" />
        <property name="build.dir" value="build" />
        <property name="src.dir" value="src" />

        <target name="resolve" description="--> retreive dependencies with ivy">
            <ivy:retrieve/>
        </target>
     

        <target name="run" depends="resolve" description="--> compile and run the project">
            <mkdir dir="${build.dir}" />
        </target>
    </project>


    >> 建立ivy.xml文件,将其放到 e:/antTemp 下面,因为在build.xml中,设置了basedir="e:/antTemp",不然这个文件和build.xml是在同一个目录的
    <ivy-module version="2.0">
        <info rganisation="org.apache" module="hello-ivy"/>
        <dependencies>
            <dependency rg="commons-lang" name="commons-lang" rev="2.0"/>
            <dependency rg="commons-cli" name="commons-cli" rev="1.0"/>
        </dependencies>
    </ivy-module>


    在控制台执行ant 命令后,执行截图如下:

    查看 E:\antTemp\lib 目录,下面有根据ivy.xml下载的jar包文件,如图:

    更多的文章可以参考\apache-ivy-2.0.0\doc 下面的index.html的帮助文档,里面主要有下面的内容
    1 如何单独运行 ivy
    2 ant的任务中如何使用ivy。主要是如何在build.xml中编写ivy的一些属性,介绍各个属性的用法
    3 ivy.xml文件的配置说明
    4 设置文件ivysettings.xml的配置说明
  • Ivy与Ant的基本介绍(3)

    2010-11-18 12:37:02

    Ivy与Ant的基本介绍(3)
    2009-02-02 17:21
    4. 使用Ant的war任务打包J2EE Web项目
    建立一个J2EE Web工程,其目录结构如下图所示:
    其中src 为源代码目录,WebRoot为各jsp存放目录,lib为工程的包目录。在antwebproject工程目录下建立了build.xml文件,该文件 为该工程的Ant构件文件。读者可以src目录下放入在前续例子中开发的HelloWorld.java文件,并在WebRoot下建立 index.jsp文件,其内容很简单,就是输出Hello信息,代码如下所示:
    <%@ page language="java" contentType="text/html; charset="UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
        
    <head>
           
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
           
    <title>ant打包测试</title>
        
    </head>
        
    <body>
            Hello,Ant
        
    </body>
    </html>


    接下来编写build.xml文件,其内容如下:
    <?xml version="1.0"?>
    <project name="antwebproject"   default="war" basedir=".">
    <property name="classes" value="build/classes"/>
        
    <property name="build" value="build"/>
        
    <property name="lib" value="WebRoot/WEB-INF/lib"/>
        
    <!-- 删除build路径-->
        
    <target name="clean">
           
    <delete dir="build"/>
        
    </target>

        
    <!-- 建立build/classes路径,并编译class文件到build/classes路径下-->
        
    <target name="compile" depends="clean">
           
    <mkdir dir="${classes}"/>

           
    <javac srcdir="src" destdir="${classes}"/>
        
    </target>

        
    <!-- war-->
        
    <target name="war" depends="compile">
    <war destfile="${build}/antwebproject.war" webxml="WebRoot/WEB-INF/web.xml">
               
    <!-- 拷贝WebRoot下除了WEB-INFMETA-INF的两个文件夹-->
        
    <fileset dir="WebRoot" includes="**/*.jsp"/>

               
    <!-- 拷贝lib目录下的jar-->
               
    <lib dir="${lib}"/>
               
    <!-- 拷贝build/classes下的class文件-->
               
    <classes dir="${classes}"/>
           
    </war>
        
    </target>
    </project>

    各target的作用在内容中已经进行说明,在此不再赘述。运行该build文件,更新目录后,可看到在build目录下生成了antwebproject.war文件,如图:

    解开后可看到其目录结构如下:
    --META-INF
         --MANIFEST.MF
    --index.jsp
    --WEB-INF
         --lib
                --log4j-1.2.9.jar
         --classes
                --HelloWorld.class
         --web.xml
         读者可以将该war包拷贝到Tomcat的目录下看一下运行结果。

    五.总结
    在 本文中,笔者由浅至深详细描述了Ant的安装与配置、关键元素和常用任务。并通过实例讲述了Ant在我们Java项目中的应用,讲述了编译、运行java 程序,以及打jar包、war包等知识,引领读者进入Ant的奇妙世界。在本文中可以看到,Ant在自动构建和部署Java程序方面方便易用,而且非常灵 活,不失为我们Java开发者的绝佳帮手。

    原文地址:http://tech.it168.com/j/2007-11-09/200711091344781.shtml

    --------------------------- 其它Ant知识摘录(下面的文字没有亲自测试过) ----------------------------------
    ant中执行Junit测试
    首先要确保正确的ant和junit测试环境。
    下面看个简单的例子:
    <target name="compile">
                <mkdir dir="${basedir}/build/tool/classes" />
                <javac destdir="${basedir}/build/tool/classes" includes="**/*.java" debug="${compile.debug}"   encoding="UTF-8">
                    <src path="${basedir}/tool/performancetest/src" />
                    <classpath refid="test.classpath" />
                </javac>
                <copy todir="${basedir}/build/tool/classes" verwrite="yes">
                    <fileset dir="${basedir}/tool/performancetest/src">
                        <include name="**/*.xml" />
                    </fileset>
                </copy>
    </target>

        <target name="test" depends="compile">
            <junit printsummary="on" fork="yes" >
                <formatter type="brief" usefile="false"/>
                <test name="com.zozoc.AllPerformanceTests"/>
                <classpath>
                    <pathelement location="${basedir}/build/tool/classes"/>
                    <path refid="test.classpath" />
                </classpath>
            </junit>
        </target>

    用Ant完成生成javadoc的任务
    用ant生成javadoc相当简单,命令如下:
    <target name="create_doc">
    <!-- destdir是javadoc生成的目录位置 -->
    <javadoc destdir="${distDir}" encoding="UTF-8" docencoding="UTF-8">
       <!-- dir是你的代码位置,记住是java文件的位置而不是class文件的位置哦,第一次用这个命令容易忽略这点 -->
       <packageset dir="${srcDir}">
        <!-- exclude是不想生成哪些类的javadoc -->
        <exclude name="${excludeClasses}" />
       </packageset>
    </javadoc>
    </target>

    ant条件判断
    [ 2008/06/17 15:48 | by followme ]
    大 | 中 | 小 
    前段时间写Ant的时候用到了条件判读condition,找了一堆资料,现总结如下:
    1、istrue isfalse:断言真假
    <project name="testCondition">
        <target name="test">
            <condition property="scondition">
                <istrue value="true"/>                   
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>

    2、逻辑运算
    2.1、not 逻辑非 
    <project name="testCondition">
        <target name="test">
            <condition property="scondition">
                <not>
                    <istrue value="true"/>                   
                </not>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>
    2.2、and 逻辑与
    <project name="testCondition">
        <target name="test">
            <condition property="scondition">
                <and>
                    <istrue value="true"/>
                    <istrue value="false"/>                   
                </and>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>
    2.3、or 逻辑或 xor异或 (语法上与and类似)

    3、available 是否可用
    <project name="testCondition">
        <path id="all.test.classes">        
             <pathelement location="bin"/>
         </path>
        <target name="test">
            <condition property="scondition">
                <!--在指定的classpath路径下是否存在资源 TestTest.class-->
                <available resource="TestTest.class">
                    <classpath refid="all.test.classes" />       
                </available>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>

    4、isset 指定属性是否存在
    <project name="testCondition">
        <!--属性也可以通过ant参数-D来设置-->
        <property name="name" value="this is name"/>   
        <target name="test">
            <condition property="scondition">
                <!--如果属性name不存在则返回false-->
                <isset property="name"/>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>

    5、equals 是否相等
    <project name="testCondition">
        <!--属性也可以通过ant参数-D来设置-->
        <property name="name" value="this is name"/>   
        <target name="test">
            <condition property="scondition">
                <!--如果arg1的值与arg2的值相等返回true,否则为false-->
                <equals arg1="${name}" arg2="this is name"/>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>   

    6、filesmatch 比较文件
    <project name="testCondition">       
        <target name="test">
            <condition property="scondition">
                <!--如果file1所代表的文件与file2所代表的文件相等返回true,否则为false-->
                <filesmatch file1="testfile1.txt" file2="testfile2.txt"/>
            </condition>
            <antcall target="isTrue"></antcall>
            <antcall target="isFalse"></antcall>       
        </target>
        <target name="isTrue" if="scondition">
            <echo>is ture</echo>
        </target>
        <target name="isFalse" unless="scondition">
            <echo>is false</echo>
        </target>
    </project>
  • Ivy与Ant的基本介绍(2)

    2010-11-18 12:36:13

    Ivy与Ant的基本介绍(2)
    2009-02-02 16:41
    四.利用Ant构建和部署Java工程
    Ant可以代替使用javac、java和jar等命令来执行java操作,从而达到轻松的构建和部署Java工程的目的。下面来看几个知识点。
    1. 利用Ant的javac任务来编译java程序
    Ant的javac任务用于实现编译Java程序的功能。下面来看一个简单的例子:
    首先我们建立名为antstudy的Java工程,建立src目录为源代码目录,在src目录下建立HelloWorld.java这个类文件。该类文件的内容如下:
    public class HelloWorld {
        
    public static void main(String[] args) {
            System.out.println("Hello,Amigo");
         }
    }

    同时在antstudy工程的根目录下建立build.xml文件,在该文件中编译src目录下的java文件,并将编译后的class文件放入build/classes目录中,在编译前,需清除classes目录,该文件的内容如下:
    <?xml version="1.0"?>
    <project name="javacTest"default="compile" basedir=".">
        
    <target name="clean">
           
    <delete dir="build"/>
        
    </target>

        
    <target name="compile" depends="clean">
           
    <mkdir dir="build/classes"/>
        
    <javac srcdir="src" destdir="build/classes"/>
        
    </target>
    </project>

    运行该build.xml文件,可在工程中看到新增了build/classes目录,并在该目录中生成了编译后的HelloWorld.class文件。如图

    2. 使用Ant的java任务运行Java程序
    Ant中可以使用java任务实现运行Java程序的功能。下面在1的例子中进行如下的修改,修改后的build.xml文件的内容如下:
    <?xml version="1.0"?>
    <project name="javaTest" default="run" basedir="e:/antTemp">
        
    <target name="clean">
           
    <delete dir="build"/>
        
    </target>

        
    <target name="compile" depends="clean">
           
    <mkdir dir="build/classes"/>
          
    <javac srcdir="src" destdir="build/classes"/>
        
    </target>

        
    <target name="run" depends="compile">
           
    <java classname="HelloWorld">
               
    <classpath>
                  
    <pathelement path="build/classes"/>
               
    </classpath>
           
    </java>
        
    </target>
    </project>

    运行该build.xml文件,可在控制台看到HelloWorld的main方法的输出。

    3. 使用Ant的jar任务生成jar文件
    读者可以在上例的基础上更进一步,来生成jar包,可在run这个target下再加上如下target:
    <target name="jar" depends="run">
    <jar destfile="helloworld.jar" basedir="build/classes">
               
    <manifest>
                  
    <attribute name="Main-class" value="HelloWorld"/>
               
    </manifest>
           
    </jar>
    </target>

    此时将ant的project的default属性设置为jar,同时运行该build.xml文件,运行完毕后,可看到在工程目录下生成了一个jar包HelloWorld.jar。
    运行helloworld.jar这个jar包,看看打包是否正确
    原文地址:http://tech.it168.com/j/2007-11-09/200711091344781.shtml
  • Ivy与Ant的基本介绍(1)

    2010-11-18 12:32:55

    Ivy与Ant的基本介绍(1)
    2009-02-02 15:53
    Ant是一个Apache基金会下的跨平台的构件工具,它可以实现项目的自动构建和部署等功能。在本文中,主要让读者熟悉怎样将Ant应用到Java项目中,让它简化构建和部署操作。

    一.安装与配置 

    下载地址:http://ant.apache.org/,在本文中下载的是1.7.1版本。解压到某个目录(例如C:\apache-ant-1.7.1),即可使用。 
    添加系统环境变量:ANT_HOME,该变量指向Ant解压后的根目录,在此为C:\apache-ant-1.7.1。 
    安装与配置完毕后,读者可以测试一下Ant是否可用,首先进入Ant的bin目录,运行命令ant –version,若安装和配置成功,则会显示Ant版本信息,如下图所示:
    由上可以看出,读者运行Ant的命令时,需要进入到Ant的bin目录,如何才能让系统自动找到Ant呢?这时需要读者在系统环境变量path中添加Ant的bin目录。设置完成后,我们就可以在任何目录(例如C:"Documents and Settings"AmigoXie目录)输入Ant的命令,来获得命令的运行结果。

    二.Ant的关键元素

    Ant的构件文件是基于XML编写的,默认名称为build.xml。为了更清楚的了解Ant,在这里编写一个简单的Ant程序,用来展现Ant的功能,让读者对Ant有一个初步的了解。首先在E盘下建立一个build.xml文件,内容如下:
    <?xml version="1.0"?>
    <project name="helloWorld">
           
    <target name="sayHelloWorld">
                  
    <echo message="Hello,Amigo"/>
           
    </target>
    </project>

    进入E盘,然后运行ant sayHelloWorld,可以看到如下的运行结果:

    其中sayHelloWorld为需要执行的任务的名称。如果文件名不为build.xml,而为hello.xml时,读者运行同样的命令时,命令窗口会出现如下错误:
    Buildfile: build.xml does not exist!
    Build failed
    由上面的命令的错误提示可以看出,ant命令默认寻找build.xml文件。若文件名为hello.xml时,读者还需要对命令做少许改变,改为:ant –f hello.xml sayHelloWorld、ant –buildfile hello.xml sayHelloWorld或ant –file hello.xml sayHelloWorld。
    接下来开始向读者讲解本节的重点:Ant的关键元素project、target、property和task。

    1.project元素
    project元素是Ant构件文件的根元素,Ant构件文件至少应该包含一个project元素,否则会发生错误。在每个project元素下,可包含多个target元素。接下来向读者展示一下project元素的各属性。

    1)name属性
    用于指定project元素的名称。
    2)default属性
    用于指定project默认执行时所执行的target的名称。
    3)basedir属性
    用于指定基路径的位置。该属性没有指定时,使用Ant的构件文件的附目录作为基准目录。
    下面给读者一个简单的例子来展示project的各元素的使用。修改E:"build.xml文件,修改后的内容如下:
    <?xml version="1.0"?>
    <project name="projectStudy" default="sayBaseDir" basedir="e:/antTemp">
           
    <target name="sayBaseDir">
                  
    <echo message="The base dir is: ${basedir}"/>
           
    </target>
    </project>

    从上面的内容我们可以看出,在这里定义了default属性的值为sayBaseDir,即当运行ant命令时,若未指明执行的target时,默认执行的target的sayBaseDir,同时还定义了basedir属性的值为E:"apache-ant-1.7.0,进入E盘后运行ant命令,可看到运行的结果,如下图所示:

    为设定了basedir的值,所以basedir属性的值变成了读者设置的值。读者可以自行将project元素的basedir属性去掉后运行ant看看运行结果,此时basedir的值变成了E:",即为Ant构件文件的父目录。

    有的时候,读者可能有这种需求,即想得到某个project下所有的target的名称,读者可以通过在ant命令里加上-proecthelp来达到该目的。例如针对上述的例子我们运行ant –projecthelp,输出结果如下:Buildfile: build.xml
    Main targets:

    Other targets:

    sayBaseDir

    Default target: sayBaseDir

    2. target元素
    它为Ant的基本执行单元,它可以包含一个或多个具体的任务。多个target可以存在相互依赖关系。它有如下属性:
    1)name属性
    指定target元素的名称,这个属性在一个project元素中是唯一的。我们可以通过指定target元素的名称来指定某个target。
    2)depends属性
    用于描述target之间的依赖关系,若与多个target存在依赖关系时,需要以“,”间隔。Ant会依照depends属性中target出现的顺序依次执行每个target。被依赖的target会先执行。
    3)if属性
    用于验证指定的属性是否存在,若不存在,所在target将不会被执行。
    4)unless属性
    该属性的功能与if属性的功能正好相反,它也用于验证指定的属性是否存在,若不存在,所在target将会被执行。
    5)description属性
    该属性是关于target功能的简短描述和说明。
    下面带领读者来看一个各属性综合使用的例子。修改E:"build.xml文件,修改后的内容如下:
    <?xml version="1.0"?>
    <project name="targetStudy">
           
    <target name="targetA" if="ant.java.version">
                  
    <echo message="Java Version: ${ant.java.version}"/>
           
    </target>
           
    <target name="targetB" depends="targetA" unless="amigo">
                  
    <description>
                                 a depend example!
                  
    </description>
                  
    <echo message="The base dir is: ${basedir}"/>
           
    </target>
    </project>

    进入E盘后运行ant targetB,可看到如下图所示的运行结果:
    读者分析结果后可以看到,我们运行的是名为targetB的target,因该target依赖于targetA,所以targetA将首先被执行,同时因为系统安装了java环境,所以ant.java.version属性存在,执行了targetA这个target,输出信息:[echo] Java Version: 1.5,targetA执行完毕后,接着执行targetB,因为amigo不存在,而unless属性是在不存在时进入所在的target的,由此可知targetB得以执行,输出信息:The base dir is: E:"。

    3. property元素
    该元素可看作参量或者参数的定义,project的属性可以通过property元素来设定,也可在Ant之外设定。若要在外部引入某文件,例如build.properties文件,可以通过如下内容将其引入:<property file=” build.properties”/>
    property元素可用作task的属性值。在task中是通过将属性名放在“${”和“}”之间,并放在task属性值的位置来实现的。
    Ant提供了一些内置的属性,它能得到的系统属性的列表与Java文档中System.getPropertis()方法得到的属性一致,这些系统属性可参考sun网站的说明。
    同时,Ant还提供了一些它自己的内置属性,如下:
    basedir:project基目录的绝对路径,该属性在讲解project元素时有详细说明,不再赘述;
    ant.file:buildfile的绝对路径,如上面的各例子中,ant.file的值为E:"build.xml;
    ant.version:Ant的版本,在本文中,值为1.7.0;
    ant.project.name:当前指定的project的名字,即前文说到的project的name属性的值;
    ant.java.version:Ant检测到的JDK的版本,在上例运行结果中可看到为1.5。
    下面让读者来看一个property元素使用的简单例子。修改E:"build.xml文件,内容如下:
    <?xml version="1.0"?>
    <project name="propertyStudy" default="example">
    <property name="name" value="amigo"/>
    <property name="age" value="25"/>
    <target name="example">
            
    <echo message="name: ${name}, age: ${age}"/>
    </target>
    </project>

    运行结果如图:
    由此读者可以看出,通过如下两个语句:
    <property name="name" value="amigo"/>
    <property name="age" value="25"/>
    我们设置了名为name和age的两个属性,这两个属性设置后,读者在下文中可以通过${name}和${age}分别取得这两个属性的值。

    三.Ant的常用任务
    在Ant工具中每一个任务封装了具体要执行的功能,是Ant工具的基本执行单位。在本小节中,主要引导读者来看下Ant的常用任务及其使用举例。
    1.copy任务
    该任务主要用来对文件和目录的复制功能。举例如下:
    Eg1.复制单个文件:<copy file="file.txt" tofile="copy.txt"/>
    如:
    <?xml version="1.0"?>
    <project name="propertyStudy" default="example" basedir="e:/antTemp">
        <target name="example">
                <copy file="file.txt" tofile="copy.txt"/>
        </target>
    </project>
    执行ant,结果如图:

    Eg2.对文件目录进行复制:
       <copy todir="../newdir/dest_dir">
                <fileset dir="src_dir"/>
    </copy>
    Eg3. 将文件复制到另外的目录:
    <copy file="file.txt" todir="../other/dir"/>
    2. delete任务
    对文件或目录进行删除,举例如下:
    Eg1. 删除某个文件:<delete file="photo/amigo.jpg"/>
    Eg2. 删除某个目录:<delete dir="photo"/>
    Eg3. 删除所有的备份目录或空目录:
            <delete includeEmptyDirs="true">
                   <fileset dir="." includes="**/*.bak"/>
            </delete>
    3.mkdir任务
    创建目录。eg:<mkdir dir="build"/>
    4. move任务
    移动文件或目录,举例如下:
    Eg1. 移动单个文件:<move file="fromfile" tofile=”tofile”/>
    Eg2. 移动单个文件到另一个目录:<move file="fromfile" todir=”movedir”/>
    Eg3. 移动某个目录到另一个目录:
            <move todir="newdir">
                   <fileset dir="olddir"/>
            </move>
    5.echo任务
    该任务的作用是根据日志或监控器的级别输出信息。它包括message、file、append和level四个属性,举例如下:
    <echo message="Hello,Amigo" file="logs/system.log" append="true">

    原文地址:http://tech.it168.com/j/2007-11-09/200711091344781.shtml
  • 一个Bug 差点让服务器的文件系统崩溃(转贴)

    2010-07-16 09:34:43

    昨天,公司的美国客户发邮件给我,说我的软件出问题了,我查来查去,发现居然是服务器上一个目录无法删除,一删除就报 cannot read from the source file or disk. 如果用命令行方式删除,则报  cannot find the specified path。一开始以为是文件系统遭破坏了,用 chkdsk 命令检查,没有发现问题,后来仔细一看,那个不能删除的目录名居然以一个空格字符结尾,而我尝试在资源管理器中创建一个目录以空格结尾结果资源管理器会自 动将末尾的字符删除,用程序创建,结果也一样,这个美国佬是怎么创建这个古怪的目录的?出现这种情况后不但是无法删除这么简单,列目录什么的也会有问题, 这样一来,系统的运行都会有问题,我想到的最坏结果就是可能不得不格式化服务器的硬盘,想到这里我几乎不敢再想下去了!Research了一天,后来终于 找到了解决方案,并且由此还发现问题的起因是我程序上的一个Bug造成,可怕的Bug!

    Windows 的文件系统可以支持特殊字符的文件名,比如以空格结尾,以点号结尾等,有一篇英文的文章说NTFS 支持这些文件名,但FAT不支持,我试了一下,FAT也支持。但Windows API 却对这些特殊文件名进行了限制,也就是说,我们通过程序是无法创建一个以空格或点号结尾的文件名或路径名的。但Copy 和 Move的API 却不做这方面的限制,这导致我们可以从其他的文件系统拷贝或移动一个特殊文件名的文件到Windows 的文件系统,但一旦在Windows的文件系统上创建成功,就无法通过正常途径删除或改名。因为调用API 删除或改名时,API 会首先进行规则检查,如果发现不符合规则,则直接忽略。这两组API 在处理上的不一致,带来一个非常严重的安全问题,可惜微软到了Windows7 还没有去弥补这个问题。

    下面让我们用代码复现这个问题

                try
                {
                    string dir = @"C:\Temp\abc";
                    System.IO.Directory.CreateDirectory(dir); //在C:\Temp 目录下创建abc 这个目录
     
                    string dir1 = @"c:\Temp\Bcd \";
     
                    System.IO.Directory.Move(dir, dir1); //将ABC 移动到"Bcd "这个目录去,注意这里 Bcd后面有个空格
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

    在运行这段代码前,你一定要有一点思想准备,因为一旦运行成功,你的 C:\temp 目录下就有了一个 “Bcd ”这样的古怪的目录,而且你用正常的方法根本无法删除它。如果我在此打住,你一定会为之抓狂。不过没关系,我已经找到了删除它的方法,下面就和大家共享:

     

    Windows 的命令行工具 Del 和 Rd 支持一种方式可以不对输入文件名的合法性进行检查,这种方式是在完整目录名前加一个 \\?\

    比如

    del “\\?\C:\Temp\xxx.” 删除xxx. 这个文件

    删除目录的话

    rd /s “\\?\C:\Temp\xxx.” 删除 xxx. 这个目录

    执行这个命令后,就可以删除这些古怪的文件了。注意,这里一定要输入完整的目录才可以,相对路径不行。

     

    讲到这里,我们知道了原因和解决方案,那么在这里我需要提醒大家我们以后在程序中调用 System.IO.Directory.Move 或者 System.IO.File.Copy , System.IO.File.Move 这些函数前,一定要注意先判断一下输入的目标文件名或目录名的结尾是不是空格或点号,可能还要判断其他情况,但目前我只知道这两种情况,而且结尾是空格非 常有隐蔽性。

  • 如何估算测试工作量(一)常规的估算测试工作量的方法

    2010-03-02 10:44:12

    如何估算测试工作量
    (一)常规的估算测试工作量的方法
    作为一个管理者,你是否被询问到某个项目要花多少时间,多少人力测试;或是作为一个普通的测试员,你是否被询问到要花多少时间来完成某个任务或是一次回归测试?我想大多数在软件行业的人或多或少都会碰到这样的关于工作量估计的询问。那么你是怎么回答的呢?你对你自己的回答有信心吗?你是否最终发现实际上花去的时间和原本估计的时间大相径庭呢?
    不同的人会使用许多不同的方法来估算及安排他们的测试工作量。不同的组织根据项目的类型,项目的内在风险,涉及的技术等而使用不同的方法。但是大多数时候测试工作量是和开发工作量合在一起的,没有一个单独的数字。
    首先让我们来看看一些常规的估算测试工作量的方法:
    1. Ad-hoc方法
    这种方法下的测试工作量不基于任何确定的期限。工作一直继续直到达到一些由管理或市场人员预先定下的时间表。或者,一直到用完了预算的经费。
    这种情况普遍存在于非常不成熟的组织,并且时常有100%的错误差数。
    2.开发时间的百分比法Percentage of development time
    .这个方法的基本前提是测试工作量依赖于开发时间/开发工作量。首先,开发工作量使用例如LOC或FP方法被估算出来,然后使用一些探索性的方法来限制测试的工作量。这种方法变化比较大而且通常基于以前的经验。
    通常预留项目的总花费时间的35%给测试。
    • 5-7%给组件和集成测试
    • 18-20%给系统测试
    • 10%给接收测试(或回归测试等)
    3.类比法(经验值法或历史数据法)
    根据以前或相似项目(主要在项目性质,领域,规模上有相似)所积累的经验或历史数据来估算工作量。类比法估计结果的精确度取决于历史项目数据的完整性和准确度,因此,用好类比法的前提条件之一是组织建立起较好的项目后评价与分析机制,对历史项目的数据分析是可信赖的。需要收集以下相关的历史数据:
    • 在设计和实现阶段花费的时间
    • 测试工作的规模,例如用户需求的数量,页面数,功能点
    • 数据样式,例如实体,字段的数量
    • 屏幕或字段数量
    • 测试对象的规模,例如KLOC
    4.WBS(work breakdown structure)估算法
    将项目或产品分解为具体的工作,然后分别对各个工作进行时间估算,最终求和得出项目或产品的测试工作量/时间。
    5.Delphi 法
    Delphi法是最流行的专家评估技术,在没有历史数据的情况下,这种方式可以减轻估算的偏差。Delphi法鼓励参加者就问题相互讨论。这个技术,要求有多种相关经验人的参与,互相说服对方。。
    Delphi法的步骤是:
    1、协调人向各专家提供项目规格和估计表格;
    2、协调人召集小组会各专家讨论与规模相关的因素;
    3、各专家匿名填写迭代表格;
    4、协调人整理出一个估计总结,以迭代表的形式返回专家;
    5、协调人召集小组会,讨论较大的估计差异;
    6、专家复查估计总结并在迭代表上提交另一个匿名估计;
    7、重复4-6, 直到达到一个最低和最高估计的一致。
    6.PERT估计法
    PERT对各个项目活动的完成时间按三种不同情况估计:一个产品的期望规模,一个最低可能估计,一个最高可能估计。用这三个估计用来得到一个产品期望规模和标准偏差的Pert 统计估计。Pert 估计可得到代码行的期望值E, 和标准偏差SD。

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/imlogic/archive/2007/11/16/1887723.aspx

  • QTP与QC的完美结合实现自动化测试框架-业务组件测试

    2010-03-01 17:58:23

    摘要:利用QTP和QC相结合搭建功能自动化测试框架

    关键词:自动化测试 测试框架 组件

    做功能自动化测试都会不约而同的遇到一个比较棘手的问题-测试框架的搭建。这也是直接影响功能自动化测试成功与否的关键。框架做的好可以使测试事半功倍,反之轻则很难看到工作的成果重则会使整个测试失败。目前网上有很多关于测试框架的讨论,其中也有成型的测试框架,其中有很多好的思想在里边,很值得借鉴。但今天要讨论的不是网上已有的,而是HP已经为我们设计好的一个测试体系,业务组件测试。他是利用QTP与QC的完美结合组成的一个体系架构。它可以轻易实现目前比较流行的三层测试架构:脚本层,业务层,数据层相分离,为开展功能自动化测试提供一个高效、稳定、容易的测试实现。

    一.概述

    1.1业务组件(Bussiness Process Testing)简介

    业务组件是组成流程测试的基本单元,组合不同的业务组件可以实现不同的业务流程测试。如将fligt系统的登录最为一个组件,选择航班最为一个组件等。这样可以实现组件的复用,提高开发效率。

    1.2 Bussiness Process Testing的优点

    1) 相关业务人员可以在没有脚本的环境下组合业务组件,实现业务流程。

    2) 对业务人员的编程能力没有要求,业务人员只需了解系统的业务流程,不用关心具体的脚本实现。这一点也实现了业务层和脚本层的分离。

    3) 一旦某个组件开发完毕,即可在不同的流程中使用该组件,实现高可复用性,从而加快业务流程测试的速度。

    4) 明确的角色分工,业务人员负责流程的开发、组织;QTP工程师负责脚本的开发、维护以及相应函数库的开发、维护。

    5) 因为实现了脚本的复用,提高了自动化开发的效率,无形中就降低了测试过程中维护的时间和成本。

    1.3 Bussiness Process Testing的简易流程

    如图所示,整个过程分为2条线:第一个是由业务测试人员划分组件并组合不同的组件实现不同的流程测试;其次QTP专家负责组件的脚本具体实现并负责调试成功,上传到QC供业务测试人员调用。

    注:测试数据的组织后边介绍,以便实现三层的测试架构;此过程需要QC有Bussiness Process Testing组件许可的支持,也就是需要单独向HP购买。

    下边以QTP自带的示例程序演示整个流程的开发过程

    2.1划分组件

    本次将系统划分为:登录;选择航班并插入;打开订单;更新订单;删除订单;注销。这样划分仅为演示之用,不用在实际的测试之中。

    2.2组织业务测试流程

    本次只是用于演示,所以流程不会100%覆盖,在实际的测试过程中要达到100%的流程覆盖。本次测试流程如下:

    流程1:登录-选择航班并插入-注销

    流程2:登录-选择航班并插入-更新订单-注销

    流程3:登录-选择航班并插入-更新订单-删除订单-注销

    流程4:登录-打开订单-更新订单-删除订单-注销

    下边需要根据划分的组件来实现组件脚本的实现。

    2.3创建应用程序区域

    在开发脚本之前首先要做的是要创建一个应用程序区域。应用程序区域提供创建业务组件所需的所有资源和设置,每个业务组建都居于一个应用程序区域,并从这些应用程序区域集成这些资源和设置。在此创建一个名为“订票系统流程测试”的区域,如图所示。

    创建过程:依次选择:file-New-Function library。保存后自动上传至QC默认目录。

    在此也可以加载自己的函数库,对象库,恢复场景等,这样以后创建的组建都可以共享该应用程序区域的资源。同时也方便维护,这也是一个优点所在,例如一旦函数库改变在此从新加载新的函数库即可,不用在脚本理修改。总之这个应用程序区域很重要,以后所有的脚本均是基于这个区域。应用程序路径一定要加载正确,否则录制时不能生成脚本。

    2.4创建脚本

    在创建脚本之前最好在QC中组织好目录树,方便保存及调用。关于脚本的开发过程,每个人、每个公司都有自己的方法。在此源代码也没法一一贴出。所以在此只列出输入参数和输出参数,方便后边的参数化以及数据组织。本次也采用最通用的方式即对象库解决对象识别问题。脚本的开发规范以及参数命名也以我自己惯用方式。

  • 如何进行报表测试?

    2010-02-08 16:21:19

    报表功能的基本要求,就是通过查询、统计、分析,为用户提供准确的数据,帮助用户做出决策。在此主要是与大家分享一下报表测试的经验。

    一、熟悉业务:
        对任何软件进行功能测试,都必须要熟悉业务,包括业务流程和业务规则。但是报表测试同一般的业务功能测试还是有些区别的,比如:报表的业务很难直接通过对界面的浏览和探索性操作去了解业务。对于报表业务的熟悉,主要是两个方面:数据项的算法和数据来源,也就是说要明白一个数据项同具体的业务有什么关系,单据的增、删、改或者状态的变化,对报表中各个数据项的计算会产生什么不同的影响。如果不知道到这些,那么就无法验证报表中的数据是否准确,也无法通过报表去检查业务系统的正确与否。


    二、准备完整、高效、专用的数据:
        1、从查询统计方法角度准备数据:尽可能覆盖到报表所提供的各查询统计方法的数据,至少保证每一种查询统计方法都应该有对应的数据,得到的结果不是0,否则等于没有覆盖到这个查询统计算法。

        2、从数据源的属性来准备数据:这里涉及到的方面比较多,都是跟数据来源有关,现举例说明:a.同样的业务数据来源于多个数据表,则需要准备多个数据表中的数据;b.与状态相关的数据,有些状态需要纳入统计,有些不需要,但这些数据都需要准备;c.数据来源与显示数据不同时,比如在 数据库中存储的是1,显示时则需要显示为“是”。等等。。。

        3、从数据项的算法来准备特殊数据:比如:除数为0,以及与0相加,是否可以得到正确的结果;

        4、数据的优化:按上述的方法基本上可以准备比较完整的数据了,但数据也不是越多越好,为了提高测试效率,需要对数据进行优化,尽量保证用最少的数据覆盖所有可能的情况。

        5、为报表准备专用的数据:即使个人精心准备了报表数据,如果多人同时测试,或者本人在测试业务时,录入了其他数据,都会对报表的数据产生影响;所以需要在开始测试时,团队内对数据的准备达成一致,使数据中的某一项具有特征性,例如分别使用不同的供应商,或者使用不同的商品。

        6、做好数据环境的备份和维护:
        数据文档的备份与维护:
        在测试过程中难免会因为误操作导致环境的变化,例如:不小心把一张单据变成了另外一种状态,或者某个类型的单据多做了一张。对于这种情况,一个简单的方法就是去维护数据文档。当然,前提就是需要对原始的数据文档进行备份。

        测试数据库的备份与恢复:
        如果想减少回归测试的工作量,那么应该考虑在一些关键的“点”上备份测试数据。例如所有的基础数据与单据已经输入完成,但是还都没有开始审核,那么可以备份一下,下次再测的时候可以直接在数据库中恢复这部分原始数据。

        另外:
        在准备报表数据的过程中,还需要多与开发人员进行沟通,一来可以了解开发人员采用的算法是否与需求符合;二来可以更加明确数据的来源。
        在进行业务功能的测试时,可以通过业务测试的过程,把报表测试所需要的数据输入到系统中。


    三、在业务功能测试通过之后才开始:
        业务功能测试是报表测试的基础。如果业务功能本身存在缺陷,导致的数据不准,那么进行报表测试也就没有什么意义了。所以,应该在保证各项同报表有关的业务的功能测试通过之后,才开始考虑对报表进行测试。


    四、尽可能覆盖报表所提供的各种查询统计方法:
        报表的使用者一般是企业的中层或高层领导,他们对于报表的要求可能会是多方面的,例如在进销存系统中,可能需要按不同商品进行分类统计,也可能是按供应商分类统计,这些都是由用户在实际工作中的需要来决定的,所以假如一个报表提供了多种查询统计的方法,那么在测试时,只要时间充分,就应该覆盖这些所有可能被用到的查询统计方法。


    五、对存在联系的多个报表进行相互对照:这需要非常了解各报表之间存在的联系。例如:库存报表中,可以看到商品的出入库情况,而在销售报表中,可以看到商品的销售金额和销售成本金额,对业务熟悉到一定程度就会知道实际上这两种报表之间就存在着某种联系。


    六、着重对那些算法复杂、与业务功能关联较多的报表的测试。


    七、留意数据的显示:小数位,千位符,四舍五入等是否与报表设置一致;单位转换是否正确;组合显示的数据是否合理 ;数据的排序。等等。。。


    八、保证测试人员可以通过软件功能界面找到自己所需的所有原始数据,而不是通过SQL语句来查找,因为实际用户在使用软件时,是不会到数据库中查找数据的。


    九、对有些报表需要考虑权限控制和访问安全性的测试。


    十、大数据量的测试。
  • 《零基础学习软件测试》系列视频之QTP使用指南(全)

    2010-02-08 16:20:22

    1 qtp目录分析
    http://www.boobooke.com/v/bbk1590
    2 qtp界面分析
    http://www.boobooke.com/v/bbk1594
    3 qtp示例程序分析
    http://www.boobooke.com/v/bbk1598
    4 qtp学习指南
    http://www.boobooke.com/v/bbk1515
    5 qtp基本操作录制与回放
    http://www.boobooke.com/v/bbk1591
    6 qtp的三种录制方式
    http://www.boobooke.com/v/bbk1516
    7 增强help步骤
    http://www.boobooke.com/v/bbk1592
    8 checkpoint
    http://www.boobooke.com/v/bbk1595
    9 参数化
    http://www.boobooke.com/v/bbk1599
    10 Tools下的工具介绍
    http://www.boobooke.com/v/bbk1589
    11 qtp插件分析
    http://www.boobooke.com/v/bbk1689
    12 qtp测试用例设计考题
    http://www.boobooke.com/v/bbk1575
    13 vbs
    http://www.boobooke.com/v/bbk1621
    14 recovery Scenarios
    http://www.boobooke.com/v/bbk1692
    15 虚拟对象
    http://www.boobooke.com/v/bbk1695
    16 专家视图测试脚本开发
    http://www.boobooke.com/v/bbk1690
    17 qtp描述性编程
    http://www.boobooke.com/v/bbk1691
    18 qtp测试脚本编写规范
    http://www.boobooke.com/v/bbk1693
    19 如何建立自动化测试框架
    http://www.boobooke.com/v/bbk2097
    20 QTP之焦点
    http://www.boobooke.com/v/bbk2146
    21 手工测试 PK 自动化测试
    http://www.boobooke.com/v/bbk2148
    22 QTP使用指南第一部分基础知识讲解完结篇
    http://www.boobooke.com/v/bbk2147
  • JavaScript基础了解

    2010-02-02 17:13:13

    JavaScript. 1:基础知识 

    1 创建脚本块

    1: <script. language=”JavaScript”>
    2: JavaScript. code goes here
    3: </script> 

    2 隐藏脚本代码

    1: <script. language=”JavaScript”>
    2: <!--
    3: document.write(“Hello”);
    4: // -->
    5: </script> 

    在不支持JavaScript的浏览器中将不执行相关代码

    3 浏览器不支持的时候显示

    1: <noscript>
    2: Hello to the non-JavaScript. browser.
    3: </noscript> 

    4 链接外部脚本文件

    1: <script. language=”JavaScript” src="/”filename.js"”></script> 

    5 注释脚本

    1: // This is a comment
    2: document.write(“Hello”); // This is a comment
    3: /*
    4: All of this
    5: is a comment
    6: */ 

    6 输出到浏览器

    1: document.write(“<strong>Hello</strong>”); 

    7 定义变量

    1: var myVariable = “some value”; 

    8 字符串相加

    1: var myString = “String1” + “String2”; 

    9 字符串搜索

    1: <script. language=”JavaScript”>
    2: <!--
    3: var myVariable = “Hello there”;
    4: var therePlace = myVariable.search(“there”);
    5: document.write(therePlace);
    6: // -->
    7: </script> 

    10 字符串替换

    1: thisVar.replace(“Monday”,”Friday”); 


    11 格式化字串

    1: <script. language=”JavaScript”>
    2: <!--
    3: var myVariable = “Hello there”;
    4: document.write(myVariable.big() + “<br>”);
    5: document.write(myVariable.blink() + “<br>”);
    6: document.write(myVariable.bold() + “<br>”);
    7: document.write(myVariable.fixed() + “<br>”);
    8: document.write(myVariable.fontcolor(“red”) + “<br>”);
    9: document.write(myVariable.fontsize(“18pt”) + “<br>”);
    10: document.write(myVariable.italics() + “<br>”);
    11: document.write(myVariable.small() + “<br>”);
    12: document.write(myVariable.strike() + “<br>”);
    13: document.write(myVariable.sub() + “<br>”);
    14: document.write(myVariable.sup() + “<br>”);
    15: document.write(myVariable.toLowerCase() + “<br>”);
    16: document.write(myVariable.toUpperCase() + “<br>”);
    17: 
    18: var firstString = “My String”;
    19: var finalString = firstString.bold().toLowerCase().fontcolor(“red”);
    20: // -->
    21: </script> 

    12 创建数组

    1: <script. language=”JavaScript”>
    2: <!--
    3: var myArray = new Array(5);
    4: myArray[0] = “First Entry”;
    5: myArray[1] = “Second Entry”;
    6: myArray[2] = “Third Entry”;
    7: myArray[3] = “Fourth Entry”;
    8: myArray[4] = “Fifth Entry”;
    9: var anotherArray = new Array(“First Entry”,”Second Entry”,”Third Entry”,”Fourth Entry”,”Fifth Entry”);
    10: // -->
    11: </script> 

    13 数组排序

    1: <script. language=”JavaScript”>
    2: <!--
    3: var myArray = new Array(5);
    4: myArray[0] = “z”;
    5: myArray[1] = “c”;
    6: myArray[2] = “d”;
    7: myArray[3] = “a”;
    8: myArray[4] = “q”;
    9: document.write(myArray.sort());
    10: // -->
    11: </script> 

    14 分割字符串

    1: <script. language=”JavaScript”>
    2: <!--
    3: var myVariable = “a,b,c,d”;
    4: var stringArray = myVariable.split(“,”);
    5: document.write(stringArray[0]);
    6: document.write(stringArray[1]);
    7: document.write(stringArray[2]);
    8: document.write(stringArray[3]);
    9: // -->
    10: </script> 

    15 弹出警告信息

    1: <script. language=”JavaScript”>
    2: <!--
    3: window.alert(“Hello”);
    4: // -->
    5: </script> 

    16 弹出确认框

    1: <script. language=”JavaScript”>
    2: <!--
    3: var result = window.confirm(“Click OK to continue”);
    4: // -->
    5: </script> 

    17 定义函数

    1: <script. language=”JavaScript”>
    2: <!--
    3: function multiple(number1,number2) { 
    4: var result = number1 * number2;
    5: return result;
    6: }
    7: // -->
    8: </script> 

    18 调用JS函数

    1: <a href=”#” nClick=”functionName()”>Link text</a>
    2: <a href="/”________javascript.:functionName"()”>Link text</a> 

    19 在页面加载完成后执行函数

    1: <body nLoad=”functionName();”>
    2: Body of the page
    3: </body> 

    20 条件判断

    1: <script>
    2: <!--
    3: var userChoice = window.confirm(“Choose OK or Cancel”);
    4: var result = (userChoice == true) ? “OK” : “Cancel”;
    5: document.write(result);
    6: // -->
    7: </script> 

    21 指定次数循环

    1: <script>
    2: <!--
    3: var myArray = new Array(3);
    4: myArray[0] = “Item 0”;
    5: myArray[1] = “Item 1”;
    6: myArray[2] = “Item 2”;
    7: for (i = 0; i < myArray.length; i++) { 
    8: document.write(myArray[i] + “<br>”);
    9: }
    10: // -->
    11: </script> 

    22 设定将来执行

    1: <script>
    2: <!--
    3: function hello() { 
    4: window.alert(“Hello”);
    5: }
    6: window.setTimeout(“hello()”,5000);
    7: // -->
    8: </script> 

    23 定时执行函数

    1: <script>
    2: <!--
    3: function hello() { 
    4: window.alert(“Hello”);
    5: window.setTimeout(“hello()”,5000);
    6: }
    7: window.setTimeout(“hello()”,5000);
    8: // -->
    9: </script> 

    24 取消定时执行

    1: <script>
    2: <!--
    3: function hello() { 
    4: window.alert(“Hello”);
    5: }
    6: var myTimeout = window.setTimeout(“hello()”,5000);
    7: window.clearTimeout(myTimeout);
    8: // -->
    9: </script> 

    JavaScript. 2:浏览器输出 

    26 访问document对象

    1: <script. language=”JavaScript”>
    2: var myURL = document.URL;
    3: window.alert(myURL);
    4: </script> 

    27 动态输出HTML

    1: <script. language=”JavaScript”>
    2: document.write(“<p>Here’s some information about this document:</p>”);
    3: document.write(“<ul>”);
    4: document.write(“<li>Referring Document: “ + document.referrer + “</li>”);
    5: document.write(“<li>Domain: “ + document.domain + “</li>”);
    6: document.write(“<li>URL: “ + document.URL + “</li>”);
    7: document.write(“</ul>”);
    8: </script> 

    28 输出换行

    1: document.writeln(“<strong>a</strong>”);
    2: document.writeln(“b”); 

    29 输出日期

    1: <script. language=”JavaScript”>
    2: var thisDate = new Date();
    3: document.write(thisDate.toString());
    4: </script> 

    30 指定日期的时区

    1: <script. language=”JavaScript”>
    2: var myOffset = -2;
    3: var currentDate = new Date();
    4: var userOffset = currentDate.getTimezoneOffset()/60;
    5: var timeZoneDifference = userOffset - myOffset;
    6: currentDate.setHours(currentDate.getHours() + timeZoneDifference);
    7: document.write(“The time and date in Central Europe is: “ + currentDate.toLocaleString());
    8: </script> 

    31 设置日期输出格式

    1: <script. language=”JavaScript”>
    2: var thisDate = new Date();
    3: var thisTimeString = thisDate.getHours() + “:” + thisDate.getMinutes();
    4: var thisDateString = thisDate.getFullYear() + “/” + thisDate.getMonth() + “/” + thisDate.getDate();
    5: document.write(thisTimeString + “ on “ + thisDateString);
    6: </script> 

    32 读取URL参数

    1: <script. language=”JavaScript”>
    2: var urlParts = document.URL.split(“?”);
    3: var parameterParts = urlParts[1].split(“&”);
    4: for (i = 0; i < parameterParts.length; i++) { 
    5: var pairParts = parameterParts[i].split(“=”);
    6: var pairName = pairParts[0];
    7: var pairValue = pairParts[1];
    8: document.write(pairName + “ :“ +pairValue );
    9: }
    10: </script> 

    你还以为HTML是无状态的么?

    33 打开一个新的document对象

    1: <script. language=”JavaScript”>
    2: function newDocument() { 
    3: document.open();
    4: document.write(“<p>This is a New Document.</p>”);
    5: document.close();
    6: }
    7: </script> 

    34 页面跳转

    1: <script. language=”JavaScript”>
    2: window.location = “http://www.liu21st.com/”;
    3: </script> 

    35 添加网页加载进度窗口

    1: <html>
    2: <head>
    3: <script. language='javaScript'>
    4: var placeHolder = window.open('holder.html','placeholder','width=200,height=200');
    5: </script>
    6: <title>The Main Page</title>
    7: </head>
    8: <body nLoad='placeHolder.close()'>
    9: <p>This is the main page</p>
    10: </body>
    11: </html> 

    JavaScript. 3:图像 

    36 读取图像属性

    1: <img src="/”image1.jpg"” name=”myImage”>
    2: <a href=”# ” nClick=”window.alert(document.myImage.width)”>Width</a>
    3: 

    37 动态加载图像

    1: <script. language=”JavaScript”>
    2: myImage = new Image;
    3: myImage.src = “Tellers1.jpg”;
    4: </script> 

    38 简单的图像替换

    1: <script. language=”JavaScript”>
    2: rollImage = new Image;
    3: rollImage.src = “rollImage1.jpg”;
    4: defaultImage = new Image;
    5: defaultImage.src = “image1.jpg”;
    6: </script>
    7: <a href="/”myUrl"” nMouseOver=”document.myImage.src = rollImage.src;”
    8: nMouseOut=”document.myImage.src = defaultImage.src;”>
    9: <img src="/”image1.jpg"” name=”myImage” width=100 height=100 border=0> 

    39 随机显示图像

    1: <script. language=”JavaScript”>
    2: var imageList = new Array;
    3: imageList[0] = “image1.jpg”;
    4: imageList[1] = “image2.jpg”;
    5: imageList[2] = “image3.jpg”;
    6: imageList[3] = “image4.jpg”;
    7: var imageChoice = Math.floor(Math.random() * imageList.length);
    8: document.write(‘<img src=”’ + imageList[imageChoice] + ‘“>’);
    9: </script> 

    40 函数实现的图像替换

    1: <script. language=”JavaScript”>
    2: var source = 0;
    3: var replacement = 1;
    4: function createRollOver(originalImage,replacementImage) { 
    5: var imageArray = new Array;
    6: imageArray[source] = new Image;
    7: imageArray[source].src = originalImage;
    8: imageArray[replacement] = new Image;
    9: imageArray[replacement].src = replacementImage;
    10: return imageArray;
    11: }
    12: var rollImage1 = createRollOver(“image1.jpg”,”rollImage1.jpg”);
    13: </script>
    14: <a href=”#” nMouseOver=”document.myImage1.src = rollImage1[replacement].src;”
    15: nMouseOut=”document.myImage1.src = rollImage1[source].src;”>
    16: <img src="/”image1.jpg"” width=100 name=”myImage1” border=0>
    17: </a> 

    41 创建幻灯片

    1: <script. language=”JavaScript”>
    2: var imageList = new Array;
    3: imageList[0] = new Image;
    4: imageList[0].src = “image1.jpg”;
    5: imageList[1] = new Image;
    6: imageList[1].src = “image2.jpg”;
    7: imageList[2] = new Image;
    8: imageList[2].src = “image3.jpg”;
    9: imageList[3] = new Image;
    10: imageList[3].src = “image4.jpg”;
    11: function slideShow(imageNumber) { 
    12: document.slideShow.src = imageList[imageNumber].src;
    13: imageNumber += 1;
    14: if (imageNumber < imageList.length) { 
    15: window.setTimeout(“slideShow(“ + imageNumber + “)”,3000);
    16: }
    17: }
    18: </script>
    19: </head>
    20: <body nLoad=”slideShow(0)”>
    21: <img src="/”image1.jpg"” width=100 name=”slideShow”> 

    42 随机广告图片

    1: <script. language=”JavaScript”>
    2: var imageList = new Array;
    3: imageList[0] = “image1.jpg”;
    4: imageList[1] = “image2.jpg”;
    5: imageList[2] = “image3.jpg”;
    6: imageList[3] = “image4.jpg”;
    7: var urlList = new Array;
    8: urlList[0] = “http://some.host/”;
    9: urlList[1] = “http://another.host/”;
    10: urlList[2] = “http://somewhere.else/”;
    11: urlList[3] = “http://right.here/”;
    12: var imageChoice = Math.floor(Math.random() * imageList.length);
    13: document.write(‘<a href=”’ + urlList[imageChoice] + ‘“><img src=”’ + imageList[imageChoice] + ‘“></a>’);
    14: </script> 

    JavaScript. 4:表单 

    43 表单构成

    1: <form. method=”post” action=”target.html” name=”thisForm”>
    2: <input type=”text” name=”myText”>
    3: <select name=”mySelect”>
    4: <option value=”1”>First Choice</option>
    5: <option value=”2”>Second Choice</option>
    6: </select>
    7: <br>
    8: <input type=”submit” value=”Submit Me”>
    9: </form> 

    44 访问表单中的文本框内容

    1: <form. name=”myForm”>
    2: <input type=”text” name=”myText”>
    3: </form>
    4: <a href='#' nClick='window.alert(document.myForm.myText.value);'>Check Text Field</a> 

    45 动态复制文本框内容

    1: <form. name=”myForm”>
    2: Enter some Text: <input type=”text” name=”myText”><br>
    3: Copy Text: <input type=”text” name=”copyText”>
    4: </form>
    5: <a href=”#” nClick=”document.myForm.copyText.value =
    6: document.myForm.myText.value;”>Copy Text Field</a> 

    46 侦测文本框的变化

    1: <form. name=”myForm”>
    2: Enter some Text: <input type=”text” name=”myText” nChange=”alert(this.value);”>
    3: </form> 

    47 访问选中的Select

    1: <form. name=”myForm”>
    2: <select name=”mySelect”>
    3: <option value=”First Choice”>1</option>
    4: <option value=”Second Choice”>2</option>
    5: <option value=”Third Choice”>3</option>
    6: </select>
    7: </form>
    8: <a href='#' nClick='alert(document.myForm.mySelect.value);'>Check Selection List</a> 

    48 动态增加Select项

    1: <form. name=”myForm”>
    2: <select name=”mySelect”>
    3: <option value=”First Choice”>1</option>
    4: <option value=”Second Choice”>2</option>
    5: </select>
    6: </form>
    7: <script. language=”JavaScript”>
    8: document.myForm.mySelect.length++;
    9: document.myForm.mySelect.options[document.myForm.mySelect.length - 1].text = “3”;
    10: document.myForm.mySelect.options[document.myForm.mySelect.length - 1].value = “Third Choice”;
    11: </script> 

    49 验证表单字段

    1: <script. language=”JavaScript”>
    2: function checkField(field) { 
    3: if (field.value == “”) { 
    4: window.alert(“You must enter a value in the field”);
    5: field.focus();
    6: }
    7: }
    8: </script>
    9: <form. name=”myForm” action=”target.html”>
    10: Text Field: <input type=”text” name=”myField”onBlur=”checkField(this)”>
    11: <br><input type=”submit”>
    12: </form> 

    50 验证Select项

    1: function checkList(selection) { 
    2: if (selection.length == 0) { 
    3: window.alert(“You must make a selection from the list.”);
    4: return false;
    5: }
    6: return true;
    7: } 

    51 动态改变表单的action

    1: <form. name=”myForm” action=”login.html”>
    2: Username: <input type=”text” name=”username”><br>
    3: Password: <input type=”password” name=”password”><br>
    4: <input type=”button” value=”Login” nClick=”this.form.submit();”>
    5: <input type=”button” value=”Register” nClick=”this.form.action = ‘register.html’; this.form.submit();”>
    6: <input type=”button” value=”Retrieve Password” nClick=”this.form.action = ‘password.html’; this.form.submit();”>
    7: </form> 

    52 使用图像按钮

    1: <form. name=”myForm” action=”login.html”>
    2: Username: <input type=”text” name=”username”><br>
    3: Password: <input type=”password”name=”password”><br>
    4: <input type=”image” src="/”login.gif"” value=”Login”>
    5: </form>
    6: 

    53 表单数据的加密

    1: <SCRIPT. LANGUAGE='JavaScript'>
    2: <!--
    3: function encrypt(item) { 
    4: var newItem = '';
    5: for (i=0; i < item.length; i++) { 
    6: newItem += item.charCodeAt(i) + '.';
    7: }
    8: return newItem;
    9: }
    10: function encryptForm(myForm) { 
    11: for (i=0; i < myForm.elements.length; i++) { 
    12: myForm.elements[i].value = encrypt(myForm.elements[i].value);
    13: }
    14: }
    15: 
    16: //-->
    17: </SCRIPT>
    18: <form. name='myForm' nSubmit='encryptForm(this); window.alert(this.myField.value);'>
    19: Enter Some Text: <input type=text name=myField><input type=submit>
    20: </form> 

    JavaScript. 5:窗口和框架 

    54 改变浏览器状态栏文字提示

    1: <script. language=”JavaScript”>
    2: window.status = “A new status message”;
    3: </script> 

    55 弹出确认提示框

    1: <script. language=”JavaScript”>
    2: var userChoice = window.confirm(“Click OK or Cancel”);
    3: if (userChoice) { 
    4: document.write(“You chose OK”);
    5: } else { 
    6: document.write(“You chose Cancel”);
    7: }
    8: </script> 

    56 提示输入

    1: <script. language=”JavaScript”>
    2: var userName = window.prompt(“Please Enter Your Name”,”Enter Your Name Here”);
    3: document.write(“Your Name is “ + userName);
    4: </script> 

    57 打开一个新窗口

    1: //打开一个名称为myNewWindow的浏览器新窗口
    2: <script. language=”JavaScript”>
    3: window.open(“http://www.liu21st.com/”,”myNewWindow”);
    4: </script> 

    58 设置新窗口的大小

    1: <script. language=”JavaScript”>
    2: window.open(“http://www.liu21st.com/”,”myNewWindow”,'height=300,width=300');
    3: </script> 

    59 设置新窗口的位置

    1: <script. language=”JavaScript”>
    2: window.open(“http://www.liu21st.com/”,”myNewWindow”,'height=300,width=300,left=200,screenX=200,top=100,screenY=100');
    3: </script> 

    60 是否显示工具栏和滚动栏

    1: <script. language=”JavaScript”>
    2: window.open(“http: 

    61 是否可以缩放新窗口的大小

    1: <script. language=”JavaScript”>
    2: window.open('http://www.liu21st.com/' , 'myNewWindow', 'resizable=yes' );</script> 

    62 加载一个新的文档到当前窗口

    1: <a href='#' nClick='document.location = '125a.html';' >Open New Document</a> 

    63 设置页面的滚动位置

    1: <script. language=”JavaScript”>
    2: if (document.all) { //如果是IE浏览器则使用scrollTop属性
    3: document.body.scrollTop = 200;
    4: } else { //如果是NetScape浏览器则使用pageYOffset属性
    5: window.pageYOffset = 200;
    6: }</script> 

    64 在IE中打开全屏窗口

    1: <a href='#' nClick=”window.open('http://www.juxta.com/','newWindow','fullScreen=yes');”>Open a full-screen window</a> 

    65 新窗口和父窗口的操作

    1: <script. language=”JavaScript”>
    2: //定义新窗口
    3: var newWindow = window.open(“128a.html”,”newWindow”);
    4: newWindow.close(); //在父窗口中关闭打开的新窗口
    5: </script>
    6: 在新窗口中关闭父窗口
    7: window.opener.close() 

    66 往新窗口中写内容

    1: <script. language=”JavaScript”>
    2: var newWindow = window.open(“”,”newWindow”);
    3: newWindow.document.open();
    4: newWindow.document.write(“This is a new window”);
    5: newWIndow.document.close();
    6: </script> 

    67 加载页面到框架页面

    1: <frameset cols=”50%,*”>
    2: <frame. name=”frame1” src="/”135a.html"”>
    3: <frame. name=”frame2” src="/”about:blank"”>
    4: </frameset>
    5: 在frame1中加载frame2中的页面
    6: parent.frame2.document.location = “135b.html”; 

    68 在框架页面之间共享脚本
    如果在frame1中html文件中有个脚本

    1: function doAlert() { 
    2: window.alert(“Frame. 1 is loaded”);
    3: } 

    那么在frame2中可以如此调用该方法

    1: <body nLoad=”parent.frame1.doAlert();”>
    2: This is frame. 2.
    3: </body> 

    69 数据公用
    可以在框架页面定义数据项,使得该数据可以被多个框架中的页面公用

    1: <script. language=”JavaScript”>
    2: var persistentVariable = “This is a persistent value”;
    3: </script>
    4: <frameset cols=”50%,*”>
    5: <frame. name=”frame1” src="/”138a.html"”>
    6: <frame. name=”frame2” src="/”138b.html"”>
    7: </frameset> 

    这样在frame1和frame2中都可以使用变量persistentVariable 
    70 框架代码库
    根据以上的一些思路,我们可以使用一个隐藏的框架页面来作为整个框架集的代码库

    1: <frameset cols=”0,50%,*”>
    2: <frame. name=”codeFrame” src="/”140code.html"”>
    3: <frame. name=”frame1” src="/”140a.html"”>
    4: <frame. name=”frame2” src="/”140b.html"”>
    5: </frameset>

  • 对测试工作进行度量

    2010-01-21 09:49:11

    测试工作的度量一直是测试管理的一个难点,我们如何衡量测试工作的质量呢?

    一般来说,衡量测试工作成效的KPI参数有如下几个:

    1.  工作时长

    2.  测试设计,测试用例数(自动化脚本代码行数)

    3.  发现故障数

    4.  输出的测试文档数(典型故障分析、测试报告、发布说明、系统使用说明等)

    5.  泄漏故障数

    6.  产品版本测试收敛度

    各部分的KPI比重如何分配?

    从测试工作的目的来看,首先必须要对测试通过的产品质量进行保证,而下游客户是产品质量的最终检验方,所以测试泄漏故障数和故障严重程度应该作为测试工作成效的首要度量KPI。

    其次,测试工作的主要目的是发现产品的故障,所以发现故障数应该作为第二KPI进行度量

    但是不同测试人员承担的测试任务不同,不同模块的故障分布也会不同,所以该KPI还应该和故障严重程度、所属模块的故障出现频度等进行综合考量

    第三主要的KPI应该测试收敛程度。

    任何版本的产品周期都是有限制的,留给系统测试的时间有限,故障如果不能尽快收敛,对产品的正常发布就会造成严重影响,所以必须要求重点功能优先测试,故障及早收敛。

    第四,测试设计

    测试用例是否充分决定产品测试过程中是否能够覆盖完全。所以测试用例数也是一个重要的KPI

    不过,完全通过数目衡量也不合理,测试用例的质量、用例细致程度等也需要有在度量时有一定的体现方式

    工作时长和总结、输出等工作量上的指标可作为辅助参考KPI指标。

  • 利用JMeter进行压力测试

    2010-01-13 17:10:40

    压力测试以软件响应速度为测试目标,尤其是在较短时间内大量并发用户的同时访问时,软件的性能和抗压能力。

      JMeter是一款开源的压力测试工具,目前最新Release版本是2.3.4,它不仅可以测试Web服务器,还可以测试数据库、JMS、Web Service、LDAP、JUNIT 等多种对象的测试能力。下载地址:http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi

      下面简单介绍一下JMeter。

      测试计划是测试的起点,其他所有组件的容器。

      线程组是用来模拟用户并发的组件。JMeter的每个任务都是用线程来处理的。线程组主要有三个属性,线程数、Ramp-up Period和循环次数。线程数就是并发的数量,Ramp-up Period表示在多长时间内创建线程数中定义的所有线程。

      逻辑控制器可以组织取样器,做出复杂的测试用的请求。

      配置元件中主要配置取样器中所需要的配置。

      定时器设置请求间的时间间隔。

      前置处理器一般用来修改请求(Request)。

      Sampler(取样器),主要的执行组件。每一个取样器都可以被监听器监听,并生成测试结果。

      后置处理器一般用来出来返回的数据(Response)。

      断言,判断取样器是否正常工作。

      监听器,收集整理测试结果,并可以指定格式生成XML、CSV等形式的文件。

      工作台中可以添加非测试元件,其中一个最重要的就是HTTP代理服务器。

      HTTP代理服务器可以用来录制测试脚本。将浏览器的代理服务器设置为127.0.0.1:8080,然后启动JMeter的HTTP代理服务器,就可以录制在浏览器中进行的操作。HTTP代理服务器可以设置包含模式和排除模式,我一般用排除模式来排除一些CSS、JS、GIF、PNG之类的。

      JMeter的基本元件就是这样,这些元件具体怎么运用请继续看下文。

211/212>
Open Toolbar