发布新日志

  • CreateProcess error=87,

    2012-10-23 11:39:26

    Cannot run program "C:\Program Files\Java\jdk1.6.0_17\bin\javaw.exe" (in directory "C:\Workspace\testSeam1-test"): CreateProcess error=87, The parameter is incorrect
    今天非常悲剧的因为这个问题整了一整天,jdk、eclipse重装N遍都没用。
    网上找到的资料也非常少。
    http://blog.csdn.net/zhangren07/archive/2010/10/15/5944173.aspx
    只怪半天没看明白余二爷说的意思。
    二爷最后一句话说出解决的要点:修改maven的本地repository的默认路径
    C:\Documents and Settings\liuyi\.m2把这个目录下的repository包全删除


    再修改D:\tools\maven-2.2.1\conf目录下面setttings.xml文件。使用编辑器打开,找到localRepository一项,将它的值修改成<localRepository>D:\MavenRepository</localRepository>
    保险起见把C:\Documents and Settings\liuyi\.m2目录下的setttings.xml也一起修改了。

    运行maven命令,重新生成eclipse文件导入项目。纠结了一天的问题解决

    原因分析有说法是maven的默认目录C:\Documents and Settings\liuyi\.m2太长或者是有空格造成


  • 接口测试从零开始系列7_Maven使用

    2011-12-16 19:28:48

    1.        Maven是什么:

    Maven是一个项目管理工具,包含项目对象模型,一组标准集合,一个项目生命周期,一个依赖管理系统,和用来运行定义在生命周期阶段中插件目标的逻辑。

    2.        如何配置maven

    1,   下载:从官网http://maven.apache.org/download.html 获取maven2的文件包;

    2,解压该mavenD:\work\maven,并配置一下环境变量:

           在系统变量里的添加path D:\work\maven\bin

    3,在dos下输入命令:mvn  -v,如果配置正确将会得到maven的版本信息等。

    注意:需要配置%JAVA_HOME%

    3.        创建Maven工程

    使用命令创建:

    1,在dos下进入要创建项目的目录,如D:\mytestproject

    2,输入命令创建项目

    mvn archetype:create -DgroupId=com.test.mytest -DartifactId=mytestproject

    3,   命令执行完成后可以看到在D:\mytestproject下会生产一个maven工程

    4,   导入eclipse工程

    D:\mytestproject>mvn -U clean eclipse:clean eclipse:eclipse

    D:\mytestproject>mvn -U clean eclipse:clean eclipse:eclipse -DdownloadSources=true 

    使用eclips创建:

    1.        Eclipse中新建选择maven工程,

    4.        配置文件元素相关说明:

      groupId:项目或者组织的唯一标志,并且配置时生成的路径也是由此生成,  com.test.mytest生成的相对路径为:/com/taobao/mytest

    artifactId: 项目的通用名称

    packaging: 打包的机制,如pom, jar, maven-plugin, ejb, war, ear, rar, par 

    version:项目的版本

    name: 项目的名称, Maven 产生的文档用

    url: 哪个网站可以找到这个项目,提示如果 Maven 资源列表没有,可以直接上该网站寻找,   Maven 产生的文档用,一般有自己的资源库时不需要此项。

    5.        常用命令

    mvn package:依项目将在target文件下生成jar文件:mytestproject-1.0-SNAPSHOT.jar

    mvn clean:清除目标目录中的生成结果
    mvn install
        将项目的jar文件添加到资源库中以备依赖此项目时使用
    mvn eclipse:eclipse
    :生成Eclipse项目文件,此时项目可以成功importeclipse

    mvn deploy 打包部署到仓库,需要有权限

    mvn war inplace:打包为可执行jar

    mvn test -Dtest=类名 :执行某个测试类

    mvn test 执行所有测试类

     

    6.     Pom文件常用元素说明

    1.    继承:项目可以通过parent元素使用继承,避免在一个项目中不断的重复同样的依赖元素,当一个项目声明一个parent的时候,它从父pom中继承信息,也可以覆盖父pom中的值,或者可以添加一些新的值。Maven在读取当前项目的pom之前,会使用这个父pom作为起始点,同样的父pom中的依赖也会被子项目继承过来。

        <parent>

            <artifactId>test-harvest.business</artifactId>

            <groupId>com.test</groupId>

         <version>2.1.4-SNAPSHOT</version>

    </parent>

    2.       多模块    一个项目有多个模块,也叫做多重模块,或者合成项目。
    如下定义,比如在父工程厦门会包括api工程和service工程

        <modules>

            <module>test-harvest.business-api</module>

            <module>test-harvest.business-service</module>

    </modules>

    3.       Build设置:bulid主要是配置编译相关的内容

    1.        Proviles:定义一些在项目生命周期中使用的环境变量

    <profile>

            <id>test</id>     //表示是测试环境

            <properties>

                <props>src/main/filters/test.properties</props>  //环境变量的配置文件

                <projectName>${project.artifactId}</projectName>

    使用于哪个项目

            </properties>

            <activation>

                <activeByDefault>true</activeByDefault> //是否激活

            </activation>

         </profile>

    2.        插件:项目中使用到的插件,比如junit测试用例执行插件

    <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-surefire-plugin</artifactId>

                <configuration>

                   <skip>false</skip>   //是否跳过测试用例执行

                </configuration>

            </plugin>

         </plugins>

    3.        资源:项目中需要指定的资源位置

    <resources>

            <resource>

                <directory>src/main/resources</directory>

                <filtering>true</filtering>

            </resource>

         </resources>

    4.        依赖关系

              <dependency>

                <groupId>junit</groupId>

                <artifactId>junit</artifactId>

    <version>4.8.1</version//版本

                <scope>test</scope//表示是测试环境使用

         </dependency>

    7.        Settings.xml:

     maven的全局性的配置文件,使用于所有项目。在maven2中存在两个 settings.xml,一个位于maven2的解压目录conf下面,作为全局性配置。对于团队设置,保持一致的定义是关键,所以 maven2/conf下面的settings.xml就作为团队共同的配置文件,保证所有的团队成员都拥有相同的配置。当然对于每个成员,都需要特殊的自定义设置,如用户信息,所以另外一个settings.xml就作为本地配置。

    一些配置说明:

     

    1.     localRepository:表示本地库的保存位置,也就是maven2主要的jar保存位置,默认在${user.dir}/.m2/repository,如果需要另外设置,就换成其他的路径,如: <localRepository>D:\\ Repository</localRepository>

    2.     offline:如果不想每次编译,都去查找远程中心库,那就设置为true。当然前提是你已经下载了必须的依赖包。

    3.     Servers:保存server相关的信息,

            <server>

  • 接口测试从零开始系列6_简简单单Spring2

    2011-12-14 18:54:04

    请查看上篇:控制反转及容器

     

    Spring的依赖注入

    1.       Sringbean配置文件声明bean

        <bean id="pingJiaDao" class="com.koubei.springdiwithbeans.PingJiaDaoImplForSpring">

            <!--  第一种配置方式 -->

           <property name="username">

               <value>liuzhan</value>

           </property>

    <!--  第二种配置方式 -->

           <!-- <property name="username" value="liuzhan"></property> --> 

    <!--  第三种配置方式 -->

           <!--  p:username="liuzhan" -->

        </bean>

    2.       实例化ioc容器及bean

        public static void main(String args[]) {

        ApplicationContext context = new ClassPathXmlApplicationContext(

               "spring.xml");

        IStoreServiceForSpring storeService = (IStoreServiceForSpring) context

               .getBean("storeService");

     

        PingJia pingJia = new PingJia();

        pingJia.setPingJiaId("123456");

        storeService.addPingJia(pingJia);

    }

    3.       Bean引用

    <bean id="storeService" class="com.koubei.springdiwithbeans.StoreServiceForSpring"

        autowire="byName">

    <!—ref local:如果使用了local,验证拥有该idbean是否在同一个xml配置文件里 -->

        <property name="pingJiaDao">

            <ref local="pingJiaDao" />

        </property>

    <!—refbean名称可以引用ioc容器里任意的bean,即使不在同一个xml配置文件里 -->

        <!-- <property name="pingJiaDao" ref="pingJiaDao"></property> -->

    <!—声明内部bean -->

        <!-- <property name="pingJiaDao">

            <bean class="com.koubei.springdiwithbeans.PingJiaDaoImplForSpring">

               <property name="username" value="liuzhan" />

            </bean>

        </property> -->

    </bean>

    4.       检查属性:

    问题:通过setter注入的方式,不能保证所有的属性一定会被注入

    解决:spring的依赖检查特性可以检查bean上某些类型的所有属性是否都被设置

    方法1:通过dependency-check指定依赖检查模式(缺点:只检查某些类型的所有属性,不能检查特定属性

           <!-- 业务Bean定义 -->

        <bean id="pingJiaDao1" class="com.koubei.springdiwithbeans.PingJiaDaoImplForSpring"

           dependency-check ="simple">

           <!-- none:所有属性都可以不设置

                simple 简单类型检查

                objects 对象类型检查

                all    任意对象类型检查 -->

           <property name="username" value="liuzhan"></property>

    </bean>

    方法2:通过Required注解检查特定属性(需要设置<context:annotation-config/>

            @Required//自动检查username属性

            public void setUsername(String username) {

           this.username = username;

    }

    5.       Bean的自动装配

    问题:bean访问其他bean是需要显式的指定引用

    解决:能够自动装配避免显式的指定

    方法1:在xml使用autowire自动装配(缺点:如果使用几种方式都无法满足,autowire属性会自动装配bean的所有属性

           <bean id="storeService" class="com.koubei.springdiwithbeans.StoreServiceForSpring"

           autowire="byName">

                  <!-- no*:不执行自动装配,需要显式装配依赖

                       byName bean属性装配与属性同名的bean,但是有时候并不一定属性名和bean名称一致

                       byType bean属性装配同类型的bean,如果存在多个类型一致的bean,则会失败

                       constructor 每个构造器参数,先找出类型与构造器参数一致的bean,然后再找出具有最

                       匹配参数的构造器

                       autodetect 如果能够找到默认没有参数的构造器,则依赖byType模式自动装配,否则

                       采用constructor模式 -->

          

        </bean>

    方法2:使用@Atuowired@Resource自动装配bean(可以配置个别属性,需要注册<context:annotation-config/>

            @Autowired(required = false) //自动匹配类型兼容的bean,默认情况下,应用了@Autowired的属性都需要设置,使用required=false,则属性并不一定要设置

            @Qualifier("pingJiaDao") //自动匹配类型兼容的bean,并且名称是pingJiaDao

            @Resource(name = "pingJiaDao")//根据名称装配

    private IPingJiaDaoForSpring pingJiaDao ;

    6.       Bean属性集合

    Map集合

    <bean id="columnNames" class="java.util.HashMap">

        <constructor-arg>

            <map>

               <entry key="flag" value="1" />

               <entry key="caseID" value="2" />

               <entry key="caseName" value="3" />

               <entry key="caseDes" value="4" />

               <entry key="mothed" value="5" />

               <entry key="param" value="6" />

               <entry key="status" value="7" />

               <entry key="resultDes" value="8" />

            </map>

        </constructor-arg>

    </bean>

                       List

            <bean id="idList" class="java.util.List">

               <constructor-arg>

                   <list>

                      <value="1" />

                      <value="2" />

                      <value="3" />

                      <value="4" />

                      <value="5" />

                      <value="6" />

                      <value

  • 接口测试从零开始系列6_简简单单Spring1

    2011-12-14 18:52:14

    一.             控制反转和容器的思想

     

    1.       面向对象设计里,讲究“接口与实现分离”

    //定义接口

    public interface IPingJiaDaoForSpring {

        //插入一条记录

        public boolean insert(PingJia pingJia);

      

    }

        //接口实现

    public class PingJiaDaoImplForSpring implements IPingJiaDaoForSpring {

            @Override

            public boolean insert(PingJia pingJia) {

    //实现insert的具体方法

    }

     

    2.       在代码当中调用

    public class StoreServiceForSpring {

        //在此处写死了实现是PingJiaDaoImplForSpring()

        private IPingJiaDaoForSpring pingJiaDao = new PingJiaDaoImplForSpring();

       

        public boolean addPingJia(PingJia pingJia) {

           return pingJiaDao.insert(pingJia);

        }

    }

    3.       不同组织有不同的实现方式

    private IPingJiaDaoForSpring pingJiaDao = new 其他实现();

    问题:需要维护多个StoreServiceForSpring,每个各自创建和管理自己的依赖,对象之间的耦合性很高。

     

    4.       使用一个容器来管理这些组件

     

    public class Container {

        public static Container instance;

        private Map<String, Object> components;

     

        public Container() {

           components = new HashMap<String, Object>();

           instance = this;

           IPingJiaDaoForSpring pinjiaDao = new PingJiaDaoImplForSpring();

           components.put("pinjiaDao", pinjiaDao);

     

           IStoreServiceForSpring storeService = new StoreServiceForSpring();

           components.put("storeService", storeService);

        }

     

        public Object getComponent(String id) {

           return components.get(id);

        }

    }

    在组件中使用容器生成组件:private IPingJiaDaoForSpring pingJiaDao = (IPingJiaDaoForSpring) Container.instance

            .getComponent("pinjiaDao");

     

    5.       使用容器后,可以用容器来生成需要的组件:

    public class Main {

            public static void main(String args[]) {

               IStoreServiceForSpring storeService = (IStoreServiceForSpring) Container.instance

                  .getComponent("storeservice");

               PingJia pingJia = new PingJia();

               pingJia.setPingJiaId("123456");

               storeService.addPingJia(pingJia);

        }

    }

    6.       使用服务定位器查找组件(主动查找)

    public class ServiceLocator {

            public static Container container = Container.instance;

     

            public static IPingJiaDaoForSpring getPingJiaDao() {

               return (IPingJiaDaoForSpring) container.getComponent("pinjiaDao");

        }

    }

       在组件中使用查找器:private IPingJiaDaoForSpring pingJiaDao = ServiceLocator.getPingJiaDao();

     

    7.       应用控制反转和依赖注入

    在组件中使用查找器查找组件时,组件依旧需要知道如何查找资源,然后向容器发起请求查找资源,容器返回资源,

    使用控制反转原则:容器主动将资源推送到所管理的组件中,组件只是选择一种合适的方式接受资源。

                       public Container() {

    //components = new HashMap<String, Object>();

    //instance = this;

               IPingJiaDaoForSpring pingJiaDao = new PingJiaDaoImplForSpring();

               components.put("pinjiaDao", pingJiaDao);

     

               StoreServiceForSpring storeService = new StoreServiceForSpring();

               StoreServiceForSpring storeService1 = new StoreServiceForSpring(pingJiaDao);

               storeService.setPingJiaDao(pingJiaDao); //设置资源

               components.put("storeService", storeService);

               components.put("storeService1", storeService1);

          

        }

           依赖注入的三种方式:接口注入,setter注入,构造器注入

    8.       使用配置文件来配置容器

    public Container() {

           components = new HashMap<String, Object>();

        // instance = this;

        Properties properties = new Properties();

        try {

            properties.load(new FileInputStream("components.properties"));

            for (Map.Entry entry : properties.entrySet()) {

               String key = (String) entry.getKey();

               String value = (String) entry.getValue();

               processEntry(key, value);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

     

        IPingJiaDaoForSpring pingJiaDao = new PingJiaDaoImplForSpring();

        components.put("pinjiaDao", pingJiaDao);

     

        StoreServiceForSpring storeService = new StoreServiceForSpring();

        StoreServiceForSpring storeService1 = new StoreServiceForSpring(

               pingJiaDao);

        storeService.setPingJiaDao(pingJiaDao);

        components.put("storeService", storeService);

        components.put("storeService1", storeService1);

    }

     

    查看下篇:

     

  • 接口测试从零开始5_教你如何使用ibatis2

    2011-12-12 19:41:20

    察看教你如何使用ibatis1

     

    4.  配置SqlMapConfig配置文件

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE sqlMapConfig

        PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"

        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

    <sqlMapConfig>

    <properties resource="dbcpconfig.properties"/>

    <settings cacheModelsEnabled="false" enhancementEnabled="true" lazyLoadingEnabled="false" errorTracingEnabled="true" maxRequests="400" maxSessions="40"

        maxTransactions="32" useStatementNamespaces="true" />  

             <!--   

            1. cacheModelsEnabled 是否启动sqlMapClient上的缓存机制;  

            2. enhancementEnabled是否针对POJO启用字节码增强机制以提升getter/setter的调用效能,  

                    避免使用Java Reflect所带来的性能开销,同时也为Lazy Loading带来了极大的性能提升;  

            3. errorTracingEnabled 是否启用错误日志;在开发期间建议设为“true”以方便调试  

            4. lazyLoadingEnabled 是否启动延迟加载机制  

            5. maxRequests 最大并发请求数(Statement并发数)  

            5. maxTransactions 最大并发事务  

            6. maxSessions 最大Session数,即当前最大允许的并发sqlMapClient数(介于maxRequestsmaxTransactions之间)  

            7. useStatementNamespaces 是否使用Statement命名空间(为true时,需要追加命名空间)  

         -->

    <transactionManager type="JDBC"> 

           <dataSource type="SIMPLE">

           <!--dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性  

                type属性: dataSource节点的type属性指定了dataSource的实现类型 ,指定了数据源的链接类型,也有3种类型(SIMPLE,DBCP,JNDI)

                1. SIMPLE   SIMPLEibatis内置的dataSource实现,其中实现了一个简单的数据库连接池机制, 对应ibatis 实现类为  

                    com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory  

                2. DBCP: 基于Apache DBCP连接池组件实现的DataSource 封装,当无容器提供DataSource 服务时,  

                    建议使用该选项,对应ibatis 实现类为com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory  

                3. JNDI 使用J2EE 容器提供的DataSource 实现,DataSource 将通过指定的JNDI Name 从容器中获取。  

                    对应ibatis 实现类为com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory  

           --> 

       <property name="JDBC.Driver" value="${driverClassName}" />

        <property name="JDBC.ConnectionURL" value="${url}" />

        <property name="JDBC.Username" value="${username}" />

        <property name="JDBC.Password" value="${password}" />

        <property name="Pool.MaximumActiveConnections" value="10" /> <!--连接池维持的最大容量--> 

        <property name="Pool.MaximumIdleConnections" value="5"/> <!--连接池允许挂起的最大连接--> 

        <property name="Pool.MaximumCheckoutTime" value="120000"/> <!--连接被某个任务所允许占用的最大时间--> 

        <property name="TimeToWait" value="500"/> <!--线程允许等待的最大时间--> 

            </dataSource> 

        </transactionManager> 

         <!-- 指定映射文件的位置,配置中可出现多个sqlMap节点,以指定项目内所有映射文件 --> 

        <sqlMap resource="conf/sqlmap/pingjia.ibatis.xml"/>

    </sqlMapConfig>

     

    5.  读取配置文件

        static {

           try {

               Reader reader = Resources.getResourceAsReader("conf/testlearnning.sqlmapconfig.xml");

               sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

           } catch (Exception e) {

               e.printStackTrace();

    }

    6.  增删改查相关操作

    @Override

    public boolean insert(PingJia pingJia) {

        boolean flag = false;

        try {

            sqlMap.insert("PingJiaDao.insert", pingJia);

            flag =true;

        } catch (SQLException e) {

            e.printStackTrace();

        }

        return flag;

    }

  • 接口测试从零开始5_教你如何使用ibatis

    2011-12-12 19:35:44

    1.       创建pojo

    public class PingJia

    2.       创建Dao接口

    public interface IPingJiaDao

     

    3.  使用ibatis编写实现类

    1.  通过pom依赖引入ibatis

        <dependency>

            <groupId>com.ibatis</groupId>

            <artifactId>ibatis</artifactId>

            <version>2.3.4.726</version>

        </dependency>

     

    2.  编写实现类,引入ibatis SqlMapClientResource

    import com.ibatis.common.resources.Resources;

    import com.ibatis.sqlmap.client.SqlMapClient;

    import com.ibatis.sqlmap.client.SqlMapClientBuilder;   

    3.  配置POJO类的IBatis配置文件pingjia.ibatis.xm

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"

            "http://ibatis.apache.org/dtd/sql-map-2.dtd">

    <sqlMap namespace="PingJiaDao">

       <!--命名空间,在此空间外要引用此空间的元素,则需要加上命名空间名 -->

        <typeAlias alias="pingJia" type="com.koubei.testlearnning.pojo.PingJia"/> 

        <!-- 实体别名,  如果有用到全名的地方,可以用别名代替,受命名空间约束 -->

        <resultMap class="com.koubei.testlearnning.pojo.PingJia" id="PingJia">

           <result column="pingjiaid" property="pingJiaId" />

           <result column="pingjiacontent" property="pingJiaContent" />

           <result column="storeid" property="storeId" />

           <result column="pingjiatype" property="pingJiaType" />

           <result column="pingjiadate" property="pingJiaDate" />

        </resultMap>

        <!-- 结果集映射, -->

        <delete id="delete" parameterClass="java.lang.String" >

        <!-- 删除操作 -->

           delete from pingjia where pingjiaid=#pingJiaId#

        </delete>

        <insert id="insert" parameterClass="pingJia" >

        <!-- 插入操作   对于自增主键的表,插入可以不配置插入的主键列,否则是必须的-->

           insert

           into pingjia (pingjiaid, pingjiacontent, storeid,

           pingjiatype,pingjiadate)

           values(#pingJiaId#, #pingJiaContent#, #storeId#, #pingJiaType#,#pingJiaDate#)

        </insert>

        <update id="update">

        <!-- 更新操作-->

           update task_info

           <dynamic prepend="set">

        <!-- 动态sqlprepend表示链接关键字,property表示属性值-->

           <isNotNull prepend=" , " property="pingJiaContent">

                  pingjiacontent =

                  #excutePerson#

            </isNotNull>

               <isNotNull prepend=" , " property="storeid">

                  storeid =#storeId#

               </isNotNull>

               <isNotNull prepend=" , " property="pingJiaType">

                  pingjiatype

                  =#pingJiaType#

            </isNotNull>

               <isNotNull prepend=" , " property="pingjiadate">

                  pingjiadate

                  =#pingJiaDate#

                   </isNotNull>

           </dynamic>

           where pingjiaid =#pingJiaId#

        </update>

        <select id="getPingJiaList" parameterClass="java.lang.String" resultMap="PingJia">

        <!-- 查询操作,插入语句入参通过parameterClass="类别名"来设定,可以设定类别名,也可以设定为map

        也可以设定为iBatis支持的原生类型(比如stringintlong等,  map是最强大的入参方式,任何入参方式

        都可以转换为这种入参方式,因为iBatis仅接受一个入参,当几个参数分布在不同对象中的时候,将这些对象

        的属性(或者对象本身put)到map中,然后一次传递给sql语句-->

           sselect * from pingjia where storeId = #storeId#

        </select>

           <select id="getGoodPingNum" parameterClass="java.lang.String">

           sselect count(1) from pingjia where storeId = #storeId# and pingjiatype=1

        </select>

           <select id="getPingJiaNum" parameterClass="java.lang.String">

           sselect count(1) from pingjia where storeId = #storeId#

        </select>

    </sqlMap>

     

    察看教你如何使用ibatis2

  • 接口测试从零开始系列4_junit断言介绍2

    2011-12-12 19:07:00

    察看junit断言介绍1

     

     需要增加hamcrest

    在测试类里导入包

    import static org.junit.Assert.*;//assertThat跟下面的Matchers配合使用

    import static com.taobao.itest.matcher.Matchers.*;//增加了反射相关的匹配,比如验证两个对象的某几个属性相同

     

        // 通用匹配符

        @Test

        public void testAssert_nomarl() throws Exception {

           int num = 200;

           String storeId = "123456";

           // allOf:所有条件必须都成立

           assertThat(num, allOf(greaterThan(100), lessThan(300))); //运行成功

           assertThat(num, allOf(greaterThan(100), lessThan(150))); //运行失败

           // anyOf:只要有一个条件成立

           assertThat(num, allOf(greaterThan(100), lessThan(150)));//运行成功

           assertThat(storeId, anyOf(equalTo("123456"), equalTo("1234")));//运行成功

           // anything:无论什么条件

           assertThat(num, anything());  //运行成功

           // is:变量的值等于指定值时

           assertThat(storeId, is("123456"));//运行成功

    assertThat(num, is("200"));//运行成功

           // not:和is相反,变量的值不等于指定值时

           assertThat(storeId, notis("123456"));//运行成功

       }

     

        // 字符串相关匹配符

        @Test

        public void testAssert_String() throws Exception {

           String storeId = "assertTest";

           // 字符串匹配符

           assertThat(storeId, containsString("assert"));//运行成功

           // startsWith:字符串变量以指定字符串开头时

           assertThat(storeId, startsWith("assert"));//运行成功

           // endsWith:字符串变量以指定字符串结尾时

           assertThat(storeId, endsWith("t"));//运行成功

           // euqalTo:字符串变量等于指定字符串时

           assertThat(storeId, equalTo("assertTest"));//运行成功

           // equalToIgnoringCase:字符串变量在忽略大小写的情况下等于指定字符串时

           assertThat(storeId, equalToIgnoringCase("assertTEst"));//运行成功

           // equalToIgnoringWhiteSpace:匹配符断言被测的字符串testedString在忽略头

           //尾的任意个空格的情况下等于expectedString,注意:字符串中的空格不能被忽

           assertThat(storeId, equalToIgnoringWhiteSpace(" assertTest   "));//运行成功

    assertThat(storeId, equalToIgnoringWhiteSpace(" assert Test   "));//运行失败

       }

     

    察看junit断言介绍3

  • 接口测试从零开始系列4_junit断言介绍

    2011-12-12 18:53:21

    一. Junit4 断言

    assertEquals(a, b)

    assertFalse(a)

    assertTrue(a)       

    assertNotNull(a)

    assertNull(a)

    assertNotSame(a, b)

    assertSame(a, b)  

        @Test

        public void testAssert() throws Exception {

            int expectNum = 123;

            int actuNum = 123;

            String storeId = "123456";     

            // assertEquals(expect,actual),测试expect是否等于actualexpectactual是原始类型数值(primitive value)或者必须为实现比较而具有equal方法)

            assertEquals(expectNum, actuNum);//运行成功

            assertEquals(storeId, "12345"); //运行失败

            //assertFalse(condition)测试是否为false(假),condition是一个Boolean数值

            assertFalse(expectNum==100);//运行成功

            // assertTrue(condition)     测试是否为true(真),condition是一个Boolean数值

            assertTrue(expectNum==123);//运行成功      

            //assertNotNull(object),测试object是否非空,object是一个对象或者null

            PingJia pingjia= null;

            assertNotNull(pingjia);//运行失败

            //assertNull(object),测试object是否非空,object是一个对象或者null

            assertNull(pingjia);//运行成功

            // assertNotSame(unexpected, actual)测试unexpectedactual是否没有都引用同一个对象。

            String storeId1 = storeId;

            assertNotSame(storeId, storeId1);//运行失败

            // assertSame(unexpected, actual)测试unexpectedactual是否没有都引用同一个对象。

            assertSame(storeId, storeId1);//运行成功 

        }

    二. junit新断言

    1.        JUnit4.4引入了Hamcrest框架,使用全新的断言语法:assertThat,结合Hamcest提供的匹配符,只用这一个方法,就可以实现所有的测试,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活;

    2.        assertThat 语法如下:

     assertThat(T actual, Matcher<T> matcher);

    assertThat(String reason, T actual, Matcher<T> matcher);

    actual 是接下来想要验证的值;
    matcher
    是使用 Hamcrest 匹配符来表达的对前面变量所期望的值的声明,如果 actual值与 matcher 所表达的期望值相符,则断言成功,否则断言失败。

    reason是自定义的断言失败时显示的信息。

    3.        注意事项:

        a. JUnit4.4之后的版本才能使用assertThat方法;

    4.        优点

    1.        统一:只需一条assertThat语句即可替代旧有的其他语句(如assertEqualsassertNotSameassertFalseassertTrueassertNotNullassertNull等),使断言变得简单、代码风格统一,增强测试代码的可读性和可维护性。

    2.        直观:assertThat 不再像 assertEquals 那样,使用比较难懂的谓宾主语法模式(如:assertEquals(3, x);)。相反,assertThat 使用了类似于主谓宾的易读语法模式(如:assertThat(x,is(3));),使得代码更加直观、易读,符合人类思维习惯。

    3.        错误信息更具描述性

    旧的断言语法如果断言失败,默认不会有额外的提示信息,如assertTrue(testedString.indexOf(”taobao”) > -1);如果该断言失败,只会抛出无用的错误信息,如java.lang.AssertionError: ,除此之外不会有更多的提示信息。

    新的断言语法会默认自动提供一些可读的描述信息,如

    assertThat(testedString, containsString(”taobao”));

    如果该断言失败,抛出的错误提示信息如下:

    java.lang.AssertionError:

    Expected: a string containing “taobao”

    got: “taoba”

    4.        Matcher匹配符联合使用更灵活强大

     

    因空间字数限制,请察看junit断言介绍2

  • 接口测试从零开始系列_mock技术使用

    2011-12-08 20:12:27

     

    1.        什么情况下会使用mock技术

    1.        需要将当前被测单元和其依赖模块独立开来,构造一个独立的测试环境,不关注被测单元的依赖对象,只关注被测单元的功能逻辑

    ----------比如被测代码中需要依赖第三方接口返回值进行逻辑处理,可能因为网络或者其他环境因素,调用第三方经常会中断或者失败,无法对被测单元进行测试 ,这个时候就可以使用mock技术来将被测单元和依赖模块独立开来,使得测试可以进行下去。

    2.        被测单元依赖的模块尚未开发完成,而被测单元需要依赖模块的返回值进行后续处理

    ----------比如service层的代码中,包含对Dao层的调用,但是,DAO层代码尚未实现

    3.        被测单元依赖的对象较难模拟或者构造比较复杂

    ----------比如,支付宝支付的异常条件有很多,但是模拟这种异常条件很复杂或者无法模拟,比如,查询聚划算的订单结果,无法在测试环境进行模拟

    2.        Mock技术分类

    1.        手动构造mock对象

    ---------------比如,可以自己写某个接口方法的实现,根据需要编写返回值,测试代码中使用该实现类对象

    缺点:会增加代码量,在写mock对象代码时,有可能引入错误

    2.        使用开源代码提供的构造mock方法

    --------------比如easyMock,提供了对接口类的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定的值或抛出指定异常

    3.        EasyMock使用

    1.        引入easyMock

    ------------maven工程中,通过pom配置依赖关系

               <dependency>

                   <groupId>org.easymock</groupId>

                   <artifactId>easymock</artifactId>

                   <version>3.0</version>

                   <scope>test</scope>

    </dependency>

    ------------在普通java工程中,通过添加外部包的方式

     

     

    2.        使用easyMock过程

    1.        使用 EasyMock 生成 Mock 对象;

    pingJiaDao = mockControl.createMock(IPingJiaDao.class);

    2.        设定 Mock 对象的预期行为和输出;

    EasyMock.expect(pingJiaDao.getGoodPingJiaRate(storeId)).andReturn(0.11);

    3.        Mock 对象切换到 Replay 状态;

    EasyMock.replay(pingJiaDao);

    4.        调用 Mock 对象方法进行单元测试;

    storeService.setStoredao(pingJiaDao);

    double rate = storeService.getStoreGoodRate(storeId);

    5.        Mock 对象的行为进行验证。

    EasyMock.verify(pingJiaDao);

    4.        其他easyMock功能

    1.        特殊的mock对象:niceMock

    2.        参数匹配器

    3.        重置mock对象

    4.        模拟异常抛出

    5.        设置调用次数

     

  • 接口测试从零开始2------接口测试的全过程2

    2011-12-07 19:55:05

    请察看上篇

     

     

    代码实现

    1.   DAO实现,使用ibatis进行dao的实现

    2.   Service实现,数据插入,更新,获取,直接通过调用dao方法实现,业务逻辑在service中实现

    可测试接口方法

    1.   添加评价 boolean  addPingJia(PingJia pingJia)

    2.   更新评价 boolean updatePingJia(PingJia pingJia);

    3.   删除评价 boolean deletePingJia(String pingjiaId)

    4.   获得店铺星数 int getSotreStar(String storeId)

    5.   得到店铺排序位置 getStoreIndex(String storeId)

    6.   得到店铺好评率 int getStoreHaoPingLv(String storeId);

    接口测试过程

    1.   @BeforeClass注解中,做初始化相关的操作,比如需要创建服务实例:storeService = new StoreService();

    2.   @Test注解中,编写具体的测试用例,编写测试用例时可用的一些技巧:

    a.   通过不同的接口方法参数来实现对不同业务场景的覆盖

    b.   接口参数如果是基本数据类型,比如String,则需要考虑该参数是做什么用的,是否需要在调用被测方法之前准备相应的数据,比如,获得店铺星数, getSotreStar(String storeId) 需要的参数是String类型的storeId,我们在测试的时候,在调用被测方法之前,就需要先为这个storeId对应的店铺构造评价,来满足对应的测试用例。

    c.   接口参数如果是对象类型,则需要考虑是否可以通过独立的方法来提取设置对象属性过程,而将不同对象属性值通过方法参数传递,而如果对象属性过多,则可以考虑将部分对象属性构造为另外的一个对象

    d. 调用被测方法后,需要根据被测方法返回值,断言被测方法是否返回期望结果,同时需要通过数据库验证

    e. 如果一个测试用例中,涉及到多个步骤的验证,则需要在每个步骤后增加对应的验证方法。

    f. 在测试用例中,针对该测试产生的数据,需要进行销毁。

        3. @AfterClass注解中,增加对数据清理及对象销毁相应的方法

        4.  关于数据库比对:可以将数据库操作,比对的方法专门提取为一个公共类。

  • 接口测试从零开始2------接口测试的全过程1

    2011-12-07 19:45:26

    接口测试培训系列2------接口测试的全过程

          接口测试培训系列1中,描述了针对一个需求的实现方法,及对这个需求方法接口测试用例的设计,在本篇中,在该需求的基础上再增加需求,同时将需求扩展为一个小的项目,讲解针对项目的接口测试如何去做。

    需求描述:

    1.  增加店铺对象,评价属于店铺

    2.  可以针对店铺增加评价,删除评价,修改评价

    3.  根据店铺id获得店铺的星

    4.  根据店铺id获得店铺的好评率

    5.  根据店铺id获得店铺在所有店铺当中的排序,排序算法是:星越多排序越靠前,如果星相等,则根据好评率排序,好评率越高,排序越靠前,如果好评率相等,则评价越多越靠前,如果评价数相等,则默认当前店铺排名靠前。

    实现思路:

    1.  建立一个店铺类,具有店铺名称,店铺ID两个属性

    2.  建立一个评价类,具有所属店铺id,评价类型,更新时间属性

    3.  增加一个店铺操作类,具有增加评价,删除评价,修改评价,获取店铺星,获取店铺好评,获取店铺排序的方法

    4.  建立一个数据库,里面有两张表,一张店铺表,一张评价表

    5.  店铺表字段:店铺id,店铺名称

    6.  评价表字段:所属店铺id,评价类型,更新时间

    分层开发

    1.   DAO层:具体的对数据库的操作

     

    public interface IPingJiaDao {

         //插入一条记录

        public boolean insert(PingJia pingJia);

        // 修改评价记录

        public boolean update(PingJia pingJia);

        // 删除评价记录

        public boolean delete(String pingJiaId);

        //得到一个店铺的评价列表

        public List<PingJia> getPingJiaList(String storeId);

         //得到一个店铺的好评率

        public double getGoodPingJiaRate(String storeId);

    }

    2.   Service层:具体的业务逻辑层

    public interface IStoreService {

    //添加评价,

    public boolean addPingJia(PingJia pingJia);

         //修改评价类型

         public boolean updatePingJia(PingJia pingJia);

    //删除评价

    public boolean deletePingJia(String pingjiaId);

    //根据店铺Id,得到店铺的星数

    public int getSotreStar(String storeId);

    //得到店铺排序位置

    public int getStoreIndex(String storeId);

    //得到店铺好评率

    public double getStoreGoodRate(String storeId);

    }

     

    因为长度限制,请察看下篇

     

  • 接口测试从零开始系列1_如何针对接口方法设计测试用例

    2011-12-06 18:37:45

    需求内容:

    功能描述: 店铺会有很多的评价,评价分两种类型,好评,差评,根据店铺的没个评价,确定这个店铺有多少个星 。具体的要求是

    1.  评价分好评,差评

    2.  连续5个好评可以转换为1个星,有一个差评,减少1个星

    3.  最多有5个星

    4.  初始星为0,最少有0个星

    接口设计:

    public interface IStoreService {

        /**

         * 根据店铺Id,得到店铺的星数

         * @param  storeId店铺id

         * @return  店铺星数

         */

        public int getSotreStar(String storeId);}

    分析过程:

    从需求角度分析,需要测试的点包括:

    1.  店铺没有评价

    2.  店铺全部差评

    3.  店铺全部好评

    4.  店铺有差评,有好评

    5.  点评评价数小于5

    6.  店铺评价中,连续好评不够5

    7.  根据星计算规则,店铺所得星号大于5

     

    具体实现:

        private int getStar(List<PingJia> pingJiaList) {

           if (pingJiaList == null) {

               System.out.println("评价列表不能为null");

               return 0;

           }

           int star = 0;

           int pingJiaCount = pingJiaList.size();

           if (pingJiaCount < 5) {

               return star;

           }

           int goodPing = 0;

           for (int i = 0; i < pingJiaCount; i++) {

               if (pingJiaList.get(i).getPingJiaType() == PingType.goodPing) {

                  goodPing++;

                  if (goodPing == 5) {

                      star++;

                      goodPing = 0;

                  }

               } else {

                  goodPing = 0;

                  if (star > 0) {

                      star -= 1;

                  }

               }

           }

           if (star > 5) {

               star = 5;

           }

           return star;

        }

    用例设计

    测试过程:

    1.  分析需求,找出被测需求测试点:

    2.  分析测试点,通过测试用例设计方法,准备测试数据,添加期望结果,提炼测试点为可执行测试用例

     常用测试用例设计方法:

    1.  边界值

    2.  等价类

    3.  场景法

    4.  错误推测法

    5.  针对参数测试

    3.  根据测试用例,准备测试数据

    4.  编写测试代码,调用被测代码,执行测试,断言测试结果

    测试注意点

    1.  代码测试依赖的是需求,而不是开发的代码

    2.  代码测试的测试用例和功能测试用例类似,增加关于传入参数的验证

     

Open Toolbar