单测的心得体会

简介: 单测是规范的软件开发流程中的必不可少的环节之一。再伟大的程序员也难以避免自己不犯错,不写出有BUG的程序。单测就是用来检测BUG的。Java阵营中,JUnit和TestNG是两个知名的单测框架。不过,用Java写单测实在是很繁琐,mock各种参数需要大量时间,所以单测试往往被认为鸡肋,会耗费很多时间。最近实习的过程中遇到一些坑,发现养成一个良好的单测习惯对于系统化开发是很有必要的。

背景介绍:

目前开发的项目基本都是基于dubbo进行远程服务调用。由于自身项目比较复杂(主要在于内部实体类之间转换过于复杂以及系统依赖服务较多导致调用链过长),造成自身无法简单的使用postman这些工具进行接口测试,且项目过大 内部开发往往需要将本地代码push上去再容器部署,一个小小的bug修改部署成本极大(往往要十五分钟)。最近写的第二个项目由于传参NPE 问题进行了十多次修改,可想而知部署成本极大。由此懂得单测的必要性。

我们部门主要使用spook+grooy进行单元测试。简单介绍如何使用grooy和spook实现简洁单元测试以及今天写单测遇到的一个坑。

原先代码中使用junit4配合Mockito 进行测试 发现对于特定条件判断往往代码量大,而且冗余。观摩以前的代码往往发现其中大部份测试都是对结果非空判断,如果遇到多条件的情况想要具体结果需要大量when() thenReturn();

spook进行单测好处是模版简单,代码简洁,对于特定数据可以清晰判断。

使用spook进行单测主要模版为 expect-where , when-then-thrown, setup-given-when-then[-where]

比如:这是最近写的一个例子可以简单的看作setup-given-when-then[-where] 这种形式

def "testFXSupplierName"(){
        setup:
        def shopClient = Mock(ShopClient)
        OrderSearchServiceImpl service = new OrderSearchServiceImpl()
        service.shopClient = shopClient
        when:
        List<OrderBO> orderBOList=[new OrderBO(xxxx:new xxxx(extra: ["xxxx":2],tags:["xxxx":true]))]
        OrderPageBO orderPageBO=new OrderPageBO(list: orderBOList)
        shopClient.queryShopMetaInfos(_) >> new ShopMetaInfosQueryResult(shopMetaInfos:[new ShopMetaInfo(xxxx: 2,xxxxx: "test")])
        service.supplierOrderPutSupplierName(orderBOList)
        then:
        orderPageBO.getList().get(0).getOrderMain().getExtra().get("xxxx")=="test"
    }

setup:建立要mock的实体类

given:建立返回的对象实体

when:将given中建立的对象实体赋值mock实体方法调用或进行方法调用

then:结果比较

where:多条件添加

这也是一个例子

@Unroll()  //这边是标记信息可以打标
    def 'presell_normal'() {
        setup:
        def tradeSku = new TradeSku(preSale: presell)
        def goods = new Goods(num: num, price: price)
        def icGoods = new IcGoods(depositType: depositType,
                                                        depositRatio: depositeRatio,
                                                        deposit: deposite)
        tradeSku.setIcGoodsPreSaleInfo(icGoods)
        expect:
        def value = TradeGroupConvertUtil.preSell(tradeSku, goods)
        value == res
        where:
        presell << [1, 1, 1, 1, 1, 1, 1, 1, 0, 0]
        depositType << [0, 0, 0, 0, 1, 1, 1, 1, 0, 0]
        depositeRatio << [40, 20, 30, 80, 1, 2, 3, 4, 0, 0]
        num << [1, 2, 3, 4, 1, 2, 3, 4, 0, 0]
        price << [100, 100, 100, 100, 100, 100, 100, 100, 0, 0]
        deposite << [40, 20, 30, 80, 1, 2, 200, 4, 0, 0]
        res << ['40', '40', '90', '320', '1', '4', '300', '16', '', '']
    }

对于异常场景可以使用这种

