分享干货 ——Java如何写一个好的单元测试以及一些测试常用的策略

单元测试的目的?

       单元测试是编写测试代码,用以检测特定的、明确的、细颗粒的功能!严格来说,单元测试只针对功能点进行测试,不包括对业务流程正确性的测试。现在一般公司都会进行业务流程的测试,这也要求测试人员需要了解需求!测试人员也不好过啊~~

       目前开发所用的单元是Junit框架,在大多数java的开发环境中已经集成,可以方便开发自己调用!

注意:单元测试不仅仅是要保证代码的正确性,一份好的单元测试报告,还要完整地记录问题的所在和缺陷以及正确的状态,方便后面代码的修复,重构和改进。

单元测试做什么?

一般来说,一份单元测试主要包括以下几个方面:

1.接口功能性测试: 接口功能的正确性,即保证接口能够被正常调用,并输出有效数据!

1)是否被顺利调用

2)参数是否符合预期

2.局部数据结构测试:保证数据结构的正确性

1)变量是否有初始值或在某场景下是否有默认值

2)变量是否溢出

3.边界条件测试:测试

1、变量无赋值(null)

2、变量是数值或字符

3、主要边界:最大值,最小值,无穷大

4、溢出边界:在边界外面取值+/-1

5、临近边界:在边界值之内取值+/-1

6、字符串的边界,引用"变量字符"的边界

7、字符串的设置,空字符串

8、字符串的应用长度测试

9、空白集合

10、目标集合的类型和应用边界

11、集合的次序

12、变量是规律的,测试无穷大的极限,无穷小的极限

4.所有独立代码测试:保证每一句代码,所有分支都测试完成,主要包括代码覆盖率,异常处理通路测试

语句覆盖率:每个语句都执行到了

判定覆盖率:每个分支都执行到了

条件覆盖率:每个条件都返回布尔

路径覆盖率:每个路径都覆盖到了

5.异常模块测试,后续处理模块测试:是否包闭当前异常或者对异常形成消化,是否影响结果!

Java的单元测试Junit4

1.业务流程的一般是按照需求的预期效果,跑完整个业务流程,包括以前开发的流程

是否实现了预期

是否影响到了以前的流程

全流程是否顺利

数据是否符合预期

2.代码测试:

// 全局只会执行一次,而且是第一个运行@BeforeClass // 在测试方法运行之前运行@Before // 测试方法@Test // 在测试方法运行之后允许@After // 全局只会执行一次,而且是最后一个运行@AfterClass // 忽略此方法@Ignore 

JUNIT4是以org.junit为框架进行的测试,以注解的形式来识别代码中需要测试的方法!

注意:对于每一个测试,我们都应该保持独立测试,以确保测试结果是有意义的。在程序中,经常会出现,当测试完一个方法后,其参数已经被系统保持或持久化下来。无疑会造成下一次的测试测试数据或者状态的不合理性!为了解决问题,对于此类场景,我们的测试代码必须具备初始化和收尾的能力。也即是@Before和@After的意义所在!@Before可以在测试之前准备需要的数据@After可以在@Test方法运行之后把测试数据删除同理@AfterClass和BeforeClass即是为了满足测试中,那些体积非常大,但只要一次初始化的代码块!

3.断言测试与及常用断言:

assertEquals:

Assert.assertEquals("此处输出提示语", 5, result);

解析:"此处输出提示语":为错误时你个人想要输出的错误信息;5:是指你期望的值;result:是指你调用程序后程序输出给你的结果

有些异常是我们预期的,不希望测试抛异常, 那又该怎么做呢

@Test(expectedExceptions = NullPointerException.class)  

解析:在注解的时候添加expectedExceptions 为忽略此异常

超时设置:

@Test(timeout  =   5000 )

期望出现异常,如果出现该异常则成功,否则测试失败

@Test(expected  =  XXXXException. class)

用户方法之上,被注解的方法会被成功需忽略

@Ignore() 

判断测试失败

fail("Not yet implemented")

解析:放在方法中,如果我顺利地执行,我就报失败出来。就是说按道理不应该执行到这里的,但是偏偏执行了,说明程序有问题

断言结果是真的或者结果是假的

// 断言结果是真的Assert.assertTrue("msg",boolean)// 断言结果是假的Assert.assertFalse("msg",boolean)

解析:如果和预期一样为true则成功,否则失败输出msg;如果和预期一样为false则成功,否则失败并输出

断言结果是null

assertNull("msg",boolean)与assertNotNull("msg",boolean)

解析:assertNull与assertNotNull可以验证所测试的对象是否为空或不为空,如果和预期的相同则测试成功,否则测试失败!

4.主要常用方法

断言列表:

断言列表

5.运行器指定?

       单元测试中,每个类都是由于JUNIT4框架中的Runner运行器来执行的。一般情况下,在没有指定运行器的时候,是由系统默认选择(TestClassRunner)的运行器执行。包括类中的所有方法都是由该运行器负责调用和执行。当我们需要指定的时候,则通过类级别注解 @Run Wirth(xxxxxx)进行选择,一般是根据不同类型选择不同执行器,可以提高效率也可以应用于某种特殊场景!

6.参数化测试?

 @RunWith(Parameterized. class )

 public class TestParam {

      private static Calculator calculator = new Calculator(); //需要测试的类

      private int param; 

      private int result;

      @Parameters

      public static Collection data(){

        return Arrays.asList(new Object[][] {{11, 17} , {xx1, xx}});

      } 

      //有参构造,在实例的时候实现参数初始化

      public TestParam(int param, int result){

        this .param = param;

        this .result = result;

      } 

      @Test

      public void TestResult(){

       calculator.square(param);

       assertEquals(result, calculator.getResult()); 

      }  } 

