自动化单元测试实践之路(4)

发表于:2014-07-29来源:uml.org.cn作者:李乐点击数: 标签:
其次,重构那些运行时间比较长且不经常失败的测试类; 更多参考推荐阅读:《Unit Testing Guidelines》 http://geosoft.no/development/unittesting.html 4 流程 图-4-1-典型工

  其次,重构那些运行时间比较长且不经常失败的测试类;

  更多参考推荐阅读:《Unit Testing Guidelines》

  http://geosoft.no/development/unittesting.html

  4 流程

  图-4-1-典型工作流程

  开发人员遵循每日构建原则,提交功能代码、测试代码(以UnitTest结尾的测试类)到Svn;

  Jenkins平台,根据配置原则(假设配置定时器每6分钟检查Svn有代码更新则构建)进行:代码更新、代码编译、UnitTest、持续反馈的流水线工作;

  构建结果发送到Sonar,并且把失败的构建以邮件方式通知影响代码的开发人员;

  开发人员、测试人员需要在Sonar平台进行review;

  5 实践

  Jenkins配置重点

  构建触发器:推荐使用PollSCM

  Poll SCM:定时检查源码变更(根据SCM软件的版本号),如果有更新就执行checkout。

  Build periodically:周期进行项目构建(它不care源码是否发生变化)。

  配置时间:H/6 * * * *

  1、Build配置

  Goals and options:emma:emma -Dtest=*UnitTest soanr:sonar

  注明:

  emma:emma,Add the "emma:emma" goal to your build to generate Emma reports;

  -Dtest=*UnitTest,参数配置,运行以UnitTest结尾的测试类;

  sonar:sonar,来触发静态代码分析。

  需要安装Emma Plugin(https://wiki.jenkins-ci.org/display/JENKINS/Emma+Plugin)

  2、构建后操作

  增加Aggregate downstream test results,勾选自动整合所有的downstream测试;

  增加Editable Email Notification,在“高级”选项增加触发器“Unstable”,

  勾选“Send To Committers”,Check this checkbox to send the email to anyone who checked in code for the last build。

  注明:Editable Email Notification插件是 https://wiki.jenkins-ci.org/display/JENKINS/Email-ext+plugin

  另外一些Jenkins的单元测试覆盖率展现方式,可以查看官网。

  构建管理工具(Maven)

  1、项目统一使用Maven进行构建管理,在pom.xml中进行依赖jar包配置

  2、持续集成服务器上同时需要安装Maven,setting.xml除了配置仓库之外,还需要配置sonar,包括sonar服务器地址、数据库连接方式:

<profile>
    <id>sonar</id>
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
    <!-- EXAMPLE FOR MYSQL -->
    <sonar.jdbc.url>
      jdbc:mysql://127.0.0.1:3306/sonar?useUnicode=true&characterEncoding=utf8
    </sonar.jdbc.url>
    <sonar.jdbc.driverClassName>com.mysql.jdbc.Driver</sonar.jdbc.driverClassName>
    <sonar.jdbc.username>sonar</sonar.jdbc.username>
    <sonar.jdbc.password>sonar</sonar.jdbc.password>
    <!-- SERVER ON A REMOTE HOST -->
    <sonar.host.url>http:/127.0.0.1:9000</sonar.host.url>
    </properties>
</profile>

  Mockito配置重点

  所有单元测试继承MockitoTestContext父类

  MockitoTestContext 父类:

package com.chinacache.portal;
import java.util.Locale;
import org.junit.BeforeClass;
import org.mockito.MockitoAnnotations;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.chinacache.portal.web.util.SessionUtil;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
/**
 * Mockito 测试环境。继承该类后,Mockito 的相关注解 (@Mock, @InjectMocks, ...) 就能生效
 */
public class MockitoTestContext {    
    public MockitoTestContext() {
        MockitoAnnotations.initMocks(this);
    }
}

  BillingBusinessManager 源码:

package com.chinacache.portal.service.billing;
//引入包忽略...
/**
 * 计费业务相关的业务方法
 */
@Transactional
public class BillingBusinessManager {
    private static final Log log = LogFactory.getLog(BillingBusinessManager.class);
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private BillingBusinessDAO billingBusinessDAO;
    @Autowired
    private BillingBusinessSubscriptionDAO billingBusinessSubscriptionDAO;
    @Autowired
    private BillingBusinessSubscriptionDetailDAO billingBusinessSubscriptionDetailDAO;
    @Autowired
    private BillingRegionSubscriptionDAO billingRegionSubscriptionDAO;
    @Autowired
    private BillingRegionDAO billingRegionDAO;
    @Autowired
    private ContractTimeManager contractTimeManager;
    /**
     * 根据id查询业务信息
     * @return 如果参数为空或者查询不到数据,返回空列表

* O 中的中、英文业务名来自 BILLING_BUSINESS 表
*/
public List getBusinessesByIds(List businessIds) { return billingBusinessDAO.getBusinessbyIds(businessIds); } }
BillingBusinessManagerUnitTest类:

//引入包忽略...
public class BillingBusinessManagerUnitTest extends MockitoTestContext {
@InjectMocks
private BillingBusinessManager sv;
@Mock
private BillingBusinessDAO billingBusinessDAO;
@Test
public void testGetBusinessesByIds() {
List<BusinessVO> expected = ListUtil.toList(new BusinessVO(1l, "a", "b"));
//简洁的语法如下所示
when(billingBusinessDAO.getBusinessbyIds(anyListOf(Long.class))).thenReturn(expected);
List<Long> businessIds = ListUtil.toList(TestConstants.BUSINESS_ID_HTTP_WEB_CACHE);
List<BusinessVO> actual = sv.getBusinessesByIds(businessIds);
Assert.assertEquals(expected, actual);
}
}

原文转自:http://www.uml.org.cn/Test/201407281.asp