def 'getpreSell_error'() {
        setup:
        def tradeSku = new TradeSku(preSale: presell)
        def goods = new Goods(num: num, price: price)
        def icGoods = new IcGoods(depositType: depositType,
                                                        depositRatio: depositeRatio,
                                                        deposit: deposite)
        tradeSku.setIcGoods(icGoods)
        when:
        TradeGroupConvertUtil.preSell(tradeSku, goods)
        then:
        def ex = thrown(Exception)
        expect:
        ex.message == errorMessage
        where:
        presell << [1, 1, 1, 1, 1, 1,]
        depositType << [0, 0, 0, 0, 1, 1,]
        depositeRatio << [-12, 0, 100, 120, 200, 300]
        num << [1, 2, 3, 4, 1, 2]
        price << [100, 100, 100, 100, 100, 100]
        deposite << [40, 20, 30, 80, null, 0]
        errorMessage <<
        ["xxxxxx异常信息", "xxxxxx异常信息", "xxxxxx异常信息", "xxxxxx异常信息", "xxxxxx异常信息", "xxxxxx异常信息"]

    }

这边就是主要使用的三个例子,需要异常抛出的情况不能和正常情况一起使用。需要区分为两个测试方法。

遇到的坑:

今晚写一个单测,仿照项目中原先的老代码写的。对于代码中mock使用的是Mockito注解方式,发现使用注解方式可以获取到这个类但是对于使用grooy 语法进行方法调用赋值一直为null但是注入的类不为空否则会报NPE问题。后来通过重新使用mock()注入解决这个问题。得出结论使用何种方式注入就要使用何种方式赋值。

相关文章
|
3月前
|
敏捷开发 安全 测试技术
【软件设计师备考 专题 】如何编写有效的测试报告
【软件设计师备考 专题 】如何编写有效的测试报告
79 0
|
12月前
|
Java 测试技术 Python
关于如何写自动化测试框架,看完本章你会有收获
关于如何写自动化测试框架,看完本章你会有收获
100 0
|
jenkins 测试技术 持续交付
初学者回归测试的基础
回归测试 是一种用于测试产品的增量验证技术。它旨在验证在正在进行的开发过程中,产品的新变化没有破坏现有功能。为每个新功能添加新的测试用例可确保回归测试成功。
114 0
|
前端开发
项目开发自测注意点
项目开发自测注意点
项目开发自测注意点
最近的踩坑分享 | 技术文档和需求拆解
最近的踩坑分享 | 技术文档和需求拆解
103 0
最近的踩坑分享 | 技术文档和需求拆解
|
测试技术
软件测试面试题:手工测试与自动测试有哪些区别?
软件测试面试题:手工测试与自动测试有哪些区别?
95 0
|
自然语言处理 Java 测试技术
告别祈祷式编程|单元测试在项目里的正确落地姿势
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Jav...
160 1
|
XML Java 测试技术
告别加班/解放双手提高单测覆盖率之Java 自动生成单测代码神器推荐
很多公司对分支单测覆盖率会有一定的要求,比如 单测覆盖率要达到 60% 或者 80%才可以发布。 有时候工期相对紧张,就优先开发功能,测试功能,然后再去补单元测试。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e9e8ea7d35ca4830bce7929774471207.jpg) 但是编写单元测试又比较浪费时间,有没有能够很大程度上自动化生成单元测试的插件,自己简单改改即可呢? 自己尝试在 Idea 插件库里搜索相关插件并去尝试使用,发现 `TestMe` 还可以。后面和其他同学交流,谎伴 同学推荐他一直在用的 `Squaretest`,我试用
6736 1
告别加班/解放双手提高单测覆盖率之Java 自动生成单测代码神器推荐
|
存储 SQL 人工智能
一文读懂测试自动化
测试是软件开发过程的关键部分,允许开发人员验证软件功能,衡量性能并识别缺陷以进行修复。但是,随着软件项目变得越来越复杂,项目开发周期越来越快,传统的手动质量保证(QA)测试可能不够快或不够完整,无法在可接受的时间范围内满足测试目标。
161 1
|
SQL JSON Java
谈一谈单元测试
写在前面对于我们开发人员来说,单元测试一定不会陌生,但在各种原因下会被忽视,尤其是在我接触到的项目中,提测阶段发现各种各样的问题,我觉得有必要聊一下单元测试。对于单元测试到底有没有存在的必要,这里不是我想要说的重点。有兴趣的可以去了解一下:【单元测试和TDD】【单元测试到底是什么】为了写而写的单元测试没什么价值,但一个好的单元测试带来的收益是非常客观的。问题是怎么去写好单元测试?怎么去驱动写好单元
642 0
谈一谈单元测试

相关实验场景

更多