乐趣区

关于单元测试:淘系用户平台技术团队单元测试建设

简介:单元测试是工程交付前品质保障的第一环,也无疑是软件工程品质保障的重要基石,无效的单元测试可能提前发现 90% 以上的代码 Bug 问题,同时也能避免代码的腐化,在工程重构演进时起到至关重要的作用。

作者 | 问元
起源 | 阿里开发者公众号

为什么须要单元测试

纵观优良的开源工程,齐备的单元测试总是必须的条件。通过这些单元测试,咱们能够充沛理解代码中相干类和办法的作用和外围逻辑,相熟各种场景的运行状况。同时也因为有了单元测试,开源作者在承受各种 feature 的代码提交时才有稳固平安的保障。其实单元测试的重要性所有开发同学应该都了然于胸,同样 TDD(测试驱动开发)也不是一个新的概念,然而真当咱们落地实际时,又总会找出各种各样的理由来劝服本人下次肯定好好写单元测试,这一次先放过本人。这些理由无外乎,开发周期太紧了; 测试同学能保障性能正确性; 写单元测试代码量比业务代码还大; 又不是不能跑。所以尽管咱们总是在追赶工程师文化,却又时不时放荡在放弃工程师底蕴的路上。

单元测试是工程交付前品质保障的第一环,也无疑是软件工程品质保障的重要基石,无效的单元测试可能提前发现 90% 以上的代码 Bug 问题,同时也能避免代码的腐化,在工程重构演进时起到至关重要的作用。

怎么写单元测试

好的单元测试的几个要点

摘自阿里巴巴开发规约

  • 单元测试必须恪守 AIR 准则,单元测试必须具备 Automatic(自动化),Independent(独立性),Repeatable(可反复)性;
  • 单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须齐全自动化才有意义。输入后果须要人工查看的测试不是一个好的单元测试;
  • 单元测试要保障测试粒度足够小。单元测试测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,个别是办法级别;
  • 单元测试要恪守 BCDE 准则,Border,边界值测试,包含循环边界、非凡取值、非凡工夫点、数据程序等;Correct,正确的输出,并失去预期的后果;Design,与设计文档相结合,来编写单元测试;Error,强制错误信息输出(如:非法数据、异样流程、非业务容许输出等),并失去预期的后果;
  • 外围业务、外围利用、外围模块的增量代码要确保单元测试通过;

单元测试编码范式

这里次要以 Mockito 单元测试框架为模版

  • Mock : 通过 when().thenReturn/thenAnswer/thenThrow 或者 doReturn().when()等 mock 形式将依赖类办法进行模仿,模仿服务依赖或者两头后果
  • DO : 调用被测试类办法,执行测试链路
  • Verify : 校验执行后果正确性,通过 Assert 校验数据后果精确,通过 Verify 校验链路执行精确,通过 expected=Exception.class 校验异样链路
public class Test {
    // 0. 依赖类
    @Mock
    DependencyClass dependencyClass;
    // 0. 待测试类
    @InjectMocks
    TestClass testClass;

    @Before
    public void setUp() {MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testMethod() {
        // 1. Mock, 依赖办法,结构中间层数据
        when(dependencyClass.someMehod(any())).thenReturn(mockData());
        // 2. Do, 调用被测试类
        Result result = testClass.testMehod();
        // 3. Verify, 校验后果数据
        Assert.assertEquals("some expected result string", result.getModel());
    }
}

当然写单元测试用例尽管套路比拟模版化,然而咱们也要充分利用单元测试框架(Junit/Mockito/PowerMock/Spock),把握其中的一些技巧,能力写出快准狠的单元测试用例,这也是研发同学必须要把握的基本功。对于如何利用单元测试框架这里不再赘述(具体能够参考阿里技术《Java 编程技巧之单元测试用例编写流程》)。

单元测试编码提效

IDEA 上有很多单元测试插件,可能半自动化生成单元测试类文件,这里重点举荐 TestMe 插件。TestMe 插件能够智能剖析被测试类的依赖类,联合 Mockito+Junit 等单元测试框架,生成 Mock/InjectMocks 依赖关系,主动生成单元测试类。

假如业务代码如下:

@Component
public class DefaultMemberManager implements MemberManager {
    @Autowired
    private MemberDAO memberDAO;
    @Autowired
    private CacheManager cacheManager;

