|
|
|
|
|
<!DOCTYPE HTML>
|
|
|
<html lang="" >
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
|
<title>三、单元测试 · GitBook</title>
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
|
<meta name="description" content="">
|
|
|
<meta name="generator" content="GitBook 3.2.3">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="gitbook/style.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="gitbook/gitbook-plugin-prism/prism.css">
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="styles/website.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<meta name="HandheldFriendly" content="true"/>
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
|
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
|
|
|
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
|
|
|
|
|
|
|
|
<link rel="next" href="安全规约.html" />
|
|
|
|
|
|
|
|
|
<link rel="prev" href="异常日志/其他.html" />
|
|
|
|
|
|
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
<div class="book">
|
|
|
<div class="book-summary">
|
|
|
|
|
|
|
|
|
<div id="book-search-input" role="search">
|
|
|
<input type="text" placeholder="Type to search" />
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<nav role="navigation">
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="summary">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="1.1" data-path="./">
|
|
|
|
|
|
<a href="./">
|
|
|
|
|
|
|
|
|
前言
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2" >
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
|
一、编程规约
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="1.2.1" data-path="编程规约/命名风格.html">
|
|
|
|
|
|
<a href="编程规约/命名风格.html">
|
|
|
|
|
|
|
|
|
(一)命名风格
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.2" data-path="编程规约/常量定义.html">
|
|
|
|
|
|
<a href="编程规约/常量定义.html">
|
|
|
|
|
|
|
|
|
(二)常量定义
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.3" data-path="编程规约/代码格式.html">
|
|
|
|
|
|
<a href="编程规约/代码格式.html">
|
|
|
|
|
|
|
|
|
(三)代码格式
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.4" data-path="编程规约/OOP规范.html">
|
|
|
|
|
|
<a href="编程规约/OOP规范.html">
|
|
|
|
|
|
|
|
|
(四)OOP规范
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.5" data-path="编程规约/集合处理.html">
|
|
|
|
|
|
<a href="编程规约/集合处理.html">
|
|
|
|
|
|
|
|
|
(五)集合处理
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.6" data-path="编程规约/并发处理.html">
|
|
|
|
|
|
<a href="编程规约/并发处理.html">
|
|
|
|
|
|
|
|
|
(六)并发处理
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.7" data-path="编程规约/控制语句.html">
|
|
|
|
|
|
<a href="编程规约/控制语句.html">
|
|
|
|
|
|
|
|
|
(七)控制语句
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.2.8" data-path="编程规约/注释规约.html">
|
|
|
|
|
|
<a href="编程规约/注释规约.html">
|
|
|
|
|
|
|
|
|
(八)注释规约
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.3" >
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
|
二、异常日志
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="1.3.1" data-path="异常日志/异常处理.html">
|
|
|
|
|
|
<a href="异常日志/异常处理.html">
|
|
|
|
|
|
|
|
|
(一)异常处理
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.3.2" data-path="异常日志/日志规约.html">
|
|
|
|
|
|
<a href="异常日志/日志规约.html">
|
|
|
|
|
|
|
|
|
(二)日志规范
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.3.3" data-path="异常日志/其他.html">
|
|
|
|
|
|
<a href="异常日志/其他.html">
|
|
|
|
|
|
|
|
|
(三)其他
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter active" data-level="1.4" data-path="单元测试.html">
|
|
|
|
|
|
<a href="单元测试.html">
|
|
|
|
|
|
|
|
|
三、单元测试
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.5" data-path="安全规约.html">
|
|
|
|
|
|
<a href="安全规约.html">
|
|
|
|
|
|
|
|
|
四、安全规约
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.6" >
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
|
五、MySQL数据库
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="1.6.1" data-path="MySQL数据库/建表规约.html">
|
|
|
|
|
|
<a href="MySQL数据库/建表规约.html">
|
|
|
|
|
|
|
|
|
(一)建表规约
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.6.2" data-path="MySQL数据库/索引规约.html">
|
|
|
|
|
|
<a href="MySQL数据库/索引规约.html">
|
|
|
|
|
|
|
|
|
(二)索引规约
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.6.3" data-path="MySQL数据库/SQL语句.html">
|
|
|
|
|
|
<a href="MySQL数据库/SQL语句.html">
|
|
|
|
|
|
|
|
|
(三)SQL语句
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.6.4" data-path="MySQL数据库/ORM映射.html">
|
|
|
|
|
|
<a href="MySQL数据库/ORM映射.html">
|
|
|
|
|
|
|
|
|
(四)ORM映射
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.7" >
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
|
六、工程结构
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="1.7.1" data-path="工程结构/应用分层.html">
|
|
|
|
|
|
<a href="工程结构/应用分层.html">
|
|
|
|
|
|
|
|
|
(一)应用分层
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.7.2" data-path="工程结构/二方库依赖.html">
|
|
|
|
|
|
<a href="工程结构/二方库依赖.html">
|
|
|
|
|
|
|
|
|
(二)二方库依赖
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.7.3" data-path="工程结构/服务器.html">
|
|
|
|
|
|
<a href="工程结构/服务器.html">
|
|
|
|
|
|
|
|
|
(三)服务器
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.8" data-path="版本历史.html">
|
|
|
|
|
|
<a href="版本历史.html">
|
|
|
|
|
|
|
|
|
附1:版本历史
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li class="chapter " data-level="1.9" data-path="本手册专有名词.html">
|
|
|
|
|
|
<a href="本手册专有名词.html">
|
|
|
|
|
|
|
|
|
附2:本手册专有名词
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="divider"></li>
|
|
|
|
|
|
<li>
|
|
|
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
|
|
Published with GitBook
|
|
|
</a>
|
|
|
</li>
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="book-body">
|
|
|
|
|
|
<div class="body-inner">
|
|
|
|
|
|
|
|
|
|
|
|
<div class="book-header" role="navigation">
|
|
|
|
|
|
|
|
|
<!-- Title -->
|
|
|
<h1>
|
|
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
|
|
<a href="." >三、单元测试</a>
|
|
|
</h1>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="page-wrapper" tabindex="-1" role="main">
|
|
|
<div class="page-inner">
|
|
|
|
|
|
<div id="book-search-results">
|
|
|
<div class="search-noresults">
|
|
|
|
|
|
<section class="normal markdown-section">
|
|
|
|
|
|
<h2 id="三、单元测试">三、单元测试</h2>
|
|
|
<ol>
|
|
|
<li>【强制】好的单元测试必须遵守AIR原则。
|
|
|
<br><span style="color:orange">说明</span>:单元测试在线上运行时,感觉像空气(AIR)一样并不存在,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。 <ul>
|
|
|
<li>A:Automatic(自动化) </li>
|
|
|
<li>I:Independent(独立性) </li>
|
|
|
<li>R:Repeatable(可重复) </li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>【强制】单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.out来进行人肉验证,必须使用assert来验证。 </li>
|
|
|
<li>【强制】保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。 <br><span style="color:red">反例</span>:method2需要依赖method1的执行,将执行结果作为method2的输入。 </li>
|
|
|
<li>【强制】单元测试是可以重复执行的,不能受到外界环境的影响。
|
|
|
<br><span style="color:orange">说明</span>:单元测试通常会被放到持续集成中,每次有代码check in时单元测试都会被执行。如果单测对外部环境(网络、服务、中间件等)有依赖,容易导致持续集成机制的不可用。 <br><span style="color:green">正例</span>:为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在测试时用spring 这样的DI框架注入一个本地(内存)实现或者Mock实现。 </li>
|
|
|
<li>【强制】对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,一般是方法级别。
|
|
|
<br><span style="color:orange">说明</span>:只有测试粒度小才能在出错时尽快定位到出错位置。单测不负责检查跨类或者跨系统的交互逻辑,那是集成测试的领域。 </li>
|
|
|
<li>【强制】核心业务、核心应用、核心模块的增量代码确保单元测试通过。
|
|
|
<br><span style="color:orange">说明</span>:新增代码及时补充单元测试,如果新增代码影响了原有单元测试,请及时修正。 </li>
|
|
|
<li>【强制】单元测试代码必须写在如下工程目录:src/test/java,不允许写在业务代码目录下。
|
|
|
<br><span style="color:orange">说明</span>:源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。 </li>
|
|
|
<li>【推荐】单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%
|
|
|
<br><span style="color:orange">说明</span>:在工程规约的应用分层中提到的DAO层,Manager层,可重用度高的Service,都应该进行单元测试。 </li>
|
|
|
<li>【推荐】编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。 <ul>
|
|
|
<li>B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。 </li>
|
|
|
<li>C:Correct,正确的输入,并得到预期的结果。 </li>
|
|
|
<li>D:Design,与设计文档相结合,来编写单元测试。 </li>
|
|
|
<li>E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果。 </li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>【推荐】对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的,或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。 <br><span style="color:red">反例</span>:删除某一行数据的单元测试,在数据库中,先直接手动增加一行作为删除目标,但是这一行新增数据并不符合业务插入规则,导致测试结果异常。 </li>
|
|
|
<li>【推荐】和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者对单元测试产生的数据有明确的前后缀标识。 <br><span style="color:green">正例</span>:在RDC内部单元测试中,使用RDC<em>UNIT_TEST</em>的前缀标识数据。 </li>
|
|
|
<li>【推荐】对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而书写不规范测试代码。 </li>
|
|
|
<li>【推荐】在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例(UC)。 </li>
|
|
|
<li>【推荐】单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项目提测前完成单元测试。 </li>
|
|
|
<li>【参考】为了更方便地进行单元测试,业务代码应避免以下情况:<ul>
|
|
|
<li>构造方法中做的事情过多。 </li>
|
|
|
<li>存在过多的全局变量和静态方法。 </li>
|
|
|
<li>存在过多的外部依赖。 </li>
|
|
|
<li>存在过多的条件语句。
|
|
|
<br><span style="color:orange">说明</span>:多层条件语句建议使用卫语句、策略模式、状态模式等方式重构。 </li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>【参考】不要对单元测试存在如下误解: <ul>
|
|
|
<li>那是测试同学干的事情。本文是开发手册,凡是本文内容都是与开发同学强相关的。</li>
|
|
|
<li>单元测试代码是多余的。汽车的整体功能与各单元部件的测试正常与否是强相关的。 </li>
|
|
|
<li>单元测试代码不需要维护。一年半载后,那么单元测试几乎处于废弃状态。 </li>
|
|
|
<li>单元测试与线上故障没有辩证关系。好的单元测试能够最大限度地规避线上故障。 </li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
</ol>
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
<div class="search-results">
|
|
|
<div class="has-results">
|
|
|
|
|
|
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
|
|
|
<ul class="search-results-list"></ul>
|
|
|
|
|
|
</div>
|
|
|
<div class="no-results">
|
|
|
|
|
|
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="异常日志/其他.html" class="navigation navigation-prev " aria-label="Previous page: (三)其他">
|
|
|
<i class="fa fa-angle-left"></i>
|
|
|
</a>
|
|
|
|
|
|
|
|
|
<a href="安全规约.html" class="navigation navigation-next " aria-label="Next page: 四、安全规约">
|
|
|
<i class="fa fa-angle-right"></i>
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
var gitbook = gitbook || [];
|
|
|
gitbook.push(function() {
|
|
|
gitbook.page.hasChanged({"page":{"title":"三、单元测试","level":"1.4","depth":1,"next":{"title":"四、安全规约","level":"1.5","depth":1,"path":"安全规约.md","ref":"安全规约.md","articles":[]},"previous":{"title":"(三)其他","level":"1.3.3","depth":2,"path":"异常日志/其他.md","ref":"异常日志/其他.md","articles":[]},"dir":"ltr"},"config":{"gitbook":"*","theme":"default","variables":{},"plugins":["book-summary-scroll-position-saver","github","prism","-sharing","-highlight"],"pluginsConfig":{"github":{"url":"https://github.com/alibaba/p3c"},"book-summary-scroll-position-saver":{},"prism":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"styles":{"website":"styles/website.css"}},"file":{"path":"单元测试.md","mtime":"2018-01-13T07:52:52.584Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2018-01-15T14:41:43.583Z"},"basePath":".","book":{"language":""}});
|
|
|
});
|
|
|
</script>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook.js"></script>
|
|
|
<script src="gitbook/theme.js"></script>
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-book-summary-scroll-position-saver/book-summary-scroll-position-saver.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-github/plugin.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-search/search.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
</html>
|
|
|
|