精华内容
下载资源
问答
  • 实用单元测试技术

    2021-03-02 22:58:44
     1.2单元测试的必要性 1.3单元测试的效益 第二章代码错误的分类及特点 2.1功能错误与性能问题 2.2代码错误的分类 2.3特征错误的特点 2.4无特征错误的特点 第三章基本测试方法 3.1单元测试的基本方法 3.2...
  • 单元测试,处于软件测试初期阶段,任务主要包括:模块接口测试、模块局部数据结构测试、模块中所有独立执行通路测试、模块的各条错误处理通路测试、模块边界条件测试。 模块接口测试是单元测试的基础。只有在...

      单元测试,处于软件测试初期阶段,任务主要包括:模块接口测试、模块局部数据结构测试、模块中所有独立执行通路测试、模块的各条错误处理通路测试、模块边界条件测试。

    1. 模块接口测试是单元测试的基础。只有在数据能正确流入、流出模块的前提下,其他测试才有意义。测试接口正确与否应该考虑下列因素:

      (1) 输入的实际参数与形式参数的个数是否相同;(2)输入的实际参数与形式参数的属性是否匹配;(3)输入的实际参数与形式参数的量纲是否一致;(4)调用其 他模块时所给实际参数的个数是否与被调模块的形参个数相同;(5)调用其他模块时所给实际参数的属性是否与被调模块的形参属性匹配;(6)调用其他模块时 所给实际参数的量纲是否与被调模块的形参量纲一致;(7)调用预定义函数时所用参数的个数、属性和次序是否正确;(8)是否存在与当前入口点无关的参数引 用;(9)是否修改了只读型参数;(10)对全程变量的定义各模块是否一致;(11)是否把某些约束作为参数传递。 如果模块内包括外部输入输出,还应该 考虑下列因素:(1)文件属性是否正确;(2)OPEN/CLOSE语句是否正确;(3)格式说明与输入输出语句是否匹配;(4)缓冲区大小与记录长度是 否匹配;(5)文件使用前是否已经打开;(6)是否处理了文件尾;(7)是否处理了输入/输出错误;(8)输出信息中是否有文字性错误;

    2. 检 查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整、正确。局部数据结构往往是错误的根源,应仔细设计测试用例,力求发现下面几类错 误:(1)不合适或不相容的类型说明;(2)变量无初值;(3)变量初始化或省缺值有错;(4)不正确的变量名(拼错或不正确地截断);(5)出现上溢、 下溢和地址异常。

    3. 除 了局部数据结构外,如果可能,单元测试时还应该查清全局数据对模块的影响。   在模块中应对每一条独立执行路径进行测试,单元测试的基本任务是保证模块中每条语句至少执行一次。此时设计测试用例是为了发现因错误计算、不正确的比较和 不适当的控制流造成的错误。此时基本路径测试和循环测试是最常用且最有效的测试技术。计算中常见的错误包括:(1)误解或用错了算符优先级;(2)混合类 型运算;

         (3)变量初值错;    (4)精度不够;    (5)表达式符号错。     比较判断与控制流常常紧密相关,测试用例还应致力于发现下列错误:    (1)不同数据类型的对象之间进行比较;    (2)错误地使用逻辑运算符或优先级;    (3)因计算机表示的局限性,期望理论上相等而实际上不相等的两个量相等;    (4)比较运算或变量出错;    (5)循环终止条件或不可能出现;    (6)迭代发散时不能退出;    (7)错误地修改了循环变量。

    1. 一 个好的设计应能预见各种出错条件,并预设各种出错处理通路,出错处理通路同样需要认真测试,测试应着重检查下列问题:(1)输出的出错信息难以理解; (2)记录的错误与实际遇到的错误不相符;(3)在程序自定义的出错处理段运行之前,系统已介入;(4)异常处理不当;(5)错误陈述中未能提供足够的定 位出错信息。

    2. 边界条件测试是单元测试中最后,也是最重要的一项任务。众的周知,软件经常在边界上失效,采用边界值分析技术,针对边界值及其左、右设计测试用例,很有可能发现新的错误。

    展开全文
  • 当前互联网主流的单元测试技术主要Junit, JMock, Mockito ,PowerMock等框架。 1.1 Junit单元测试框架 Junit是一套java编写的开源测试框架IDEA,Eclipse等开发工具均集成。可以轻松的完成依赖关系少或者...

    1 主流的单元测试技术

         当前互联网主流的单元测试技术主要有Junit, JMock, Mockito ,PowerMock等框架。

    1.1 Junit单元测试框架

          Junit是一套java编写的开源测试框架IDEA,Eclipse等开发工具均有集成。可以轻松的完成依赖关系少或者比较简单的单元测试,但是对于依赖关系多的场景又非常耗时。比如依赖数据库,依赖地图资源,或者依赖第三方的某些组件。很多时候我们需要修改依赖的资源来模拟程序运行的一些场景,却又无法保证这些依赖资源的正确性。在SpringMVC框架中我们一般只需要测试Controller层和Service即可保证比较高的测试覆盖率。也能够测试到程序的主要执行逻辑。为了摆脱依赖资源对单元测试效率的钳制,希望能够直接模拟这些资源,就引入了Mock(模拟)框架。

    1.2 Mock类框架对比

            JMock既可以模拟一般方法也可以模式静态方法等,但是写法较为复杂学习成本较高。Mockito 相较于JMock写法简单却不能模拟静态方法。PowerMock是Mockito 的增强,结合了两者的优点,引入了静态方法的Mock特性。却因为使用@PrepareForTest注解注入静态方法导致生成的字节码和一般测试字节码有所区别,所以被注解的进来的class无法出现覆盖率。但是我们一般不会在被测试目标中写静态方法,一般会写在工具类中。所以这些静态方法不会被覆盖,覆盖率会有所降低。当然这三个工具各有利弊,根据需要选择即可。

    2 如何使用PowerMock进行单元测试

           接下来以Maven项目为例手把手教你搭建PowerMock单元测试demo。

    2.1 引入依赖jar包

           在pom文件中添加如下所示的内容:

    版本号:

        <powermock.version>1.7.1</powermock.version>    <maven.compiler.source>1.6</maven.compiler.source>    <maven.compiler.target>1.6</maven.compiler.target>    <mockito1.version>1.10.19</mockito1.version>    <mockito2.version>2.8.9</mockito2.version>    <assertj-core.version>3.5.2</assertj-core.version>    <junit.version>4.12</junit.version>

    引入jar:

    <dependency>      <groupId>org.assertj</groupId>      <artifactId>assertj-core</artifactId>      <version>${assertj-core.version}</version>      <scope>test</scope>    </dependency>    <dependency>      <groupId>junit</groupId>      <artifactId>junit</artifactId>      <version>${junit.version}</version>      <scope>test</scope>    </dependency>    <dependency>      <groupId>org.powermock</groupId>      <artifactId>powermock-api-mockito</artifactId>      <version>${powermock.version}</version>    </dependency>    <dependency>      <groupId>org.powermock</groupId>      <artifactId>powermock-core</artifactId>      <version>${powermock.version}</version>    </dependency>    <dependency>      <groupId>org.powermock</groupId>      <artifactId>powermock-module-junit4</artifactId>      <version>${powermock.version}</version>    </dependency>    <dependency>

    2.2 编写待测试类

          拿我最喜欢的餐馆采购功能举例子,我有一个通过食物种类来获取餐馆采购的食物订单详情的方法。cookerService.getFoodList查询到蔬菜的采购订单详情,下面的循环中又将采购种类修改成了水果(真实情况应该没有这种业务,这里为了说明问题)。其中RestuarantUtils.isFood是一个静态方法。

    @GetMapping("foodList")    @ResponseBody    public List<FoodResponseEntity> getFoodList(FoodRequestEntity food) {        FoodResponseEntity foodResponse = new FoodResponseEntity();        List<FoodResponseEntity> FoodList = cookerService.getFoodList("蔬菜");        if(RestuarantUtils.isFood(FoodList)){          for(FoodResponseEntity foodResponseEntity:FoodList){          foodResponseEntity.setFoodKinds("水果");           }        }        return FoodList;    }

    2.3 编写单元测试

    第一步:引入PowerMockRunner并且将待Mock的静态类必须写到@PrepareForTest中。不要讲测试对象写到该注解,否则jacoco无法做到覆盖率统计。

    @RunWith(PowerMockRunner.class)@PrepareForTest({RestuarantUtils.class})public class CookerControllerTest {

    第二步:注入测试对象

      @InjectMocks  CookerController cookerController;

    第三步:注解的形式注入模拟的普通对象

     @Mock CookerServiceImpl cookerService;

    第四步:必须对注解对象和静态Mock对象初始化

      @Before    public void setUp() {        // 对定义了注解对象进行初始化        MockitoAnnotations.initMocks(this);        PowerMockito.mockStatic(RestuarantUtils.class);    }

    第五步:编写测试逻辑       

           首先分析要做的操作首先是Mock一个cookerService.getFoodList("蔬菜")的结果,其次是Mock静态函数RestuarantUtils.isFood(FoodList)的结果。然后执行整个方法获取结果。然后再和我们预期的结果对比。

     @Test    public void testGetFoodList(){        //假如食物清单全部为蔬菜        List<FoodResponseEntity> mockFoodList=new ArrayList<>();        FoodResponseEntity foodResponseEntity=new FoodResponseEntity();        foodResponseEntity.setFoodKinds("蔬菜");        mockFoodList.add(foodResponseEntity);        //现在开始Mock这个方法        PowerMockito.when(cookerService.getFoodList("蔬菜")).thenReturn(mockFoodList);        //mock静态方法        PowerMockito.when(RestuarantUtils.isFood(mockFoodList)).thenReturn(true);        //执行完要返回的清单        List<FoodResponseEntity> returnFoodList=cookerController.getFoodList(null);        Assert.assertEquals(returnFoodList.get(0).getFoodKinds(),"水果");    }

    小结:单元测试结果如下测试通过。

            

     

    3 单元测试覆盖率

    3.1 maven引入覆盖率插件

         通过maven引入maven-compiler-plugin插件执行编译操作,maven-surefire-plugin和jacoco-maven-plugin配合生成覆盖率。

    <build>    <plugins>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-compiler-plugin</artifactId>        <version>3.1</version>        <configuration>          <source>${jdk.version}</source>          <target>${jdk.version}</target>          <encoding>${project.build.sourceEncoding}</encoding>        </configuration>      </plugin>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-surefire-plugin</artifactId>        <version>2.12.4</version>        <configuration>          <skip>false</skip>        </configuration>      </plugin>      <plugin>        <groupId>org.jacoco</groupId>        <artifactId>jacoco-maven-plugin</artifactId>        <version>${jacoco.version}</version>        <executions>          <execution>            <id>prepare-agent</id>            <goals>              <goal>prepare-agent</goal>            </goals>          </execution>          <execution>            <id>report</id>            <phase>prepare-package</phase>            <goals>              <goal>report</goal>            </goals>          </execution>          <execution>            <id>post-unit-test</id>            <phase>test</phase>            <goals>              <goal>report</goal>            </goals>          </execution>        </executions>      </plugin>    </plugins>  </build>

    3.2 执行mvn生成覆盖率文件

           在terminal执行mvn clean install 生成测试文件以及覆盖率文件。如下图所示在浏览器端可以查看生成的静态覆盖率html文件:

    (1)执行mvn clean install命令

    (2)查看生成的覆盖率文件

    (3)浏览器查看

    3.3 注意事项

          引入的插件放在在<build>/<plugins>/下,不要在子级pom文件中出现pluginManagement否则mvn clean install命令不会执行覆盖率插件。

    (1)为什么网络上有些人生成覆盖率配置的命令非常长,本来mvn clean install就能实现的事情,命令中还要出现jar包?

           答:这是因为有些pom文件忽视了plugins和pluginManagement的区别。plugins 下的 plugin 是真实使用的,而 pluginManagement 下的 plugins 下的 plugin 则仅仅是一种声明,子项目中可以对 pluginManagement 下的 plugin 进行信息的选择、继承、覆盖等。

    (2)执行mvn test命令为什么会自动执行单元测试?

          约定俗成,Maven自动去寻找src/test/java下面的类,当此文件夹下面    的类符合以下规范,那么Maven默认认为他们是单元测试用例类。

      Test*.java:任何目录下以Test为开始的类

      *Test.java: 任何目录下以Test为结尾的类

      *TestCase.java: 任何目录下以TestCase为结尾的类。

    3.4 关于jacoco的在线模式和离线模式

           网络上有很多文章是对在线模式和离线模式的误读,这里推荐一篇文章详细的对比了这两种模式,一般情况下推荐在线模式。

    地址:

    JAVA代码覆盖率工具JaCoCo-原理篇

    4 总结

           经过个人的实践和体会,推荐使用PowerMock和jacoco做单元测试。

     好了,今天的教程就分享到这里,我是快乐的一只,一只快乐的我。如果我的文章对你有所帮助,请随手点个赞吧,您的鼓励将是我坚持创作下去最大的动力。

    博客地址:

    https://blog.csdn.net/renchunlin66

    码云社区地址:

    https://gitee.com/renchunlin66

    公众号请搜索:“快乐的一只”

    展开全文
  • 单元测试技术

    千次阅读 2016-12-06 16:42:46
    关于单元测试,个人认为,在开发一款软件时,测试是必不可少的一项,如果没有比较完善的测试,上线的项目往往会出现很多在开发阶段意想不到的问题。如果这样的一个项目上线之后,让你去负责这么一个不确定的东西,谁...

    关于单元测试,个人认为,在开发一款软件时,测试是必不可少的一项,如果没有比较完善的测试,上线的项目往往会出现很多在开发阶段意想不到的问题。如果这样的一个项目上线之后,让你去负责这么一个不确定的东西,谁都不敢想象,所以说这一部分还是很有必要学习一下的。

    1.什么是单元测试?

    • 单元:代码的基本组成单位,比如方法、类、模块等。
    • 测试:给定输入,检查输出是否符合要求。
    • 自动化测试:无需人工干预,定期、不定期自动执行的测试任务。

    2.关于java的单元测试框架

    • JUnit:最早的单元测试框架
    • TestNG:优化了的单元测试框架
    • Selenium:侧重于页面和集成测试
    • Arquillian:侧重于集成测试,整合CDI。

    以下是关于在Netbeans下进行的测试类的创建方式

    • 新建测试类:新建->测试类,选择要测试的类
    • 要在测试的类上右键点击“工具->新建更新测试”
    • 运行时,按照正常的java文件一样运行测试类即可

    Ps:

    1)在定义测试类的名称问题上,注意最好是用test+类名,否则可能会引起错误(Test class not found in selected Project)当然之后因为有@test注解可以避免,但最好将其作为一种习惯。

    2)对于生成的测试类进行运用修改时,需要将最后一行的fail...注释掉,不然在进行测试的时候事没有颁发通过的。

    3)在手写测试类的时候,按照对应的情况在上面进行相应的注释

    eg: //case1    //case2等等

    3JUnit主要的注解

    这里所说的对应的注解及为在netbeans里面创建对应的测试类的时候的一些勾选项目,如下所示:
    1

    对应会生成相应的测试方法,以下是各种注解的用法:

    • @Test:表明方法为测试方法(可以测试期望异常和超时时间)
    • @Before:每次执行测试方法前都要执行(初始化方法)
    • @After:每次执行测试方法之后都要执行(释放资源)
    • @BeforeClass:每次初始化测试类前都要执行(必须为static void)
    • @AfterClass:每次初始化测试类后都要执行(必须为static void)
    • @Ignore:忽略这个测试方法
    • @RunWith:制定测试类使用某个运行器
    • @Parameters:制定测试类的测试数据集合
    • @Rule:允许灵活添加或重新定义测试类中的每个测试方法的行为
    • @FixMethodOrder:制定测试方法的执行顺序

    一个测试类单元测试的执行顺序为:

    @BeforeClass - > @Before - > @Test - > @After - > @ AfterClass

    每一个测试方法的调用顺序为:

    @Before - > @Test - > @After

    引入对应的一个概念:代码覆盖率

    通常的计量方法:已测试的方法/总方法数

    JUnit常见断言

    assertArrayEquals(expecteds, actuals)查看两个数组是否相等。
    assertEquals(expected, actual)查看两个对象是否相等。类似于字符串比较使用的equals()方法
    assertNotEquals(first, second)查看两个对象是否不相等。
    assertNull(object)查看对象是否为空。
    assertNotNull(object)查看对象是否不为空。
    assertSame(expected, actual)查看两个对象的引用是否相等。类似于使用“==”比较两个对象
    assertNotSame(unexpected, actual)查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象
    assertTrue(condition)查看运行结果是否为true。
    assertFalse(condition)查看运行结果是否为false。
    assertThat(actual, matcher)查看实际值是否满足指定的条件
    fail()让测试失败

    JUnit测试套件

    • 将多个测试类组织到一起的方法按照顺序执行。
    • 在和Maven整合之后,这一部分就不太重要。

    JUnit和Maven的整合

    参见Phabricator/training实例

    链接:Training实例

    JUnit和Jenkins的结合

    在登陆Jenkins之后,对应的面板上有关与对应项目的参数信息,而这些对应的信息来源就是在用maven来生成的target>surefire-reports目录下的.xml文件来传递的信息。对应的pom文件配置为:

             <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.19.1</version>
                    <configuration>
                        <skip>true</skip>
                    </configuration>
                    <executions>
                        <!-- 单元测试 -->
                        <execution>
                            <id>unit test</id>
                            <phase>test</phase>
                            <goals>
                                <goal>test</goal>
                            </goals>
                            <configuration>
                                <includes>
                                    <include>**/*Test.class</include>
                                </includes>
                                <excludes>
                                    <exclude>**/*IT.class</exclude>
                                </excludes>
                                <skip>false</skip>
                            </configuration>
                        </execution>
                        <!-- 集成测试 -->
                        <execution>
                            <id>run-integration-test</id>
                            <phase>integration-test</phase>
                            <goals>
                                <goal>test</goal>
                            </goals>
                            <configuration>
                                <includes>
                                    <include>**/*IT.class</include>
                                </includes>
                                <excludes>
                                    <include>**/*Test.class</include>
                                </excludes>
                                <skip>false</skip>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>





    展开全文
  • 软件测试中测试技术:如何建立单元测试标准是时候出新版本了。那么应该把什么包括进来?显然,它应该包括每个模块的最新的最好的版本。对吧?“最新的和最好的”基于一个假设:最新的版本就是最好的版本。最新的版本...
  • java单元测试技术

    千次阅读 2014-06-17 11:40:33
    摘要:本文针对当前业软开发现状,先分析了WEB开发的技术特点和单元测试要解决的问题,然后分别阐述了解决这些问题的单元测试技术,内容包括:JUnit、测试桩构建、访问数据库的Java代码测试、Struts框架测试、服务器...
    转自:http://www.cnblogs.com/javawebsoa/archive/2013/05/20/3089258.html 
    
    摘要:本文针对当前业软开发现状,先分析了WEB开发的技术特点和单元测试要解决的问题,然后分别阐述了解决这些问题的单元测试技术,内容包括:JUnit、测试桩构建、访问数据库的Java代码测试、Struts框架测试、服务器布署环境下的组件测试、Spring下的单元测试,以及覆盖率检查技术,最后还谈到了测试自动化技术以及希望在业软推广的自动化测试框架和它带来的好处。另外,随本文还附有例子代码供大家参考。

    关键词:Java、Web开发、单元测试、工具、JUnit、EasyMock、DBUnit、Struts、StrutsTestCase、Cactus、Spring、Cobertura、覆盖率检查、自动化测试、例子代码。

     

    单元测试与开发技术密切相关,业软基于Java的开发一般是WEB应用开发,涉及的开发技术繁多,尤其是现在的开源软件盛行,更给Java增添了无穷的活力和生机,同时也给单元测试增加了复杂度,我们推行单元测试面临着前所未有的挑战,难怪项目组抱怨单元测试难测或测不起来。本文试图给出基于业软开发现状的Java单元测试完整解决方案,以便更加有效地在业软推行单元测试。下面我们从分析开发技术特点以及对单元测试的影响说起。

    1      基于Java开发的技术特点
    u  容器管理的组件开发

    开发WEB应用程序,实质上就是在开发一系列组件。组件的类型有很多,JavaBean、Servlet、Filter、JSP Taglib、EJB、Spring Bean,等等。这些组件一般是不能独立运行的,需要将它们布署到WEB服务器,通过与WEB容器或EJB容器交互才能实现一定的业务逻辑,也就是说,组件依赖的许多对象是运行时由容器创建的,如HttpServletRequest、HttpServletResponse、ServletContext、SessionContext、FilterChain、PageContext,等等,这就面临着单元测试时这些容器对象如何生成的问题。对于这些组件的测试一般我们有两种单元测试方法:一种是对被测组件进行隔离测试,组件依赖的服务器环境对象用桩取代,它的缺点是构建桩太麻烦;另一种是将组件运行在真实服务器环境下,有别于系统测试,被测对象是我们主动在测试代码中创建的,它的优点是更接近于真实环境、免除了构建桩的工作量。

    u  页面显示的视图开发

    有很多技术用于将视图与业务逻辑分开,如Struts、JSF、WebWork、Spring等,页面开发的技术也有很多,如Html、XML、JSP、JavaScript、Velocity,等等,对于这些页面文件,技术上很难进行编译和静态检查,对它们的测试虽然有一些工具支持,但效果均不理想,而且代码Review大家反映也很难发现实质性的页面问题,如何确保页面文件的质量一直是单元测试要解决的问题。

    u  框架复杂

    WEB开发使用的框架很少有自己独立设计的,一般都会使用现成的架构,如Struts、JSF、WebWork、EJB、Spring、Hibernate、iBATIS等等,不同的框架,能够支持单元测试的程度也是不一样的。

    u  数据库访问技术多

    业软的WEB应用开发很少有不访问数据库的,因为多是面向业务的开发,业务离不开数据存储。项目组可能会选择不同的数据库访问技术,如JDBC、EntityBean、Spring、Hibernate、iBATIS等,对于涉及数据库访问的代码如何做单元测试也是我们需要解决的问题。

    2      单元测试技术需要解决的问题
    有许多的单元测试技术和工具,综合起来,无非是为了解决以下问题。

    u  驱动(Driver)—驱动被测单元

    单元不能独立运行,必须实现调用它们的代码,我们称其为驱动代码,其实最简单的驱动就是实现main方法,大家常用的驱动典型工具就是JUnit。

    u  构建桩(Stub)—模拟被测单元依赖的对象

    被测的孤立单元通常会对其它对象有依赖,这种依赖通常表现在:依赖对象通过被测方法参数传入或者被测对象保存有依赖的对象引用,然后在被测方法中调用了依赖对象的方法。构造依赖对象,一方面我们可以直接将开发完成的并且之前已经过单元测试的代码直接拿过来用,另一方面,也是更常用的方法,就是自己构建模拟对象,我们称其为桩,但自己写桩很麻烦,工作量大,现成构建桩的理想工具是EasyMock。

    u  验证(Verify)

    用例执行是否成功,需要在测试中添加验证点,需要将预期结果与测试执行获得的实际结果进行比较,为此JUnit为我们提供了验证的基本逻辑框架,其它工具可以基于它实现更复杂的验证逻辑,如DBUnit实现的对数据库表数据的验证。

    u  用例管理

    常有同事提到用main方法也能实现对被测单元的驱动,但我觉得最大的不足是无法实现对用例的有效管理,为此JUnit为我们提供了用例管理的基础框架,通过引入测试套的概念将用例有效地组织起来。

    u  结果输出(Report)

    测试结束后要能够将本次运行的结果情况形成报告,并以图形化直观的形式报告给用户。JUnit也为我们做到了,尤其是IDE与JUnit的集成,使我们在开发过程中做单元测试变得更加方便。

    u  覆盖率检查

    公司要求被测代码要求达到语句的100%覆盖,是否覆盖到了,我们可以借助覆盖率检查工具,做测试执行的同时进行覆盖率检查,对未覆盖到的代码可能会发现两类问题:不可达代码,这样的代码需要优化;用例设计不充分,这时就要及时补充用例。常用的覆盖率检查工具有PureCoverage、Cobertura。

    u  测试自动化

    实现测试自动化的好处大家都很明白,方便回归测试,节省了工作量;另一个好处是便于对测试的监控,这一点我们在后面会谈到。我们模索系统测试自动化已有多年,但效果都不理想,主要原因我觉得和系统测试本身的特点有关,因为系统测试是站在用户角度看系统功能的整体表现(这其中最讨厌的是我们经常还有需求变更,如何做到以不变应万变,我们曾经尝试过,但效果均不理想)。但单元测试不同于系统测试,单元不能独立运行,需要我们实现驱动代码,它的这个特点决定了实现单元测试自动化是非常容易也是顺理成章的事。

    3      Java单元测试技术总览
    基于Java的开发一般分为Java应用程序开发和Web应用程序开发,目前我们已经有了针对Java开发的较为全面的单元测试解决方案,可以说,每个开发领域都已经有了相应的单元测试技术支持,以下是一个简单示意图,后面的章节我们针对每项技术分别阐述。

     

    4      单元测试的基础框架(JUnit)
    JUnit是Java单元测试的经典之作,它的功能包括:提供实现测试用例的框架,并驱动测试执行;提供验证逻辑;用例执行结果统计与报告;测试套、测试用例管理。JUnit是Java单元测试的基础框架,Java领域的其它测试工具和技术一般都是基于它的扩展,如我们后面提到的:EasyMock、StrutsTestCase、DBUnit等,另外Spring中的单元测试支持也是基于它的。

    使用JUnit只需要将junit.jar加入CLASSPATH路径即可。因为Java编译后不需要链接(不同于C++),加上流行的IDE,如Eclipse、JBuilder、NetBeans等,都集成有JUnit,我们可以在IDE中边写代码、边做测试、边做重构。所以实际上,Java的单元测试比起C++来更方便。

    1)        基本概念

    测试用例(TestCase):同我们公司的测试用例概念,但用例是以测试方法(测试代码)的形式体现的,一个测试方法对应一个测试用例,JUnit框架提供了抽象类TestCase,我们要做的就是继承该类,增加测试方法,在测试方法中实现对被测试代码的调用,并增加验证点。同一个类可以有很多个测试方法,你只要向测试框架提供这个实现类就可以了,框架负责生成测试用例对象(就是实例化测试用例),一个测试方法生成一个测试用例对象,用例有用例名称,取的就是测试方法名。测试方法的原型(函数定义)必须满足以下要求:

    ü  当然是公共方法

    ü  方法名以“test”开头

    ü  方法无参数

    ü  方法的返回值类型为void

    框架在装载你的测试用例类的时候,使用JAVA的反射技术,基于以上条件找到你的测试方法,并创建用例对象。

    测试套(TestSuite):若干个测试用例对象组成一个测试套,测试套与测试用例的关系就如同文件夹与文件的关系一样,测试套包含测试用例,当然也可以包含子测试套。之所以这样,是便于测试用例的组织和管理。JUnit提供了可直接实例化的TestSuite类,实现了很多功能,例如:分析一个测试用例类,对每一个测试方法生成一个测试用例对象,将这个测试用例类的所有测试用例对象作为一个测试套;实现对测试用例的调用以及子测试套的递归调用(实际上是子测试套包括的用例)。

    2)        测试用例类的基本结构

    以下是测试用例类的基本结构:

    public class HelloWorldTest extends TestCase

    {

     

       

        protected void setUp( ) throws Exception

        {

            super.setUp();

        }

     

       

        protected void tearDown( ) throws Exception

        {

            super.tearDown();

        }

     

       

        public final void testCalculate( )

        {

            //TODO 实现 calculate()。

        }

     

    }

    其中TestCase基类由JUnit框架提供。

    3)        框架常见类介绍

    JUnit包含6个包(package):junit.awtui、junit.swingui、junit.textui、junit.extensions、junit.framework、junit.runner。其中前三个包中包含了JUnit运行时的入口程序以及运行结果显示界面,它们对于JUnit使用者来说基本是透明的。junit.runner包中包含了支持单元测试运行的一些基础类以及自己的类加载器,它对于JUnit使用者来说是完全透明的。剩下的两个包是和使用JUnit进行单元测试紧密联系在一起的。其中junit.framework包含有编写一般JUnit单元测试类必须要用到的JUnit类;而junit.extensions则是对framework包在功能上的一些必要扩展以及为更多的功能扩展留下的接口。我们常用的还是junit.framework包,所以下面我就将这个包下的类作一介绍。

     

    以上是这个包下的类图,为方便理解,我将Throwable类和Error类也放了进来,注意它们是JDK提供的类,非本包的类。

    u  接口Test、抽象类TestCase、类TestSuite之间的关系

    Test是接口(interface),定义有方法run,TestCase和TestSuite都实现了该接口,前面我们提到TestSuite包含TestCase, TestSuite有一个Vector成员,Vector的元素就是它包含的TestCase,当然也可以是子TestSuite,所以为便于管理,TestSuite只认Test接口,在它看来TestSuite包含的是Test对象,而不用细分为TestCase和子TestSuite。对测试套run方法的调用,相应地就会递归调用它所包含的用例run方法和子测试套run方法。这里使用到了Composite设计模式,另外,从命令调用(run命令)与命令实现分离的角度看又能看到Command设计模式的影子。

    u  抽象类TestCase

    抽象类TestCase实现了接口Test,以下是接口Test的一个方法原型:

    public abstract void run(TestResult result);

    TestCase对这个方法的实现如下:

    public void run(TestResult result) {

         result.run(this);

    }

    对这个方法的调用又将主动权交给TestResult,由TestResult来执行对被测方法的调用,这样便于TestResult跟踪用例执行结果并记录下来,以便作最后的统计分析。

    转到TestResult中这个方法的实现:

    protected void run(final TestCase test) {

         startTest(test);

         Protectable p= new Protectable() {

            public void protect() throws Throwable {

                test.runBare();

            }

         };

         runProtected(test, p);

     

         endTest(test);

         //这个方法和上面的startTest用于调用TestListener接口对象,实现监听机制。

    }

    在这个方法中调用了TestCase的runBare方法:

    public void runBare() throws Throwable {

         setUp();

         try {

            runTest();

         }

         finally {

            tearDown();

         }

    }

    可以看到先调用了setUp,之后不管是否产生了异常,都一律调用了tearDown,这两个方法在TestCase中空实现,我们的用例子类可以覆盖(overload)这两个方法,用于用例执行前的初始环境建立和用例执行后的环境清除。接下来我们关注TestCase的runTest方法,看它如何调用到我们的测试方法的。前面提到,TestCase维护了一个用例名称,这个用例名称在TestCase实例化时传入,用例名称就是测试方法名,知道了测试方法名,也就知道了测试方法原型,使用JAVA的反射机制实现了对测试方法的调用。注意这个测试方法正是TestCase子类需要实现的。

    protected void runTest() throws Throwable {

            ......

         Method runMethod= null;

         try {

            runMethod= getClass().getMethod(fName, null);// fName是测试方法名

         } catch (NoSuchMethodException e) {

            ......

         }

         ……

         try {

            runMethod.invoke(this, new Class[0]);

         }

            ......

    }

    u  类TestSuite

    类TestSuite不需要我们再子类化了,它维护了对一组测试用例对象的引用(包括它所包含的嵌套TestSuite对象),它也实现了Test的接口,run方法的实现就是递归调用它所引用的对象的run方法,下面我们谈一下给定一个TestCase子类(指类定义),TestSuite是如何针对其中定义的每个测试方法生成对应的TestCase对象的。以下是TestSuite的两个相关方法,一个是构造方法(给定用例类,生成该测试套下的用例对象)和成员方法(给定用例类,生成子测试套下的用例对象)。

    public TestSuite(final Class theClass){ }

    public void addTestSuite(Class testClass) { }

    这两个方法的实现相似,基本实现思路是根据JAVA的反射技术,找出用例定义的满足以下条件的成员方法(测试方法)

    条件1:当然是公共方法

    条件2:方法名以“test”开头

    条件3:方法无参数

    条件4:方法的返回值类型为void

    对应每一个这样的方法生成该用例类的一个对象,并将用例名初始化为该方法名。测试套下的用例对象就是这样生成。

    u  类Assert

    类Assert是TestCase的基类,其中定义了可供TestCase使用的大量静态方法,用于实际返回值与预期值的比较,这些方法名都是以assert开头,在我们自己写的测试方法中可以使用这些方法用于测试结果的验证。要注意的是JUnit对测试失败(实际值与预期值不符)是以抛出AssertionFailedError异常的形式体现的。我们看一个assert方法的典型实现:

    static public void assertTrue(String message, boolean condition) {

         if (!condition)

            fail(message);

    }

    static public void fail(String message) {

         throw new AssertionFailedError(message);

    }

    一旦验证逻辑验证失败,该用例就会抛出AssertionFailedError异常,TestResult记录下测试失败的该用例对象引用以及它所抛出的异常,这两者的对应关系是TestFailure类体现的,它用于维护用例对象与异常(注意异常的引用类型是所有异常的基类Throwable)的对应关系。TestResult有一个Vector类型成员变量fFailures,它的元素就是TestFailure对象。

    用例执行中除了可能会捕获到AssertionFailedError异常,被测代码有可能会抛出其它异常,包括RuntimeException运行期异常、JAVA虚拟机抛出的Error异常,抛出了这样的异常,也意味着用例执行失败,为此TestResult还有另一个Vector类型成员变量fErrors,它的元素也是TestFailure对象,不过它维护的是用例对象与非AssertionFailedError异常的对应关系。

    在用例执行结果中分别显示出因抛出AssertionFailedError异常而失败的用例个数(故障,Failure),以及因抛出非AssertionFailedError异常而失败的用例个数(错误,Error)。

    以下是在Eclipse中的的执行结果图示:

     

    4)        JUnit4.X的用例设计

    JUnit4.0之后的版本在用例设计上有较大的改变,主要使用了JDK5.0的Annotation新特性,但业软有相当多的版本还未升级到JDK5.0,另外,部分基于JUnit的单元测试工具还未升级到JUnit4.X,所以短期内就会出现JUnit新老版本共存的局面,但不管如何,JUnit中设计用例都很方便。下面我们简单看一下JUnit4.0以后的用例设计。

    u  用例类不再需要继承自TestCase基类

    u  测试方法名也不需要必须以test开头

    u  几个Annotation标识

    Ø  @Test—标识一个测试方法(对应一个用例)

    l  expected属性可以标识该方法执行期望会抛出什么异常

    l  timeout属性可以指定该方法必须在指定的时间内执行结束

    l  验证失败抛出JDK自带的AssertionError异常

    Ø  @Before —每个测试方法运行前要执行的方法,相关于以前的setUp()

    Ø  @After —每个测试方法运行后要执行的方法,相关于以前的tearDown()

    Ø  @Ignore —暂时不运行该测试方法

    另外,新版本的Eclipse和ANT已经全面支持JUnit4.X。
    转自:http://www.cnblogs.com/javawebsoa/archive/2013/05/20/3089258.html
    展开全文
  • 单元测试技术

    2009-05-09 18:34:00
    重点讲解如何使用Mock/Stub和依赖注入技术进行单元测试。关于工具JUnit等则不做累赘介绍。希望通过本章能够帮助大家开始单元测试的有益实践,与大家共勉!一、Stub技术这是最为古老的一种测试技能。通过类层次上的...
  • 持续集成技术单元测试方法 内容包括以下: 持续集成技术 – 持续集成的基本概念 – 持续集成的作用和优点 – 如何实施持续集成 • 单元测试技术 – 单元测试基本方法 – 单元测试实践中常见的问题 – 单元...
  • 表格驱动的单元测试技术(1)

    千次阅读 2014-03-27 14:51:52
    【摘要】本文分析了传统单元测试技术的不足,提出了表格驱动的单元测试技术,新技术可以大幅降低单元测试的难度及综合成本,用户不需要编写测试代码,测试工作效率通常是现有技术的五倍以上。新技术已在C/C++单元...
  • 一、单元测试 为何要进行单元测试? 尽早发现错误 错误发现越早,成本越低。 发现问题比较容易 修正问题更容易 1.定义 单元测试是对软件基本的组成单元进行独立的测试 2.目标 单元模块是否被正确编码。 信息能否...
  • 不经意的转变成集成测试 我们可以将被依赖的类在测试中实例化 被依赖的类肯定也在依赖别的类 一环扣一环,于是我们把整个软件的大部分类都牵扯到一次测试中 这个单元测试变得笨重 这已经不是单元测试了!!!
  • 考虑到单元测试的并行性,提出了基于函数优先级的测试策略.分析了函数的参数、全局变量和局部变量对函数控制流正确实现的影响,建立了量化的权值影响因子数学模型,并结合函数的控制流图生成了带权值向无环图,...
  • 白盒测试关注的是类中一个方法的功能,是更小的单位,但是完成一个单元测试可能需要N多类,所以说作单元测试需要写驱动和稳定桩,比如查询单元是一个查询包,包括N多的测试类、测试数据,运行他需要提供数据的部分,...
  • 单元测试-mock技术基础
  • 实用单元测试技术(1)

    2011-12-18 11:38:48
    单元测试是高收益难实施的过程改进。...越复杂的程序越需要充分测试,只能应用于简单代码的测试技术有什么意义呢? 理想的单元测试理论体系应该符合以下标准: 实用,即能应用于实际项目,能测试
  • 许多的单元测试技术和工具,综合起来,无非是为了解决以下问题。 u 驱动(Driver)—驱动被测单元 单元不能独立运行,必须实现调用它们的代码,我们称其为驱动代码,其实最简单的驱动就是实现main方法,大家...
  • 实用单元测试技术(2)

    2011-12-18 11:43:01
    第一章 单元测试的必要性和效益 1.1 什么是单元测试? 工厂在组装一台电视机前,会先测试所有元器件,与此类似,软件开发过程中也要对各个代码单元进行单独的隔离的测试,这就是单元测试。 "代码单元...
  • 考虑到单元测试的并行性,提出了基于函数优先级的测试策略.分析了函数的参数、全局变量和局部变量对函数控制流正确实现的影响,建立了量化的权值影响因子数学模型,并结合函数的控制流图生成了带权值向无环图,...
  • 白盒测试技术-单元测试理论篇

    千次阅读 2008-12-19 11:09:00
    白盒测试技术-单元测试理论篇作者:张元礼http://blog.csdn.net/vincetest 2.1 单元测试概念单元测试单元测试又称模块测试,属于白盒测试,是最小单位的测试。模块分为程序模块和功能模块。功能模块指实现了一个...
  • 1.1白盒测试和单元测试的区别的论述: 1) 单元测试和白盒测试是不同的,虽然单元测试和白盒测试都是关注功能,虽然他们都需要代码支持,但是级别不同, ... 不过很多时候是很少区分的,因为这两种技术实现起来...
  • 浅谈软件测试嵌入式单元测试技术

    千次阅读 2009-12-15 10:38:00
    对嵌入式系统软件进行测试是一项很挑战性的工作。因为嵌入式系统的软件开发平台和最终运行平台是完全不一样的两个平台,开发者不可能... 本文阐述了单元测试在嵌入式系统软件开发过程中的作用以及其如何帮助开发者解
  • 单元测试技术培训练习总结报告

    千次阅读 2009-12-08 11:21:00
    培训日期:2007年9月14日到2007年9月15日日程安排:第1天:上午:单元测试技术与方法培训下午:LINUX下CUNIT单元测试工具的使用方法第2天:上午:分组练习下午:分组练习练习总结练习情况概述:约50名开发人员参加...
  • 单元测试作为代码级最小的单位的测试,在软件开发过程中举足轻重的作用。极限编程(XP)推崇测试优先原则,由此引发了软件开发方法从传统的瀑布模型转向以测试为驱动的敏捷开发模式的革命。在这场软件开发方法革命中,...
  • 覆盖了8个条件取值和4个分支 其实判定/条件覆盖也缺陷从表面上看它测试了所有条件的取值但事实并非如此因为往往某些条件覆盖另一些条件 如对于表达式 (A>1) and (B=0) 来说若 A>1) 的测试结果为真则还要测试 (B=0)...
  • 包括软件测试基础、软件测试方法、软件测试流程和规范、单元测试与集成测试、系统测试、验收测试、软件本地化测试、测试自动化及其框架、白盒测试和黑盒测试等。 软件测试方法技术  软件测试方法: 一、等价类测试...
  • 单元测试

    千次阅读 2019-04-09 08:26:02
    1、测试类型有哪些? 2、单元测试介绍 3、单元测试的特性:断言、注解、Mock
  • 单元测试:又称模块测试,是针对软件设计的最小单位——程序模块进行正确性检验的测试工作(对于软件的一个一个小功能进行测试就是单元测试)。其目的在于检查每个程序单元能否正确实现详细设计说明中的模块功能、...
  • 本文以及一系列文章均转自... 单元测试——是最小粒度的测试,以测试某个功能或代码块。一般由程序员来做,因为它需要知道内部程序设计和编码的细节。 JUnit ——是一个开发源代码的Java测试框架,用于编

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 272,733
精华内容 109,093
关键字:

单元测试技术包括哪些