性格内敛

  • 其实,思路才是测试过程最重要的。虽然这个文档/demo 是三年前的的,但其实我们当前也只是在这个上面根据业务内容的调整不断优化而已。相关的功能点都在上面的回帖中提及到了的。置于新的 demo,我这边目前没有太多时间来将新的实践整理出 demo 来,抱歉!

  • 一、展示一个流程数据构造的例子:
    1、如下是一个完整的业务流程

    @RepeatedTest(1) // 为当前用例执行的次数
    @Execution(CONCURRENT)  // CONCURRENT表示支持多线程
    @DisplayName("申请 + 商户录单 + 风控初审 + 风控复审 + 绑卡 + 在线签约 + 面签合同 + 抵押办理 + GPS安装 + 请款/等待放款成功")
    public void applyWorkFlowCase6() throws Exception {
        String userMobile = MobileUtil.generate();
        String agentMobile = agentDefaultMobile;
        String productNo = "379968089799786497";
    
        // 借款提交
        String bizNo = applyService.loanApply(userMobile, agentMobile, productNo);
    
        // 商户录单
        merchantAppDealOrderService.merchantReplenish(bizNo);
    
        // 初审
        approvalService.firstTrial(bizNo);
    
        // 复审
        approvalService.retrial(bizNo);
    
        // 绑卡
        bindBankService.bindBank(bizNo);
    
        // 签约
        signService.sign(bizNo);
    
        // 面签合同
        contractService.signContractFace2Face(bizNo);
        // 办理抵押
        mortgageService.registerUpload(bizNo);
        // GPS安装
        contractService.gpsInstall(bizNo);
    
        // 等待请款/放款
        fundingService.waitFundingSuccess(bizNo);
    }
    

    从这上面看我们是看不到任何的接口调用,它是一个业务流程
    2、我们展开上面的 “借款提交” applyService.loanApply

    public String loanApply(Boolean caseMockHF,
                                String userMobile, String agentMobile, String productNo) throws InterruptedException {
            // 注册/登录
            LoginDataVO loginDataVO = loginService.appUserLoginBySms(userMobile);
            String authorization = loginDataVO.getAuthorization();
            String userId = loginDataVO.getUserId();
    
            // 身份信息认证
            userInfoService.identifySave(authorization, userId);
    
            // 用户信息
            userInfoService.userInfoSave(authorization, userId);
    
            // 征信授权
            CreditDataVO creditDataVO = userInfoService.creditAuth(authorization, agentMobile, productNo);
            String bizNo = creditDataVO.getBizNo();
    
            // 提交
            apply(authorization, caseMockHF, userId, bizNo, agentMobile, productNo);
    
            return bizNo;
        }
    

    从这上面我们也看不到任何的接口调用,他是完整业务流程中的某一个节点
    3、我们再展开上面的 “身份信息认证” userInfoService.identifySave

    public void identifySave(String authorization, String userId) {
            Response response;
            String name;
            String certNo;
            String bankCardNo;
    
            response = identifyApi.identifyStatus(authorization, null);
            Assertion.isSuccess(response);
            // 认证未通过的需要进行认证
            if (!response.then().extract().path("data.identifyStatus").equals("2")) {
                // 姓名生成
                name = NameUtil.generate();
                // 身份证号生成
                certNo = CerNoUtil.generate();
                // todo 银行类型可选择
                bankCardNo = BankCardNoUtil.generate("621700");
    
                // todo mock适配
                // 卡bin
                response = bankApi.bankCardBin(authorization, bankCardNo);
                Assertion.isSuccess(response);
    
                // todo mock适配
                // 协议绑卡发送短信验证码
                BaofooSmsRequestVO baofooSmsRequestVO = new BaofooSmsRequestVO()
                        .setName(name)
                        .setCertificateNo(certNo)
                        .setBankCardNo(bankCardNo)
                        .setBankMobile(bankMobile);
                response = orderBankApi.baoFooSms(authorization, baofooSmsRequestVO);
                Assertion.isSuccess(response);
                // 协议号
                String platformBindApplyNo = response.then().extract().path("data");
    
                // todo 四要素验证
                //  可暂时不调用,可mock
    
                // 保存身份认证信息
                IdentifySaveRequestVO identifySaveRequestVO = new IdentifySaveRequestVO()
                        .setName(name)
                        .setCertificateNo(certNo)
                        .setBankCardNo(bankCardNo)
                        .setMobile(bankMobile)
                        // todo 地址生成
                        .setAddress("这只是一个地址")
                        .setBirthday(certNo.substring(6, 14))
                        .setExpiryDate("20210802")
                        .setIdCardBackUri("uri")
                        .setIdCardFrontUri("uri")
                        .setIssue("公安局")
                        .setIssueDate("20110802")
                        .setNation("汉")
                        .setPlatformMsgCode("111111")
                        // 根据身份证号来判定
                        .setSex(CerNoUtil.isMen(certNo) ? "1" : "2")
                        .setPlatformBindApplyNo(platformBindApplyNo);
                response = identifyApi.identifySave(authorization, identifySaveRequestVO);
                Assertion.isSuccess(response);
            }
        }
    

    从上面看 identifyApi.identifySave 才算是一个接口调用,而我们整个业务流程中有很多节点,而每个节点可能都有多个接口调用才最终推动流程的开展。所以,通过相应接口的组合,就可以完成业务流程数据的构造。

    二、再展示一个接口测试的例子
    1、如下是一个接口测试的用例

      @ParameterizedTest(name = "{displayName} [{index}] {argumentsWithNames}")
      @CsvSource({
              "【机构案件有效期为长期,单机构】, true, false",
              "【机构案件有效期非长期,多机构】, false, true"
      })
      @DisplayName("案件认领(单个机构/多个机构认领,机构有效期长期/非长期)")
      @Tag("CaseHandleApi.claim")
      public void testAppOutsourceCaseClaimInterfaceCase1(String des, boolean forever, boolean multiOrg) {
          RecoverModeEnum recoverModeEnum = RecoverModeEnum.SHARED;
          RecoverWayEnum recoverWayEnum = RecoverWayEnum.AMOUNT;
    
          OutsourceCasePreconditionVO outsourceCasePreconditionVO = appOutsourceCaseHandleService.outsourceLoginInfo(
                  authorization, forever, recoverModeEnum, recoverWayEnum);
          String bizNo = outsourceCasePreconditionVO.getOutsourceCase().getApplyBizNo();
          String caseNo = outsourceCasePreconditionVO.getOutsourceCase().getCaseNo();
          String outsourceAdminAuth = outsourceCasePreconditionVO.getOutsourceAdmin().getAuthorization();
    
          // 机构案件认领
          BindResult<Void> result = caseHandleApi.claim(outsourceAdminAuth, new ClaimRequestVO().setCaseNo(caseNo));
          Assertion.isSuccess(result);
          // 认领后的案件数据
          OutsourceCase outsourceCaseClaim = outsourceCaseDataSourceBiz.getCaseByBizNo(bizNo);
    
          // 数据验证
          assertCaseClaim(outsourceCasePreconditionVO.getOutsourceCase(), outsourceCaseClaim,
                  outsourceCasePreconditionVO.getOrganizationResponseVO());
    }
    

    caseHandleApi.claim 才是该接口的调用,在此调用之前的 appOutsourceCaseHandleService.outsourceLoginInfo 其目的只是为了构造前置数据(而在这里面,其实也是不同接口调用/SQL 等的数据构造而已),assertCaseClaim 就是接口测试的验证了

    通过上面的两个例子,应该可以说明我所说的了

  • 我们的测试流程其本质就是一个接口一个接口的调用,从而推进流程。所以,你需要根据对应的业务场景,通过组合不同的接口调用来完成对应的流程,在对应过程中加上各个接口调用后相应数据的验证。这样的话,就实现了通过接口来开展业务流程的测试

  • 问题 1:
    1、当前 github 上的代码是根据两年前的接口测试的思路编写的 annotation,如果有需要可以自行添加对应的 annotation,我们当前项目中是添加了其他 annotation 的,对应的 annotation 里面的属性如果有特殊使用场景也可以在 HttpUtils 里面添加对应的属性作用
    2、Junit 我用得不是很多,一般来说,可以通过制定测试类或者测试方法进行,你那边可以通过 Jenkins 传入对应参数来区分这些来达到这个目的

  • 是的

  • 或者说大家不应该把这种思路当做接口测试自动化的思路,而是以接口自动化的思路达到整体流程的自动化(我认为这才是我这样做的一个最终目的)

  • 好久没有更新过这个项目了,大家看到的这个项目与我当前在公司使用的项目比较上已经升级了好多了。
    1、你这边提到了测试结果显示清晰问题,我这边截图一个测试报告

    2、我始终认为,使用代码维护的测试用例在保持最大灵活的前提下(可以写出任何场景的测试用例,数据构造足够方便并不依赖于测试平台是否提供对应功能),可以方便我们根据不同测试条件在代码层面提供对应的测试数据从而最大程度达到稳定性。举个例子,对于贷款业务,还款计划是一个变化的东西,在代码层面我可以根据不同的参数生成还款计划,而非在测试用例级别和测试平台级别两个地方分别处理

  • 看接口参数要求,一般情况是 json 串传过去,服务端自己解析

  • 我在 github 上更新了一下,你按照类似的方法试试呢

性格内敛