1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > junit 单元测试 规范

junit 单元测试 规范

时间:2020-12-26 07:28:16

相关推荐

junit 单元测试 规范

一、测试准则

必须遵守AIR原则

A(自动化):单元测试应该是全自动执行的,并且非交互。单元测试中不准使用System.out来进行人工验证,必须使用assert来验证。I (独立性):单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。

**反例:**method2需要依赖method1的执行,将执行结果作为method2的输入。R(可重复):单元测试是可以重复执行的,不能受到外界环境的影响。

保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,一般是方法级别。

核心业务、核心应用、核心模块的增量代码必须确保单元测试通过。

说明:新增代码及时补充单元测试,如果新增代码影响了原有单元测试,请及时修正。

单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%。

**说明:**在工程规约的应用分层中提到的DAO层,Manager层,可重用度高的Service,都应该进行单元测试。

对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的,或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。

**反例:**删除某一行数据的单元测试,在数据库中,先直接手动增加一行作为删除目标,但是这一行新增数据并不符合业务插入规则,导致测试结果异常。

确保测试与时间无关,尽可能避免使用可能过期的数据;此类数据应手动或以编程方式刷新。

在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例。

单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项目提测前完成单元测试。

不要在单元测试中打印任何内容。

不要在单元测试类的构造函数中初始化;使用@Before方法代替。

在测试类中,不要声明方法抛出任何特定类型的异常

说明:声明它们抛出一种特定类型的异常的测试方法非常脆弱,因为每当被测试的方法发生变化时,都必须对其进行更改。

不要在单元测试中使用Thread.sleep

不要对单元测试存在如下误解:

那是测试同学干的事情。单元测试代码是多余的。单元测试代码不需要维护。一年半载后,那么单元测试几乎处于废弃状态。单元测试与线上故障没有辩证关系。好的单元测试能够最大限度地规避线上故障。

二、结构规范

单元测试代码必须写在如下工程目录:src/test/java,不允许写在业务代码目录下。

**说明:**源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。

测试类命名规范:被测试的业务+Test、被测试的接口+Test、被测试的类+Test

正例:例如当前的测试类为MessageLog该类的测试用例应为MessageLogTest。

测试用例命名规范:测试用例命名应做到简洁全面,可描述。避免使用test1、test2没有含义的名称。其次需要有必要的函数方法注释。

推荐的命名法:MethodName_StateUnderTest_ExpectedBehavior

MethodName 被测试的方法、一组方法或者一组类。StateUnderTest 测试进行的条件以及状态。ExpectedBehavior 在测试场景指定的条件下,你对被测试方法行为的预期。

正例:sum_simpleValues_calculated

这种方式可以在不用看方法细节的情况明白方法要做的事情。同时,还建议在MethodName前加test,这样方便在ide中快速搜索到你要找的代码

测试开发包,测试包保持和被测包一致。

三、编码原则

编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。

B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。C:Correct,正确的输入,并得到预期的结果。D:Design,与设计文档相结合,来编写单元测试。E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果。

和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者对单元测试产生的数据有明确的前后缀标识。

正例:在RDC内部单元测试中,使用RDCUNIT_TEST的前缀标识数据。

对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而书写不规范测试代码。

为了更方便地进行单元测试,业务代码应避免以下情况:

构造方法中做的事情过多。存在过多的全局变量和静态方法。存在过多的外部依赖。存在过多的条件语句。

说明:多层条件语句建议使用卫语句、策略模式、状态模式等方式重构。

编写测试时考虑语言环境,例如:

对于下面的日期测试。

Date date = DateFormat.getInstance ().parse ("dd/mm/yyyy");

但是该代码不能在使用不同语言环境的机器上工作。因此,下面代码将会好很多

Calendar cal = Calendar.getInstance ();Cal.set (yyyy, mm-1, dd);Date date = Calendar.getTime ();

利用JUnit的assert / fail方法和异常处理获得干净的测试代码

反例