解说:参数化测试的目标是为了一次性完成同类型测试,将相同类型的数据按照一定的顺序批量地传入测试方法,并得出结论!其本质是一个批量的化的操作,只是为了方便我们测试而进行了封装。我们只有提供测试的方法以及按照一定的顺序进行设置则可以。

进行类注解:@RunWith(Parameterized.class),为了测试类指定一个ParameterizedRunner运行器

进行参数设置:将测试结果和期望结果,以每一组都是一个数组的形式存放以形成二维数组,转化为list返回并注解。

参数初始化:设置测试方法要入参的参数,并按照"参数设置"的顺序利用构造方法进行初始化的赋值!

测试调用:写一个测试方法进行调用,将参数传递到要测试的类的方法中并返回数据

注意:参数化测试需要创建一单独用于测试的测试类。并定义两个变量用于接受测试结果和预期目标。数据存放以二维数组的方式,两个为一组。接着便是通过构造方法进行数据初始化。构造方法入参的顺序要和二维数组中国每一组存放的数据顺序保持一致。

7.打包测试

@RunWith(Suite. class )@Suite.SuiteClasses( {CalculatorTest. class ,SquareTest. class } )public   class  AllCalculatorTests  {

    //to do something;} 

解析:将有需要的一起执行程序一起打包,然后执行运行器:Suite. class解析:我们把需要打包一起测试的测试类作为参数传递给该注解。然后直接运行代码,此处的测试类可以直接设置为空,只需要添加注解便OK;


测试策略

1、 功能测试

方法步骤:执行测试用例,补充场景测试以及异常情况测试。(边界值法:使用于包含数值的输入框;//等价类划分法:输入数据类型取用有代表性的数据;场景法:一轮测试后,对于有关联的页面和数据进行场景模拟测试)

       功能测试一般需要根据编写的测试用例,执行测试用例,执行的过程中提交缺陷;功能测试一般至少会有两轮,遇到比较麻烦的项目甚至会有三到四轮,而每一轮测试都有其侧重点,比如第一轮功能测试可能会重点关注先关注每个单独的模块的测试,其次会关注功能,关注功能的时候也需要区分,哪些是主要功能,首先需要保证主流程没有阻塞情况,才能进一步测试其他的功能。

2、 易用性测试(用户体验:自适应、页面从属关系)

方法步骤:功能测试完毕使用新账号测试或是重新登录测试。(针对使用人群是否有新手引导、流程是否简单易懂)

3、 兼容性测试(内部和外部兼容性)

方法步骤:最少测试2款安卓以及2款iPhone手机。

       兼容性测试会在系统测试结束以后开展,若是app需要兼容主流设备;若是网页,则需要兼容主流浏览器。主要需要考虑的包括:1)操作系统兼容性,2)不同浏览器的兼容性,3)不同分辨率下的兼容性,4)软件本身向前向后兼容,5)软件与相关软件的兼容性。

4、 性能测试(响应能力、压力测试、负载测试)

方法步骤:--负载测试;(手机端测试使用代理,使用Jmeter工具,测试服务端性能)

          --小程序进行性能数据监测(微信自带功能,监测:CPU、内存、页面切换/启动/初次渲染耗时、帧率、数据缓存),app可使用Charles工具查看CPU,内存的占用,耗电量、流量的情况。

CPU说明:CPU占用率低于20%表示为最佳状态,如果CPU占用在20%~60%之间表示资源使用比较稳定,如果CPU占用率在60%~80%之间表示资源使用饱和,如果CPU占用率超过80%属于性能的瓶颈,必须尽快进行资源调整与优化。

5、 安全性测试(软件权限、安装卸载、数据、通讯、人机接口安全)

方法步骤:使用Fiddler抓包登录的用户名和密码。(可以抓包成功则需改进安全性能)

          小程序安全性测试可不进行。

6、 交叉事件测试(冲突测试)

方法步骤:模拟手机的多种特殊场景测试。(后台运行、锁屏、接打电话、收发短信等,注意:app或小程序后台运行后再次使用是否受影响,后台运行时间可延长至手机锁屏)

前后台切换测试要点:(1)锁屏、中断、关闭进程后切换;

(2)出现必须处理的提示框后,切换到后台,再切换回来,检查提示框是否还存在,有时候会出现应用自动跳过提示框的缺陷。

(3)对于有数据交换的页面,每个页面都必须要进行前后台切换、锁屏的测试,这种页面最容易出现崩溃。

7、 网络测试

方法步骤:测试2G/3G/4G网络下(可charles模拟),app或小程序运行情况。

弱网测试

方法步骤:使用charles模拟弱网环境,完整操作一遍小程序或是app,观察流畅度等。

(可模拟场景测试,注意:打开代理模拟时,该软件自动关闭,影响测试程序的运行)

8、 app安装、卸载、更新测试(安装、运行、卸载、更新、操作前后对资源的占用情况)

方法步骤:正常和异常情境下安装、卸载、更新测试。

9、UI测试(导航测试、图形测试、内容测试;用户友好性、人性化、易操作性测试)

方法步骤:查看界面布局、风格,查看文字、图片。

不积跬步,无以至千里;不积小流,无以成江海。点点滴滴终将成就最好的你!我这也有一个平时交流学习的扣群:164549428 如果这篇文章帮到了你,欢迎点赞和关注

你可能感兴趣的:(分享干货 ——Java如何写一个好的单元测试以及一些测试常用的策略)