测试驱动培训2022.04.08

4/8 TDD测试驱动开发training
1. 代码整洁
    -- 为什么要有整洁代码, 随着时间推移.....
    -- 代码可读性: 命名,表达式(if-else,最好封装)
    -- 方法行数控制,只做一件事
        细节内容不需要暴露出来-提取方法
        提取无关的子问题,确定好这个函数的high-level goal
    -- 重复《程序员修炼之道》
    -- Kent Beck写好代码的三要素:a.态度 b.技能 c.习惯
    -- 注释 < 提取方法
    -- 规模越小, 越通用越容易复用
        重构:通用方法放到superClass
        DRY原则: Don't Repeat Yourself
2. 面向对象: roles, responsibilities, collaborations
    -- 判断职责: 职责操作的数据是谁的, 父类子类?
    -- 隔离功能, 职责分配
    -- 迪米特法则
    -- 正交设计
        a.消除重复
        b.分离不同的变化方向
        c.缩小依赖范围
        d.向稳定的方向依赖
3. 测试加油站
    单元测试不依赖于外部资源(文件系统,网络通信)
    单元unit -- 业务场景
    FIRST原则:   a.Fast
            b.Isolated
            c.Repeatable
            d.Self-verifying
            e.Timely
    单元测试文档化: 方法的命名, e.g. should_not_create_publication_in_offline_mode_when_click_no蛇形模式
    GIVEN-WHEN_THEN
    AssertJ:
        -- assertThat()......
    Mockito:
        -- mock(X.class)    
        -- when(...).thenReturn(...);
        -- mock的一个list曾经add过但是又clear了, verify也可以判断它有过这个行为。
    测试的价值:
        -- 1. 测试提供API调用的文档,阅读测试可以更有效地帮助我们理解开发代码
        -- 2. 根据复杂的业务逻辑来先写测试, 可以保证逻辑代码的健壮性
            慎用static方法,工具类才用
            方法内不能new对象, 尽量注入(set或者spring注入)
            不需要考虑coverage
        -- 3. 被测试覆盖的代码可以更有效地保护重构的正确性
        -- 4. 测试可以改进设计,保证代码的可测试性
4. 重构
    外部条件不变的情况下, 优化内部设计
    何时重构?
        -- 新增功能
        -- 修改bug
        -- code review
        -- 代码发现坏味道
            函数对某个类的兴趣高于对自己的兴趣
            ......
    重构手法
        -- if分支语句: 合并提取公共因子
        -- 属性list, 不让整个set, 可以add或者remove
        -- 提取父类
        -- split loop
            把for循环中的职责分开。时间复杂度一样
    练手(基本根据职责分配来重构):
        提取当前类的因素, 不用getXX(),直接用XX, 因为用到了Movie的枚举类, 再次抽取方法, 移动到mivie中。
        重构之前先run test, 改完再run test
问题: 一个系统中Unit Test框架,junit升级导致用不了。

 

4/21 TDD
1. 分解任务可以对业务逻辑进行分层
2. 伪代码
3. 再写测试案例
4. 根据测试案例开发

任务描述用语需要更具有业务风格 
TEST: 报名人 Enrollee 报名单Ticket 报名通道EnrollingChannel
    a. 验证报名(需要错误信息返回)
        -- 1. 报名人资格核实(人和活动的部落一致性)
        -- 2. 报名通道核实
        -- 3. 不可重复报名
    b. 完成报名(失败给原因:e.g.名额有限之类的)
    c. 发通知(报名成功)

伪代码 -- 工具 ZenUML时序图 
        -- 点评: AppService中出现了多个对象的调用(业务逻辑)
            不可, 这不属于网关层的任务,应该再嵌套一层EnrollService, 验证的流程都放里面
    EnrollController.enroll(EnrollRequest) {
        Enroll = EnrollRequest.to(); // 转换为领域对象
        EnrollAppService.validateEnrollment(Enroll) {
            EnrollerService.validate(Enroll);
            EnrollingChannelService.isOpen(Enroll);
            EnrollingChannelService.checkEnrollerNumber(Enroll);
            EnrollRecordRepository.queryByEnrollerIdAndChannelId(Enroll);
        }
        EnrollRecordRepository.save(Enroll);

        NotifacationClient.notify(Enroll);
    }
    -- 点评: 代码层面上注意AppService的职责边界: 只包含两项职责, 第一个是报名, 第二个是通知
总结
    1. 每次改代码一定要跑所有的测试,起到了test对程序的保护
        所以必须TDD+CI
    2. 随时随地重构,在test的保护下。重构完也必须跑test
    3. 保持TDD的结构感

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值