public void exampleTest () {try {// do some test} catch (SomeApplicationException e) {fail ("Caught SomeApplicationException exception");}}

正例

public void exampleTest () throws SomeApplicationException {// do some test}

说明:JUnit自动捕获异常。它认为未捕获的异常是错误

使用各种断言方法以一种更简单的方式表达你的意图。

反例

assert (creds == 3);

正例

assertEquals ("The number of credentials should be 3", 3, creds);

说明:上面的示例对代码阅读器有用得多。如果断言失败,它将为测试人员提供更多信息。使用assertSame()测试两个引用指向同一个对象。使用assertEquals()测试两个对象是相等的。

不要假设测试用例中测试的运行顺序,不应该假定将以任何特定顺序调用测试。

考虑以下代码段:

public class SomeTestCase extends TestCase {public SomeTestCase (String testName) {super (testName);}public void testDoThisFirst () {...}public void testDoThisSecond () {}}

说明:在此示例中,不确定使用反射时JUnit将以任何特定顺序运行这些测试。因此,除非将测试设计为按任何顺序运行,否则在不同的平台和Java VM上运行测试可能会产生不同的结果。避免时间耦合将使测试用例更加健壮,因为顺序的更改不会影响其他测试。如果测试是耦合的,则可能很难发现由次要更新导致的错误。

不要使用测试用例构造函数来设置测试用例。

反例:

public class SomeTest extends TestCasepublic SomeTest (String testName) {super (testName);// Perform test set-up}}

不要从文件系统上的硬编码位置加载数据

反例

public void setUp () {FileInputStream inp ("C:\\TestData\\dataSet1.dat");}

说明:上面的代码依赖于C:\ TestData路径中的数据集。考虑在两种情况下是不正确的:1.测试人员没有空间将测试数据存储在C:上而是将其存储在另一个磁盘上;2.这些测试可能是在其他平台(例如Unix)上运行的。

常见的方法将测试放在与源代码相同的位置。如:

public void setUp () {FileInputStream inp ("dataSet1.dat");}

使用最合适的断言方法

JUnit的断言方法有许多,应该了解最新版本的JUnit中的断言,并使用最合适的断言来获得最具可读性的测试代码。例如:

使用assertTrue(classUnderTest.methodUnderTest())而不是assertEquals(true, classUnderTest.methodUnderTest())。使用assertEquals(expectedReturnValue, classUnderTest.methodUnderTest())而不是assertTrue(classUnderTest.methodUnderTest().equals(expectedReturnValue))。使用assertEquals(expectedCollection, classUnderTest.getCollection())而不是声明集合的大小和集合的每个成员。

四、如何测试dao层

对于dao的测试,我们应根据实际需要在测试类中继承 AbstractTransactionalJUnit4SpringContextTests 和AbstractJUnit4SpringContextTests中 的一个类。

AbstractTransactionalJUnit4SpringContextTests提供了数据库自动回滚,也就是说测试前和测试后数据库是一样的。AbstractJUnit4SpringContextTests不提供数据库自动回滚,测试会破坏数据库。

如果你觉得每个测试用例都要配置spring环境很麻烦的话,可以先建立一个父类:BasicTest,然后继承该类即可。

如果你使用的是springboot + junit,那么测试环境可以这样配置

@RunWith(SpringRunner.class)@SpringBootTest(classes = DemoApplication.class)public class BasicTest {}

RunWith中如果要使用SpringRunner你的junit版本需要在4.12以上,若在4.12以下,您应该这样写:@RunWith(SpringJUnit4ClassRunner.class),更多参数可自行百度。SpringBootTest中classes的值为springboot的启动项,这里也可以省略。

理想情况下,测试应使用与应用程序相同的配置。是可能会有一些仅针对单元测试的更改。要解决此问题,您应该创建另一个特定于测试的配置文件,并添加/覆盖特定于测试的配置更改。

例如在主应用程序中,如果是配置文件application-context.xml,则应创建另一个文件application-context-test.xml,并将原始配置导入到该文件的顶部。然后覆盖您可能需要的bean定义。

application-context-test.xml

<beans ····><import resource="application-context.xml"/><bean>要覆盖的bean</bean></beans>

五、如何测试controller层

.验证HTTP请求匹配

我们应测试控制器应响应某些URL,HTTP方法和内容类型,即对控制器的请求方式,请求路径,参数类型等进行验证,保证控制器能准确的拦截非法数据。

输入验证

假如实体类用了@NotNUll来拒绝null值,像这样

public class UserResource {@NotNullprivate final String name;@NotNullprivate final String email;}

此时就需要对控制器中的参数进行校验,同时如果控制器对参数添加了一些注解,如@Valid,也需要进行测试。

业务逻辑测试

即我们需要测试方法是否按预期方式调用了业务逻辑。

验证输出序列化

调用业务逻辑后我们希望控制器将结果映射到JSON字符串并将其包含在HTTP响应中,即判断返回的数据是否为我们期望的数据。

异常验证测试

通常,如果发生异常,则控制器应返回某个HTTP状态。400,如果请求有问题,500,如果出现异常,依此类推。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。