zoukankan      html  css  js  c++  java
  • 【功能测试技巧2】dubbo引起的数据精度的思考

    1.引言

    1.1引入背景

    我们目前使用的所熟知的公司的保险系统,好多涉及计算金额的字段,开发都将这类变量定义为Double类型,举例请看下表:

    字段

    定义类型

    来源系统

    Premium【保费】

    double

    承保系统

    PlanFee【应收应付金额】

    double

    收付系统

    EstimateLoss【估损金额/报案金额

    double

    理赔系统

    1.2场景重现

    所在项目涉及的是接口测试,寺库商户系统每向样光信保发送一笔订单,在阳光信保进行承保;有承保自然会出现理赔场景;当寺库商户将一笔订单的逾期报案信息发送到阳光信保理赔系统时,信保接口接收一笔索赔金额时报错;自己测试也没有问题,进行查找后发现是double类型精度问题所导致;

    2.分析

    2.1产生原因

    接口传送过来的报文以JSON形式进行交互,每个字段都定义为String类型;寺库逾期报案金额=逾期本金+逾期利息之和即[EstimateLoss=balance+int]

    具体举例如下:

    Balance=121.57

    Int=4.83

    此时EstimateLoss=balance+int=121.57+4.83=126.40;但是当balance本金与int利息进入理赔系统,按照double方式进行接收相加的结果如下图在Eclipse里运行的结果:

    了然了吧,理赔系统会拿126.39999999999999与接口报文中实际传送的129.40做比较,肯定不相等,从而触发了报案的报案金额一定要和本金+利息之和相等这条需求;

    2.2解决方案

    采用Java 浮点数精确计算 BigDecimal方式进行处理;

    第一:即先将两个String类型的本金和利息直接接收到理赔系统;

          String类型的EstimateLoss报案金额直接接收到理赔系统,

    Double类型;

    第二:将String类型的本金和利息分别转换为BigDecimal

    第三:将本金与利息之和是BigDecimal类型的,在还原成理赔系统识别的Double类型,在拿去和EstimateLoss报案金额做比较;

    最后在构造为BigDecimal实现相加。

    即按照如下代码实现:涉及减法、乘法、除法的浮点型精度也需要考虑测试的是哪种数据类型;

     public static double sub(double v1,double v2){

            BigDecimal b1 = new BigDecimal(Double.toString(v1));

            BigDecimal b2 = new BigDecimal(Double.toString(v2));

            return b1.subtract(b2).doubleValue();

        }

    运用BigDecimal进行运算结果如下:

    2.3分享说明

    希望今后大家测试接口或者其他涉及金额的问题时,一定要事先向开发咨询其定义的和金额有关的变量,定义的数据类型是什么,如果是浮点型的FloatDouble,那么这样的变量进行运算的时候就会出现精度问题,需要格外注意;

    一般情况下:

    两个(或以上)的Float类型的数据进行数学运算,会产生精度丢失问题;

    两个(或以上)的Double类型的数据进行数学运算,会产生精度丢失问题;

    一个Float类型与另一个Double类型的数据进行数学运算,会产生精度丢失的问题;

    所以测试涉及小数(一般是金额相加减的时候)需要明确的内容:

    1.两个相加字段,在开发程序里定义的数据类型是什么;

      一般直接定义为BigDecimal,不要想当然的认为就没有问题,要看它是否自始至终都是BigDecimal类型的数据进行操做,如果不是,请注意:因为只有String直接转BigDecimal才不会有精度丢失错误,将float或者double转成BigDecimal也会出现数据精度丢失问题;

       2.熟悉一般类型哪些小数进行数学运算会报数据精度丢失问题,数据精度丢   失原因这里不做介绍,可以自行百度;一般给自己准备上几组,遇到这类问题的时候将这几组数据套用进去验证一下;

    3.一般容易出现这种问题的数据验证组合如下(包括但不局限以下实例):

    323.34-4.85

    121.54-4.83

    121.57+4.83

    4.015*100

    123.3/100

    2.4延伸扩展

    从精度问题引申到我们平时需要注意有些字段,开发定义的数据类型会影响精度;

    有时还要留意JAVA数据内部默认赋值的特性;

    Int数据类型默认值为0

    String类型默认值为NULL

    Boolean类型的默认值为false

    当我们测试规则引擎的时候,有些时候定义只有某一个值为0的时候才会触发规则,当系统处理异常时有可能不能返回正常数据的值,此时如果默认为int型的数据将会默认返回0,使得系统默认这条数据触发了规则,从而使风控规则失真;

    3.希望

    希望通过本文档的书写,使得在测试金额等涉及精度问题的时候,能够快速的意识到精度风险,当然也不要草木皆兵,先向开发了解清楚程序内部定义的数据类型是什么。总之,希望大家都能耳聪目明,叫精度丢失问题在我们面前无所遁形;

  • 相关阅读:
    Oracle11g备份与恢复-手工备份与恢复
    undo段及区的状态和使用
    图解一个事务操作流程
    Oracle11g备份与恢复
    undo表空间概述-1
    事务的隔离级别
    事务概述
    系统改变号(SCN)详解
    实例崩溃恢复原理--检查点队列的作用
    Oracle-检查点队列
  • 原文地址:https://www.cnblogs.com/haibaowang/p/6733498.html
Copyright © 2011-2022 走看看