美文网首页
给测试小姐姐优化代码——干掉if-else

给测试小姐姐优化代码——干掉if-else

作者: Vongola々骸 | 来源:发表于2018-11-01 15:26 被阅读0次

    友情提示,这篇的代码比较多,可以选择性阅读


    最近测试小姐姐在写自动化测试case,之前我就和测试小姐姐提过,她写的代码确实有点臃肿,可以考虑优化一下,减少冗余代码,提高可读性和可维护性......
    估计小姐姐听了我一番高谈阔论被我给忽悠到了。这天晚上大概9点,我正准备跑路,测试小姐姐突然找我


    测试:你看看我这个代码该怎么优化一下

    me:emmm..(扔给我一个js文件,467行,我统计了一下,三个if控制段,每个if带19个else,平均每一个条件6-7行的代码,就是说加起来有三四百行的代码是在重复工作)

    describe ("退货分仓逻辑",function(){
        it("第三方商家、自主发货、已签收状态:退回商家地址",function(){
                var checkMap = {
                    "type" : 1
                }
                var data = returnWhcode(checkMap);
                checkDataResults(data,checkMap);
        });
        // 省略19种不同的case
    }
    
    function returnWhcode(checkMap){
        //数据准备
        var info = {};
        if(checkMap.type == 1){
    
            info = {
                "seller" : "***",
                "status" : 7,
                "whcode" : "CPartner",
                "logistics" : "auto"
            }
        }else if(checkMap.type == 2){
            info = {
                "seller" : "5ac442c71d9771377df40c8d",
                "status" : 6,
                "whcode" : "CPartner",
                "logistics" : "consolidation"
            }
        }
        //此处省略18个else if
        var data = null;
        // 业务逻辑
        return data;
    }
    function checkDataResults(data,checkMap){
        caseResult.setResultMsg("商家:" + data.afterSaleMap.seller_name);
        caseResult.setResultMsg("包裹状态:" + data.info.status);
        caseResult.setResultMsg("发货仓:" + data.info.whcode);
        caseResult.setResultMsg("物流模式:" + data.info.logistics);
        if(checkMap.type == 1 || checkMap.type == 2 || checkMap.type == 3 || checkMap.type == 5 || checkMap.type == 7 || checkMap.type == 9 || checkMap.type == 11 || checkMap.type == 13){
            expect(data.afterSaleMap.return_wh_code).toBe("CPartner");
            caseResult.setResultMsg("退货地址为第三方商家地址:" + data.afterSaleMap.return_address);
        }
        // 这里当然也省略好多个else if
    }
    

    me: 这么多if-else你看着不难受么

    测试:难受啊,所以来找你看看怎么优化嘛

    me: 呃,要不你先说说这个测试的场景是什么

    测试:测试退货分仓逻辑,根据不同的商家类型、物流模式、和发货仓库,把货物退到不同的地方,目前有20种退货组合,会分别退货到5个不同的仓库

    me:明白了,就是说你现在要测一个接口,参数就那么几个,但是请求参数组合有很多种,是这样吧

    测试:是哒

    me: 那完全不需要把所有的请求数据全部hardcode到代码里面啊,你把请求参数抽出来,放到配置文件里面去,然后用个for循环去调用就好了

    我的初版设计

    {
      "第三方商家、自主发货、已签收状态->退回商家地址" : {
          "seller" : "***",
          "name" : "测试",
          "status" : 7,
          "whcode" : "CPartner",
          "logistics" : "auto",
          // 预期退货仓库
          "return_wh_code" : "CPartner",
          // 预期退货地址
          "return_address" : "上海 上海市 ***"
      }
    }
    
    describe ("退货分仓逻辑",function(){
        var whCodeInfos = JSON.parse(JsonSchemaUtils.getJsonFile(PWD+'/whCodeInfo.json'));
        for(var key in whCodeInfos){
            info = whCodeInfos[key];
            data = returnWhCode(info);
            checkDataResults(data,info);
        }
    }
    
    function returnWhcode(info){
        var data = null;
        // TODO 业务逻辑
        return data;
    }
    
    function checkDataResults(data,checkMap){
        expect(data.afterSaleMap.return_wh_code).toBe("CPartner");
        caseResult.setResultMsg("退货地址为第三方商家地址:" + data.afterSaleMap.return_address);
    }
    
    

    me : 你看,我们把数据和控制逻辑分离开,几百行代码一下子就变成几十行了,如果之后有新的请求组合出现,你只需要在json文件里面新增一个key-value对就好了(快夸我)
    测试: 嗯,我先改好测一下看看

    me: (中间经历了不少次失败,反正是折腾了很久) 十点多了,我得下班了,你写好了我明天再看看,应该还可以改进的

    测试:这样很好了啊,还要怎么改进

    me: 你先把这个写完,明天再看

    第二天,测试小姐姐的新版

    describe("退货分仓逻辑",function(){
        it("第三方商家、自营分仓",function(){
            for(var key in whCodeInfo){
                caseResult.setResultMsg("--------------分仓case分割线--------------");
                caseResult.setResultMsg("|" + key + "|");
                info = whCodeInfo[key];
                data = returnWhCode(info);
                checkDataResults(data,info);
            }
        });
    });
    
    function returnWhCode(info){
        var data = null;
        // 省略业务逻辑
        return data;
    }
    
    function checkDataResults(data,info){
        caseResult.setResultMsg("商家:" + info.name);
        caseResult.setResultMsg("包裹状态:" + info.status);
        caseResult.setResultMsg("发货仓:" + info.whcode);
        caseResult.setResultMsg("物流模式:" + info.logistics);
        caseResult.setResultMsg("期望退货仓:" + info.return_wh_code);
        caseResult.setResultMsg("期望退货地址:" + info.return_address);
        caseResult.setResultMsg("实际退货仓:" + data.afterSaleMap.return_wh_code);
        caseResult.setResultMsg("实际退货地址:" + data.afterSaleMap.return_address);
        expect(data.afterSaleMap.return_wh_code).toBe(info.return_wh_code);
        expect(data.afterSaleMap.return_address).toBe(info.return_address);
    }
    

    me:你上面的caseResult.setResultMsg("商家:" + info.name);这一串msg是需要展示到界面的么

    测试:是的,我得在页面上看到结果

    me: 那要是之后这个接口加了个字段,你又得来改代码

    测试:没关系啊,反正只需要加两行就好了

    me:白帮你优化了,可以通过改配置解决的问题,就不要改代码,像这样

    我的终版设计1.0(其实后面还有一些改进,就不在这里列出来了

    {
    "第三方商家、自主发货、已签收状态->退回商家地址":{
        "input":{
          "seller":"5ac442c71d9771377df40c8d",
          "name":"测试redqa021",
          "status":7,
          "whcode":"CPartner",
          "logistics":"auto"
        },
        "except_output":{
          "return_wh_code":"CPartner",
          "return_address":"上海 上海市 黄浦区马当路388号小红书"
        }
      }
    }
    
    function checkDataResults(data,info){
        // 输入数据展示
        for(var key in info["input"]){
            caseResult.setResultMsg(key + ": " + info["input"][key])
        }
        // 实际结果和预期结果展示
        for(var key in info["expect_output"]){
            caseResult.setResultMsg(key + "_actrual: " + info["expect_output"][key])
            caseResult.setResultMsg(key + "_expect: " + info["expect_output"][key])
        }
        // 实际结果和预期结果对比
        for(var key in info["expect_output"]){
            expect(data[key]).toBe(info["expect_output"][key]);
        }
    }
    

    总结一下

    1. 为什么会有这么多if-else

    就这次测试小姐姐的案例来看,其实整个主流程的逻辑是很单一的,之所以会有这么多代码量,都是因为数据影响了控制逻辑,其实本次测试的每一个case的测试流程都是一样的,完全不需为每个case写一个条件判断。

    2. 我们做了什么

    其实前辈们已经提供了方向,把常改变的和不常改变的东西分开,在这个案例中很明显,随着业务的变更,这一个服务可能会产生更多的case,所以case数据是经常变动的,但是我们的接口调用流程,请求响应的整体结构是不会经常变动的。
    如果对变和不变的预测没有一个好的标准,那么我这里提出一个清晰一点的方法:把数据和控制逻辑分开

    3. 有什么好处

    1. 看着舒服(467行和67行,你说呢)
    2. 几乎不用改代码了
      这样就可以更专注于测试数据,不用担心改代码的时候出错,造成测试结果不符合预期
    3. 就算要改代码也会很轻松,参考第一条
    4. 接入配置中心,以后测试的时候你连代码都不用拉下来,直接在平台上就可以新增、修改case

    相关文章

      网友评论

          本文标题:给测试小姐姐优化代码——干掉if-else

          本文链接:https://www.haomeiwen.com/subject/myxxxqtx.html