    @Override
    public Date queryActivationTime(long userId) {Date activationTime = cacheManager.getActivationTime(userId);
        if (activationTime == null) {MemberDO memberDO = memberDAO.queryByUserId(userId);
            if (memberDO != null) {cacheManager.saveActivationTime(userId, memberDO.getActiveTime());
                activationTime = memberDO.getActiveTime();}
        }
        return activationTime;
    }
}

则通过 TestMe 快捷键 COMMOND+N, 能够极速主动生成如下的单元测试类

public class DefaultMemberManagerTest {
    @Mock
    MemberDAO memberDAO;
    @Mock
    CacheManager cacheManager;
    @InjectMocks
    DefaultMemberManager defaultMemberManager;

    @Before
    public void setUp() {MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testQueryActivationTime() throws Exception {when(memberDAO.queryByUserId(anyLong())).thenReturn(null);
        when(cacheManager.getActivationTime(anyLong())).thenReturn(new GregorianCalendar(2022, Calendar.MARCH, 5, 23, 2).getTime());
        Date result = defaultMemberManager.queryActivationTime(0L);
        Assert.assertEquals(new GregorianCalendar(2022, Calendar.MARCH, 5, 23, 2).getTime(), result);
    }
}

团队单元测试建设

覆盖率概念

覆盖率是类 JaCoCo 插件通过 javaagent 挂载的形式,在单元测试命令运行时执行代码覆盖率检测,计算单元测试执行过程中所笼罩的代码比例来生成覆盖率。常见的覆盖率指标,又可进一步细分为语句覆盖率,条件覆盖率,分支覆盖率,门路覆盖率等。这里咱们以后更为关注语句覆盖率和分支覆盖率,尤其是增量代码的覆盖率,更能体现变更代码的单元测试笼罩状况。

如何进行单元测试

这里咱们借助于阿里研发平台 Aone 的测试实验室性能,Aone 实验室反对测试工作插件的编排组合,通过独立的测试资源执行测试工作。所以咱们将代码拉取插件,单元测试插件和覆盖率计算插件进行编排配置,造成最终的执行流:拉取代码;执行单元测试命令;单元测试后果解析;计算覆盖率。最终实现整个工程的单元测试覆盖率计算。

单元测试覆盖率后果示例如下

什么时候触发单元测试

单元测试工作次要通过继续交付流水线 pipeline 来集成,以后几个次要触发策略如下

  • 代码提交时,保障单元测试执行及时性
  • 代码审核时,保障代码审核通过的代码分支合乎单元测试规范
  • 公布流程中,保障最终集成公布的所有分支代码合乎单元测试规范

单元测试覆盖率卡点

用户平台技术团队单元测试标准如下:

  • 单元测试用例通过率为 100%
  • 单元测试增量代码行覆盖率为 85%
  • 代码标准扫描增量问题总数为 0 个

单元测试覆盖率报表

为了更好的掂量单元测试的覆盖率状况,咱们采纳报表的模式统计每个利用,每个团队的代码单元测试覆盖率。

总结

以后团队内各利用(除边缘利用外)的单元测试增量代码覆盖率在 2022 年曾经全副达到 85% 规范,最新均匀增量代码行覆盖率达到 88%,整体全量代码覆盖率均匀进步 20%。诚然单元测试覆盖率的进步不是最终的目标,覆盖率高不能齐全代表工程质量高,然而一个没有单元测试或者单元测试覆盖率低的工程,其代码品质和稳定性必然不高。同时团队内研发同学对单元测试也有了新的意识,自测和提测品质显著晋升,全年未产生因为代码品质产生的线上故障,无效晋升了工程质量和服务稳定性。

后续布局,继续优化单元测试品质,晋升分支覆盖率,优化边界异样笼罩;关注单元测试编码效率的晋升,优化测试用例和测试数据拆散;关注外围链路单元测试覆盖率;纯熟将 TDD 思维使用到业务开发过程中。

团队介绍

大淘宝技术 - 用户平台技术团队是一支集研发、数据、算法一体的团队,负责淘系的用户增长,游戏互动,平台会员和私域经营等消费者外围业务。在对用户抢夺进入白热化的期间,团队正承当着保卫电商主板块增长的重要使命,是阿里外围电商战场的参与者,用继续的技术创新来驱动阿里电商引擎的稳步前行。

原文链接
本文为阿里云原创内容,未经容许不得转载。

退出移动版