发布新日志

  • 如何学习一个新的系统

    2013-03-28 21:29:12

    不管是换工作,新项目,或者公司内部换项目都面临着如何上手的问题,如何快速的学习,进入角色是每一个测试人员的挑战。个人觉得可以从几个方面入手:
    1. 从自身角度谈
    a. 了解整个项目的流程,主要是包括有几个主要的milestone,每个milestone是不是有交付的标准和交付文档
    b. 学习a中提到的文档,不需要太仔细,只有知道大概的内容,比如某个文档用来做什么用,包含哪些东西,这要以后如果遇到什么问题的时候,可以有个大方向,知道从哪里入手。个人感觉文档是入门的开始,一定要先阅读一定量的项目文档
    c. 阅读之前的文档,包括测试用例,操作指南以及设计文档,这样对系统大体有个了解;注意一定要动手实验,同时记录下遇到的问题
    d.阅读或者了解应用的数据库结构,包括配置表,交易相关的表;了解数据库会对了解这个系统有很大的帮助,同时你了解不同配置数据的同时,你也在学习系统可能的业务;
    e. 动手实验,结合文档和数据库结构,进行实际操作,同时查看业务数据在数据库中是如何存储和变化的,这个过程中,大概可以写出系统的大模块,以及模块和模块间传递的什么数据, 同时也可以动手写一些之后测试可能会用到的查询sql或者制造数据的sql或者存储过程
    f. 如果系统中有很多异步处理,去了解常用的异步过程,包括信息是如何触发,如何提供,如何消费的
    g.查找一些以前的bug来看看,这样有助于提高测试这个项目的感觉
    坚持2-3个月,对于系统的认识就一定有很大提高。
    2. 请教他人
    a.项目中不一定每个人都时间帮你解决问题,所以提出问题的时候要先想好问题,需要什么,得到回答之后在仔细思考一下,看看能不能解决更多的问题,或者再思考一下,之前的理解是不是正确;有些思路可能是这个项目特有的同时会应用在项目的不同地方,所以思考一下有助与解决相似的问题
    b.关于业务知识可以想产品经理和业务人员多请教,同时去了解他们的新需求以及提出这些需求的逻辑,了解用户的出发点要比只了解需求好,因为出发点才是最本质的东西,需求不一定就一定很到解决了这个出发点
    c.请教其他测试人员,项目的难点是什么,这样自己的学习就以此为重点
    d.如果有新工具,可以请教老手从哪里入手
    e.请教项目中用到的工具如何使用,以及使用的目的
    f.报bug需要注意的地方

    以上是自己能想到的一些快速进入新项目自己总结的一些方法。不过无论如何过往的经验以及一些基础性知识需要好好总结和打扎实,这些对于快速学习新项目非常有用。比如数据库,想不出还有不用数据库的应用了;如果测试财务相关,会计基础基本上在哪个系统都是一样的。


  • Ant Sample -- 代码确实是文档

    2012-06-02 20:33:02

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="sample" default="makejar">
        
        <!-- Another Tool -->
        <!--
            project
                工程,运行一次
            target
                在这一次之中,到底都要干什么
                多个target,用来维护互相之间的顺序。depends
                    画一张甘特图,要做箭头的事,先做箭尾的事
                    init2->init1->【init3】->init4
                    要看工程从哪个target开始
                好处在于,写target的顺序,和运行的顺序无关
            property
                键值对
                用来维护多个target共同的东西
        -->
       
        <!--
            要做不同的事,在target里写不同的子元素
        -->
       
        <property name="dlist" value="f:\38\dlist" />
        <property name="project" value="."/>
       
        <target name="clean">
            <delete dir="${dlist}"/>
        </target>
       
        <target name="init" depends="clean">
            <mkdir dir="${dlist}\classes"/>
            <mkdir dir="${dlist}\xml"/>
            <mkdir dir="${dlist}\html"/>
        </target>
       
        <!--
            1、拷到哪儿
            2、从哪儿拷
            3、拷贝的黑白名单
        -->
        <target name="copy" depends="init">
            <copy todir="${dlist}\classes">
                <fileset dir="${project}\src">
                    <exclude name="**/*.java"/>
                </fileset>
            </copy>
        </target>
       
        <!--
            指定编译或者运行的classpath
            1、jar包如何指定
            2、类文件夹如何指定
        -->
        <path id="project.classpath">
            <!--
                jar包
            -->
            <fileset dir="${project}\lib">
                <include name="**/*.jar"/>
            </fileset>
            <!--
                类文件夹
            -->
            <pathelement path="${dlist}\classes"/>
        </path>

       
        <!--
            1、编译哪些
            2、编译之后放哪儿
            3、有没有编译路径
                默认的编译路径,只有jdk下面的那些
        -->
        <target name="javac" depends="copy">
            <javac srcdir="${project}\src" destdir="${dlist}\classes">
                <classpath refid="project.classpath"/>
            </javac>
        </target>
       
        <!--
            1、要运行哪个类
            2、要依赖哪个classpath
                一定要注意,编译之后的类要在这个classpath里
            3、是否需要给main方法的args传参
        -->
        <target name="java" depends="javac">
            <java classname="cn.javass.MyLogger" classpathref="project.classpath">
                <arg value="xyz"/>
            </java>
        </target>
       
        <target name="test" depends="java">
            <!--
                运行junit测试
                1、junit的类在哪儿
                2、运行的classpath依赖谁
                3、生成的结果交给谁
                4、哪些类算测试类
            -->
            <junit dir="${dlist}\classes" failureProperty="test.failed">
                <classpath refid="project.classpath" />
                <formatter type="xml" />
                <batchtest fork="true" todir="${dlist}\xml" unless="testcase">
                    <fileset dir="${project}\src">
                        <include name="**/*Test.java" />
                    </fileset>
                </batchtest>
            </junit>
            <!--
                从上一个的运行结果生成报告
                1、结果在哪里
                2、谁算结果
                3、生成的html到底放在哪里
            -->
            <junitreport todir="${dlist}\xml">
                <fileset dir="${dlist}\xml">
                    <include name="TEST-*.xml" />
                </fileset>
                <report format="frames" todir="${dlist}\html" />
            </junitreport>
        </target>
        <!--
            1、从哪儿开始打
            2、打的jar包放到哪儿
        -->
        <target name="makejar" depends="test">
            <jar basedir="${dlist}\classes" destfile="${dlist}\temp.jar"/>
        </target>
       
    </project>
     
  • Maven 基础

    2012-05-19 19:41:59

    Maven Study:
    1.项目对象模型(Project Object Model)

    2.坐标(Coordinates),
    3.项目生命周期(ProjectLifecycle),
    4.插件(plugin)和目标(goal),
    5.依赖管理系统(Dependency Management System),
    6.仓库管理(Repositories)

    mvn clean test
    mvn clean package
    mvn clean install
    mvn是命令名:
    clean说明要清空所有的配置文件
    test说明要运行单元测试
    package说明要打包
    install安装到本地仓库
    坐标:
    groupId:定义当前Maven项目隶属的实际项目。groupId的表示方式与java
    包名的表示方式类似,通常与域名反向一一对应。
    artifactId:该元素定义实际项目中的一个Maven项目/模块。
    version:版本【可以分成稳定版本和快照版本】。
    packaging:打包方式。如:jar、war。
    classifier:不能直接定义,用来表示构件到底用于何种jdk版本。
    生命周期:
    Maven的生命周期就是为了所有的构建过程进行抽象和统一。这个生命周期
    包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点
    生成等几乎所有构建步骤。
    Maven拥有三套相互独立的生命周期,他们分别为clean、default和site。
    clean生命周期的目的是清理项目,default生命周期的目的是构建项目,而site
    生命周期的目的是建立项目站点

    clean生命周期包含三个阶段:
    pre-clean、clean、post-clean

    default生命周期包含很多阶段:
    validate、initialize、generate-sources、process-sources、
    generate-resources、process-resources、compile、process-classes、
    generate-test-sources、process-test-sources、generate-test-resources、
    process-test-resources、test-compile、process-test-classes、test、
    prepare-package、package、pre-intergration-test、integration-test、
    post-integeration-test、verify、install、deploy

    site生命周期包含四个阶段:
    pre-site、site、post-site、site-deploy


  • Xpath basic

    2012-05-14 04:28:08

    Sample XML:
    <?xml version="1.0" encoding="ISO-8859-1"?>

    <bookstore>

    <book>
      <title lang="eng">Harry Potter</title>
      <price>29.99</price>
    </book>

    <book>
      <title lang="eng">Learning XML</title>
      <price>39.95</price>
    </book>

    </bookstore>

    Xpath basic:
    <bookstore> (文档节点)
    <author>J K. Rowling</author> (元素节点)
    lang="en" (属性节点)
    节点关系: Parent,Child,Sibling,Ancestor,Descendant

    Xpath expression:

    nodename     选取此节点的所有子节点。
    /             从根节点选取。
    //             从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    .             选取当前节点。
    ..             选取当前节点的父节点。
    @             选取属性。

    路径表达式     结果
    bookstore     选取 bookstore 元素的所有子节点。
    /bookstore     选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
    bookstore/book     选取属于 bookstore 的子元素的所有 book 元素。
    //book     选取所有 book 子元素,而不管它们在文档中的位置。
    bookstore//book     选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
    //@lang     选取名为 lang 的所有属性。

    路径表达式     结果
    /bookstore/book[1]     选取属于 bookstore 子元素的第一个 book 元素。
    /bookstore/book[last()]     选取属于 bookstore 子元素的最后一个 book 元素。
    /bookstore/book[last()-1]     选取属于 bookstore 子元素的倒数第二个 book 元素。
    /bookstore/book[position()<3]     选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
    //title[@lang]     选取所有拥有名为 lang 的属性的 title 元素。
    //title[@lang='eng']     选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
    /bookstore/book[price>35.00]     选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
    /bookstore/book[price>35.00]/title     选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

    选取未知节点
    XPath 通配符可用来选取未知的 XML 元素。
    通配符     描述
    *         匹配任何元素节点。
    @*         匹配任何属性节点。
    node()     匹配任何类型的节点。
    实例
    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
    路径表达式         结果
    /bookstore/*     选取 bookstore 元素的所有子元素。
    //*             选取文档中的所有元素。
    //title[@*]     选取所有带有属性的 title 元素。

    选取若干路径
    通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
    实例
    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
    路径表达式                         结果
    //book/title | //book/price     选取 book 元素的所有 title 和 price 元素。
    //title | //price                 选取文档中的所有 title 和 price 元素。
    /bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

    XPath 轴

    轴可定义相对于当前节点的节点集。
    轴名称         结果
    ancestor     选取当前节点的所有先辈(父、祖父等)。
    ancestor-or-self     选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
    attribute     选取当前节点的所有属性。
    child     选取当前节点的所有子元素。
    descendant     选取当前节点的所有后代元素(子、孙等)。
    descendant-or-self     选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
    following     选取文档中当前节点的结束标签之后的所有节点。
    namespace     选取当前节点的所有命名空间节点。
    parent     选取当前节点的父节点。
    preceding     选取文档中当前节点的开始标签之前的所有节点。
    preceding-sibling     选取当前节点之前的所有同级节点。
    self     选取当前节点。

    步的语法:

    轴名称::节点测试[谓语]

    实例
    例子     结果
    child::book     选取所有属于当前节点的子元素的 book 节点。
    attribute::lang     选取当前节点的 lang 属性。
    child::*     选取当前节点的所有子元素。
    attribute::*     选取当前节点的所有属性。
    child::text()     选取当前节点的所有文本子节点。
    child::node()     选取当前节点的所有子节点。
    descendant::book     选取当前节点的所有 book 后代。
    ancestor::book     选择当前节点的所有 book 先辈。
    ancestor-or-self::book     选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
    child::*/child::price     选取当前节点的所有 price 孙节点。
  • Oracle 基础-1-基本数据类型 -- DML DDL 常用函数 事务概念

    2012-05-12 23:14:02

    1.Oracle基本数据类型
    char -- char(4) -- 不足位数空格补
    varchar2 -- varchar(4) 不足位数不补空格
    number(p,s)  -- p 总长度,s 小数位数
    date -- 一个7字节的定宽日期/时间数据类型。其中总包含7个属性,包括:世
    纪、世纪中哪一年、月份、月中的哪一天、小时、分钟和秒。
    timestamp --一个7 字节或12.字节的定宽日期/时间数据类型。它与DATE 数
    据类型不同,因为TIMESTAMP 可以包含小数秒(fractional second);带小数
    秒的TIMESTAMP 在小数点右边最多可以保留9位。
    BLOB:不包含字符转换信息,(4GB)×(数据库块大小)字节的数据
    CLOB: 字符转换信息 (4GB)×(数据库块大小)字节的数据
    2.DML:
    CREATE TABLE 创建表(主键、外键、约束、级联)
    DROP TABLE 删除表
    ALTER TABLE 修改表
    CREATE VIEW 创建视图
    DROP VIEW 删除视图
    CREATE INDEX 创建索引
    DROP INDEX 删除索引
    CREATE SEQUENCE 创建序列
    。。。。。。。。
    3.DQL及常用Oracle函数
    select
    SELECT 查询字段
    FROM 表
    [ WHERE 查询条件]
    [ GROUP BY 分组字段]
    [ HAVING 分组条件]
    [ ORDER BY 排序字段[ ASC | DESC ] ]
    ASC 升序,默认; DESC 降序

    4. DDL:INSERT、UPDATE、DELETE Truncate
    Insert(新增数据)
    语法
    insert into 表名( 列名(,列名)* )* values ( 值( ,值)* );
    1、新增整行insert into 表名values ( 值( ,值)* );
    insert into TBL_STUDENT values(1,’name’,1,’1’);
    注:[所有值必须和列定义位置一一对应]
    2、新增行的一部分insert into 表名( 列名(,列名)* )* values ( 值( ,值)* );
    insert into TBL_STUDENT(snum,sname,age) values(1,’name’,1);
    3、新增某些查询的结果insert into 新表名(查询);
    insert into TBL_STUDENT (select * from TBL_STUDENT);
    4、从一个表复制到另一个表
    create table tbl_student3 as select * from tbl_student;

    Update(更新数据)
    语法:Update 表名set 列名=值(,列名=值)* (where 条件)*
    1、更新表中特定行
    update tbl_student set age=2,sex=‘0’ where snum=1;
    2、更新表中所有行:初始化时可能用用
    Update tbl_student set age=2,sex=‘0’;

    Delete(删除数据)
    语法:Delete from 表名(where 条件)*
    1、从表中删除特定行数据
    Delete from tbl_student where snum=1;
    2、从表中删除所有行
    Delete from tbl_student;
    3、截断,更快的从表中删除所有行-不保留日志,1、不能回滚;2、快
    Truncate table TBL_Student;

    Oracle 运算符:
    比较运算符:=、<、<=、>、>= 、!=、^=、<>
    算数运算符:+、-、*、/、%
    范围:between...and、not between....and
    逻辑运算符:and、or、not
    字符串匹配运算符:like、not like
    字符串连接运算符: ||
    空运算符:is null、is not null
    包含运算符:in、not in;exists、not exists
    集合操作符:union、union all、intersect、minus

    Oracle 数据处理函数
    1、CHR(intValue) 返回等价数值的字符ASCII(charater) 返回等价字符的数值
    2、LENGTH(str)字符串长度
    3、CONCAT(str1,str2)字符串连接
    4、INITCAP(str)返回字符串的每个单词的第一个字母大写,而其他字母小写。
    5、LOWER(str) 把字符串str转换为小写UPPER(str)把字符串str转换为小写
    6、LTRIM(str1,trimCharater)从str左边开始去掉出现在trimCharater的中任何前导字符集。
    7、RTRIM(str1,trimCharater)从str右边边开始去掉出现在trimCharater的中任何前导字符集。
    8、LPAD(str, length, padStr)在字符串str左边添加字符串padStr直到str字符串的长度等于length
    9、RPAD(str, length, padStr)在字符串str右边添加字符串padStr直到str字符串的长度等于length
    10、SUBSTR(str, fromIndex, length)返回字符串str中从fromIndex位置开始的length个字符
    11、INSTR(str,searchStr,fromIndex, count)在str中从位置fromIndex开始查找searchStr在str中出
    12、to_number(str) 将str转换为数字

    Oracle 数字处理函数
    1、ABS(x) x的绝对值
    2、CEIL(x) 大于或等于x的最小整数值FLOOR(x)小于或等于x的最大整数值
    3、MOD(x, y) 求余,返回x除以y的余数。
    4、POWER(x,y)计算x的y次幂
    5、ROUND(x, y)计算保留到小数点右边y位的x值。会四舍五入
    6、TRUNC(x,y)计算保留到小数点右边y位的x值。会四舍五入
    7、LOG(x,y)、SIN(x)、COS(x)、TAN(x)、EXP(x)、LN(x)……
    第count次的位置,fromIndex可以为负(此时,从str的尾部开始)。

    Oracle 聚合函数
    1、avg(列名) 返回某列的平均值
    2、count(列名) 返回某列的行数
    3、max(列名) 返回某列的最大值
    4、min(列名) 返回某列的最小值
    5、sum(列名) 返回某列值的总和

    子查询:any,same,all  用法
    Join:左连接,右连接,内连接
    nvl,bvl2,decode,case
    rownum,rowid

    事务特性(ACID)
    1.原子性 Atomicity,全做-不做
    2.一致性 Consistency 不破坏数据约束
    3.隔离性 Isolation 并发操作,不相互影响
    4.持久性 Durability 操作成功,数据永久改变,不因为突发事件而造成数据不一致和丢失
    事务处理
    事务(transaction):一组SQL语句;
    回滚(rollback) :撤销指定SQL语句的过程;
    提交(commit) :执行指定SQL语句;
    保留点(savepoint):事务处理中设置的临时占位符,可以对保留点执行回滚

  • 数据库3个范式

    2012-05-12 22:08:10

    数据库范式
    1.第一范式(1NF)无重复的列
      一个表里面没有重复的列,每一列表示一个特定的属性
     2.第二范式(2NF)属性完全依赖于主键 [ 消除部分子函数依赖 ]
      一个表中的每一个列表示一个唯一的实体。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性
      假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分),关键字为组合关键字(学号, 课程名称),因为存在如下决定关系:
    (学号, 课程名称) → (姓名, 年龄, 成绩, 学分)
    这个数据库表不满足第二范式,因为存在如下决定关系:
    (学号) → (姓名, 年龄)
    即存在组合关键字中的字段决定非关键字的情况。
    由于不符合2NF,这个选课关系表会存在如下问题:
    (1) 数据冗余:
    同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
    (2) 更新异常:
    若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
    (3) 插入异常:
    假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
    (4) 删除异常:
    假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
    把选课关系表SelectCourse改为如下三个表:
    学生:Student(学号, 姓名, 年龄);
    课程:Course(课程名称, 学分);
    选课关系:SelectCourse(学号, 课程名称, 成绩)。
    这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。
    另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
    3.第三范式(3NF)属性不依赖于其它非主属性 [ 消除传递依赖 ]
    第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。简而言之,第三范式就是属性不依赖于其它非主属性。
    所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。
    因此,满足第三范式的数据库表应该不存在如下依赖关系:
    关键字段 → 非关键字段x → 非关键字段y
    假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
    (学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
    这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
    (学号) → (所在学院) → (学院地点, 学院电话)
    即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
    它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
    把学生关系表分为如下两个表:
    学生:(学号, 姓名, 年龄, 所在学院);
    学院:(学院, 地点, 电话)。
    这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
    4. 鲍依斯-科得范式(BCNF是3NF的改进形式)
    若关系模式R是第一范式,且每个属性都不传递依赖于R的候选键。这种关系模式就是BCNF模式。即在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合鲍依斯-科得范式。
    (仓库ID, 存储物品ID) →(管理员ID, 数量)
    (管理员ID, 存储物品ID) → (仓库ID, 数量)
    所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
    (仓库ID) → (管理员ID)
    (管理员ID) → (仓库ID)
    即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
    (1) 删除异常:
    当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
    (2) 插入异常:
    当仓库没有存储任何物品时,无法给仓库分配管理员。
    (3) 更新异常:
    如果仓库换了管理员,则表中所有行的管理员ID都要修改。
    把仓库管理关系表分解为二个关系表:
    仓库管理:StorehouseManage(仓库ID, 管理员ID);
    仓库:Storehouse(仓库ID, 存储物品ID, 数量)。
    这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
  • Java 变量访问

    2012-05-12 17:13:16

    成员变量或方法的访问权限是用访问权限修饰符来指定的。Java的访问权限修饰符包括四种显示方式修饰符和一种隐含方式修饰符,即:
    1. 公用变量
    用public说明的变量是公有变量。
    访问权限:允许任何包中的任何类的变量访问。
    例如:下面的代码中,在类Alpha中说明了一个公用变量i_public,而在另一个类Beta
    中可以访问该变量。
    class Alpha{public int i_public ; //说明公用变量i_public
    }
    class Beta{
    void accessmethod()
    {
    Alpha a= new Alpha();
    a.i_public=10; //访问公用变量i_public
    }
    }
    2. 私有变量
    用private说明的变量是私有变量。
    访问权限:只能被定义它的类的变量访问。
    例如:下面的代码中,在类Alpha中说明了一个私有变量i_private,其他类不允许访问。
    正确的访问格式:
    class Alpha{
    public int i_private ; //说明私有变量i_private
    void accessmethod()
    {
    Alpha a= new Alpha();
    a.i_private=10; //访问私有变量i_private
    }
    }
    3. 保护变量
    用protected说明的变量是保护变量。
    访问权限:允许类自身、子类以及在同一个包中的所有类的变量访问。
    例如:假定某个包Geek中含有两个成员类Alpha和Beta,若在类Alpha中说明了一个保护变量i_protected,则在另外一个类Beta中可以访问该变量。
    class Alpha{
    public int i_protected; //说明保护变量i_protected
    void accessmethod()
    }
    class Beta
    {
    void accessmethod()
    {
    Alpha a= new Alpha();
    a.i_protected=10; //访问保护变量i_protected
    }
    }
    4. 私有保护变量
    用private protected说明的变量是私有保护变量。
    访问权限:允许类自身以及它的子类变量访问。
    例如:下面的两种访问方式是可行的。(1) 在类中访问私有保护变量
    例如:
    class Alpha{
    private protected int i_pri_prot ;
    void accessmethod()
    {
    Alpha a= new Alpha();
    a. i_pri_prot =10; //访问私有保护变量i_pri_prot
    }
    }
    (2) 在子类中访问私有保护变量
    例如:
    class Alpha{
    private protected int i_pri_prot=10 ;
    }
    class Beta extends Alpha
    {
    void accessmethod()
    {
    Alpha a= new Alpha();
    a. i_pri_prot =30; //访问私有保护变量i_pri_prot
    }
    }
    在程序执行时,变量i_pri_prot的值是30,而不是10;
    5. 友好变量
    如果一个变量没有显示地设置访问权限,则该变量为友好变量。
    访问权限:允许类自身以及在同一个包中地所有类地变量访问。
    例如:下面的类中定义了一个友好变量:
    class Alpha{
    int i_friendly ;
    void accessmethod()
    {
    Alpha a= new Alpha();
    a. i_friendly =10; //访问友好变量i_friendly
    }
    }
    在了解了成员变量的访问权限之后,那么在说明每一个成员变量时,都可以按访问权限给变量提供适当的保护措施,这样就加强了变量的安全性。

  • QTP中如何使用类

    2012-04-15 19:35:55

    QTP中如何使用类

    VBScript中也有类的概念,所以QTP也可以使用类。类有initializeterminate,同时也属性和方法。

    下例是说明类的生命周期的代码:
    Class TestClass

       Private Sub Class_Initialize   ' Setup Initialize event.

          MsgBox("TestClass started")

       End Sub

       Private Sub Class_Terminate   ' Setup Terminate event.

          MsgBox("TestClass terminated")

       End Sub

    End Class

     

    Set X = New TestClass    

    Set X = Nothing  

    运行这段代码,就可以很好的了解类生命周期,Class_Initialize/ Class_Terminate都是事件(event).

    同时Class还有Property Get/Property Set/Property Let,那么三者的区别是什么呢?

    Property Get :返回属性的值

    Property Set :设置属性的值

    Property Let :设置对象的值

  • 要做什么样的软件测试

    2012-04-15 19:08:38

    工作很多年了,最近老是想一个问题,要做怎么样的一个软件测试人员?
    我一开始的答案是:
    1.熟悉某个行业,是某个行业的业务专家,这样做测试就不怕业务人员了
    2.了解基本的开发框架,看得懂代码,熟练1-2种自动化测试工具(QTP/Selenium),这样也不容易被开发人员忽悠(实际上构建一套自动化测试方案基本上就是开发一个产品,同样非常不容易)
    3.会性能测试,了解性能指标的意义(我不是个性能测试人员)
    4.安全测试,一定要去了解并且学习安全测试,这个在不久的将来可能是个热点

    然后仔细想想,这些够了吗?这些就可以把我一个工作了好多年的软件测试一下子就可以和工作1-2年或者刚毕业的区分开了吗? 

    或许我还要熟悉:
    1.如何定量的分析代码,产品的质量(单元测试覆盖率,测试用例覆盖率。。。。。。),尽管有了定量分析,也许不能说明什么,但是没有定量更加的虚幻
    2.是不是可以构建一套测试管理和自动化测试结合的系统
    3.如何做持续集成,如何做配置管理

    想到这些,我无语了。想到一句电影台词,人生总是这么苦吗?还是只有童年。改变一下,人生总是这么苦吗,还是只有做测试好多年之后?

    测试不是一个简单活,外延太丰富,但是既然上了这条路,就默默走下去知道测试这个职位的消亡(我预测独立的软件测试有一天是不会存在的)
  • Ruby 编写自己的迭代器

    2011-01-23 19:44:32

    def factorial (count, &block)
      value=1
      1.upto(count) do |i|
        value =value*i
        block.call(i,value)
      end
    end
    factorial(5) do |i,sum|
      puts "factorial(#{i})=#{sum}"
    end

    输出:
    factorial(1)=1
    factorial(2)=2
    factorial(3)=6
    factorial(4)=24
    factorial(5)=120

    所以其实这面,i,valu传给i,sum

    # store the input block
    class MathFact
      def initialize(&block)
        @block=block
      end
      def factorial(max)
        value=1
        1.upto(max) do |i|
          value=value*i
          @block.call(value)
        end
      end
    end
    the_value =MathFact.new do |count|
      puts "Current value is #{count}"
    end
    the_value.factorial(5)
    输出结果是什么?
  • Ruby -- 小结1

    2010-12-12 16:40:09

    A.对于Ruby来说任何可操作的东西都是对象,里面有:
    1.string:“hello world!”
    2.字面量(literal):123,1.4e4,1.0,99.40
    3.数组:
    [1, 2, 3],[1, "string", 2, ["nested", "array"]]
    4.hash表:{"key"=>"value", "key2"=>"value2", "key3"=>"value3"}

    B.方法调用:
    "hello world!".upcase(),"hello world!".upcase().downcase();
    例子:
    p("helloworld")
    p("helloworld".upcase())
    p("helloworld".downcase())
    对于常量的,一般是以大些字母开头的,重新给常量赋值,会得到警告信息:
    Const="hello world"
    p(Const)
    Const=3.4
    p(Const)
    运行上面例子,会得到一个警告信息,但不是错误

    C.类
    Class C
      def myupcase( str )
        return str.upcase()
      end
    end
    p(C.new().myupcase("content"))

    Self:
    class C
    def get_self()
    return self
    end
    end

    c = C.new()
    p(c) # #<C:0x40274e44>
    p(c.get_self()) # #<C:0x40274e44>

    通过self 调用方法:
    class C
    def my_p( obj )
    self.real_my_p(obj) # 通过自身调用方法
    end

    def real_my_p( obj )
    p(obj)
    end
    end

    C.new().my_p(1) # 显示1
    省略self的调用:
    class C
    def my_p( obj )
    real_my_p(obj) # 可以不指定调用的接收者
    end

    def real_my_p( obj )
    p(obj)
    end
    end

    C.new().my_p(1) # 显示1
    初始化类(initialize)
    class C
      def initialize()
        @i = "ok"
      end
      def get_i()
        return @i
      end
    end
    c = C.new()
    p(c.get_i())   # 显示"ok"

    继承
    class C
    def hello()
    return "hello"
    end
    end

    class Sub < C
    end

    sub = Sub.new()
    p(sub.hello()) # 显示"hello"
    Override:
    class C
    def hello()
    return "Hello"
    end
    end

    class Sub < C
    def hello()
    return "Hello from Sub"
    end
    end

    p(Sub.new().hello()) # 显示"Hello from Sub"
    p(C.new().hello()) # 显示"Hello"




  • 什么样的项目适合QTP?

    2010-10-24 14:13:04

    看到51testing 19期上面关于什么样的项目适合自动化测试,感觉非常好。很同意一个生命周期长的项目或者产品这个决定了自动化测试的回报率,但是是不是除此之外就没有适合自动化测试的了呢?个人觉得,也未必,如果一个短期的项目中有很多测试点都是通过同样的操作,来达到计算数值是不是超过每个临界点的,倒是可以直接通过录制回放,然后将测试数据参数化的方式来测试,并不需要搭建什么自动化测试框架这样的东西。
  • 做什么的自动化测试

    2010-08-29 23:36:40

    马上就要做自动化测试了,由于以前完全没有做过这方面的东西,所以没有想好要怎么做。先说说要做什么样的东西:

    1.工具 QTP

    2.尽可能的减少由于界面变化而造成自动化脚本的变化

    3.测试用例和脚本分离,最好规定好测试用例的格式之后可以直接转化为自动化脚本

    4.测试用例没有依赖性,可以在任意时间跑任意脚本

     

    实现自动化脚本的过程,希望是完成一部分就可以运用到项目中运行。希望可以半年时间完成。

  • 面试总结

    2010-08-10 21:41:33

    接二连三面试了几家公司,都是以失败告终,总结总结经验:

    1,你的特点是什么?是手工测试呢还是自动化测试?是流程很熟练呢还是其他?我自己不是一个很有特点的人,更多的是就事论事的解决问题的能力,以及肯干的精神。但是,现在对于测试的要求越来越高,需要了解代码,需要能写代码,能写代码将是一个很有特点的事情,接下来的问题就是,如何表达你能够写代码?我的总结是基本功,比如数据库至少能够说清楚左连接,右连接,什么是index,什么是transaction,会写代码,如果这些基本元素都不能表达清楚的话,那么,你能让人相信你会写代码吗?基本功,是必须要提高和打扎实的

    2,表达能力,一定要有条理的,有思路的,结构性的解释你做的工作,怎么来做好表达,我觉得方法应该是一定要做好面试的准备,脑子里面过几遍,如何来说清楚这些事情

    3,直接回答问题,不要绕圈子

    4,测试流程,不管现在公司的测试流程怎么样,至少要了解经典的测试流程,以及各个阶段的目的

    5,英语能力,这个基本可以说就可以了,如果有准备会更好

  • 问题到底在哪里?

    2010-08-08 20:55:17

    这几天心情一直不好,因为公司的事情,一直在想,问题到底在哪里?我列几个问题:

    1.这个测试流程是个博傻的关系,谁认真做谁倒霉,来了几年,连系统一个完整的TestCase都没有,谁想做这个谁倒霉,这个需要很大的精力来做,而且本质上没有人完全了解这个系统

    2.公司到底公平嘛?不公平,机会都留给了没有做多少事情的人,而认真做事,做很多事情的人,却不能够很好的对待,公司评价人的标准是他会什么,而不是他做什么,应该说这是老板的标准,如何改变,没有办法,无非就是换个环境。公平不公平这种事情,没有什么好抱怨的,习惯就留,不习惯就走

    3.思路,从老板开始都没有什么思路,不确认我们面临的什么问题,个人觉得面临的问题就是没有完整的test case,把实际做事看成了无关紧要的事情,而去学习什么编程技术认为是一种个人能力的进步。至于测出来的bug,完全没有人关注,至于贡献什么价值,老板根本不在乎

  • 从八个方面写好测试用例

    2010-08-08 20:16:42

    从网站上看到了个不错的帖子,从八个方面写好测试用例:

    1.用统一的模板,个人推荐还是使用Excel,好用又方便

    2.测试用例描述简单同时清楚

    3.可重用--这点比较有意思

    4.原子性--这个我觉得挺重要的,至少分工的时候好用,尽量不要把一个case写的太长了

    5.正面和反面

    6.程序改变了,测试用例也要跟着变

    7.测试数据,如果太复杂,用图表来表示

    8.明确测试用例的前提条件

     

  • Ruby 学习笔记-Ruby 安装

    2010-07-17 21:24:22

    下载一键安装Ruby程序,双击就可以在Windows 上面安装,目前我可以在Window7上面使用Ruby1.9.1。

    下面是下载的网址:

    http://rubyforge.org/projects/rubyinstaller/

     

    安装结束之后, 可以使用netbeans作为编写Ruby程序的IDE,我比较喜欢Netbeans,最主要的一个功能就是,输入“之后自动会补全成“”,这样让我感觉少输一点字符,其他的编辑器像VIM之类的,我感觉入门有点高,所以我就直接使用netbeans了!

  • Perl-- Use Strict

    2010-04-24 17:27:35

    命令use strict意味着所有变量必须用my来声明,裸单词必须用引号括起来

    use strict;
    #!/user/bin/perl -w

    $pi=3.14 ;
    $area=$pi*(3*3);
    print $pi;
    print $area;

    这个会报错, 而要用:

    use strict;
    #!/user/bin/perl -w

    our $pi=3.14 ;
    our $area=$pi*(3*3);
    print $pi;
    print $area;

    或者

    use strict;
    #!/user/bin/perl -w

    my($pi)=3.14 ;
    my($area)=$pi*(3*3);
    print $pi;
    print $area;

    our 实际上就是一个定义全局变量,而my就是定义了局部变量

  • 测试的要求

    2010-04-24 16:29:50

    做个好的测试很难,知识面要求很宽,基本功要求很高;知识面,就是行业知识要求至少怎么也要个方方面面的了解,虽然不需要很深入,但是遇到问题之后至少可以知道从哪个方面了解业务知识来解决问题;基本功,也就是对于编码的了解,这个越来越有测试人员程序员化的要求了,不管从效率角度出发,还是从技术角度出发,现实越来越要求测试人员要有开发的能力了。看看满眼的招聘测试的要求,80%以上的senior的职位都需要自动化测试,或者了解编码像java或者一堆的动态语言和数据库语言。想想可能有两个方面的现实要求吧,一个了解业务,那可以从需求层面来把控质量关,了解编码,那就是从技术层面来深入的把控质量关。说到把控的问题,质量如何度量似乎永远都说不清到不明,这是个问题!

    从不断的学习中进步,从不断的练习中磨练,可怕的不是困难,可怕的是不思考问题,要有自己的原则,要有自己的目标,要有执行力,这是我对自己的要求!

  • Testing is really a tough job

    2009-12-11 22:26:38

    Testing is really a tough job,so much things to consider,so less income it is.It is really tough job.Normally, a tester like a blinder, can not know the detail of the software,but need to test;when find the bug, but do not know why the bug happens,so can not find the root cause and can not determine which cases is duplicated,which is needed.Developer just want to tell you he/she fixed it, but never tell you which then fix and for why.It is so bad,so tired.It is really for a tester,no good thing to find.
231/212>
Open Toolbar