其他分享
首页 > 其他分享> > 游戏服务器单元测试实施的必要条件

游戏服务器单元测试实施的必要条件

作者:互联网

说起单元测试,很多人都知道它是一个好东西,也有很多人认识到单元测试的好处之后,想在自己的项目中实施单元测试。但是往往是不尽人意,理想太丰富,实现太骨感,变成从调研到实施,再到放弃。这就值得我们静下心来研究一下,只有充分了解了它的本质和规律,才能更好的便用它。

单元测试需要在服务器框架层面支持。单元测试不仅是业务的一部分,也是服务器框架的一部分,并且,它首先是服务器框架的一部分,然后才是业务的一部分。所以在设计服务器框架的时候,要充分考虑到单元测试的实施,把单元测试框架嵌入到服务器框架的设计之中,和整个服务器框架融为一体,这样才不会让单元测试在项目中显得那么突兀。比如现在SpringBoot就比较好的在框架层上面支持了单元测试,如果不使用像Spring这样的框架的,就需要自己在服务器框架中封装好,让单元测试可以方便的启动,运行,调用系统方法等。

单元测试需要建立在良好的面向对象的编程风格之上。如果要在项目中实施单元测试,团队所有的必须有良好的面向对象思想,或者在项目开发上约定好对象职责划分方法,被测试的对象和方法的代码量尽量少而精,方法的实现最好都是单一职责。单元测试和面向对象编程是一个相辅相成的关系,在写代码的时候,需要考虑到编写的代码是否符合单元测试的规范,是否方便对编写的方法进行单元测试,如果不适合,就应该毫不犹豫的对代码进行重构;反过来,单元测试促尽了代码的可测试性,面向对象性,并使代码的质量有可测试性,进而减少代码的混乱性。而且可以培养团队的代码风格统一。

比如下面这段代码,就是一个糟糕的代码,非常不适合做单元测试:

/**
 * @author 王广帅
 * @date 2021年04月27日 2:41 下午
 */
public class CardService {

    public  void cardUpLevel(Player player, CardModel cardModel) {
        //检测是否达到最大等级
        if (cardModel.getLevel() >= 100) {
            throw new IllegalArgumentException("已达到最大等级");
        }
        //检测材料是否足够
        if (player.getDiamond() < 100) {
            throw new IllegalArgumentException("钻石不足");
        }
        //扣除钻石
        player.setDiamond(player.getDiamond() - 100);
        int nextLevel = cardModel.getLevel() + 1;
        cardModel.setLevel(nextLevel);
    }
}
注:上面的数字只是为了方便说明问题,随便写的,正式开发环境中,都是从配置中读取的

而如果重构一下,变成下面的方式就非常方便单元测试了:

/**
 * @author 王广帅
 * @date 2021年04月27日 2:41 下午
 */
public class CardService {

    public void cardUpLevel(Player player, CardModel cardModel) {
        checkArrivalMaxLevel(cardModel);
        checkDiamondEnough(player);
        upLevel(player, cardModel);

    }

    private void checkArrivalMaxLevel(CardModel cardModel) {
        //检测是否达到最大等级
        if (cardModel.getLevel() >= 100) {
            throw new IllegalArgumentException("已达到最大等级");
        }
    }

    private void checkDiamondEnough(Player player) {
        //检测材料是否足够
        if (player.getDiamond() < 100) {
            throw new IllegalArgumentException("钻石不足");
        }
    }

    private void upLevel(Player player, CardModel cardModel) {
        //扣除钻石
        player.setDiamond(player.getDiamond() - 100);
        int nextLevel = cardModel.getLevel() + 1;
        cardModel.setLevel(nextLevel);
    }
}

另外,欲实施单元测试,还需要人力的支持。即必须公司领导层认识到单元测试的作用,以及这样做给公司带来的好处,然后支持在公司的项目组中实施单元测试,给予人力的支持。一般来说,谁写的功能由谁来负责写此功能的单元测试,但是这样就会增加模块的开发时间,如果不增加开发人员,项目进度一定会受到影响。这就需要在项目管理上进行适当的调整和妥协,为了项目质量妥协。好的单元测试可以保证代码质量,减少测试人员测试出的bug,进而减少测试成员与开发人员的沟通成本,减少代码返工的成本,就间接的减少了项目的整个研发周期,为项目节约大量的开发时间。

在游戏服务器开发过程中,会有这样一个理由还反驳说不好实施单元测试:功能需求变更太频繁,一个功能还没有做完,或者刚做完可能就要变需求,写了也白写。这确实是让人头疼的问题,但是代码的设计就是为了应对之后的需求变化与维护的,良好的单元测试会保证良好的代码设计,这样可以更加灵活方便的应对功能的变更。比如如果模块化划分清楚,需求删除时,直接删除模块,基本上不影响或很少影响其它的模块,即是不删除需求,对需求进行调也只是修改基本的方法,可以快速的实现修改,并修补对应的单元测试代码。让代码健康的跑起来。

所以,宗上所述,要在项目中推广并实施代码的单元测试,首先是管理层达成一定的共识,支持实施单元测试。二是项目研发的主管人员(游戏服务器开发中叫主程)必须熟悉并能熟练使用单元测试,并且保证团队人员的代码风格严格按面向对象的方式的设计(这样最方便写单元测试),而且这个是影响实施单元测试是否成功的决定因素。因为如果代码混乱,不是按面向对象的方式开发,写单元测试时就非常困难,开发人员就会烦感写单元测试,导致即使写了也是应付上面的要求,而达不到保证代码质量的目的,逐渐演变成了形式主义。


在这里插入图片描述

标签:框架,代码,单元测试,cardModel,player,必要条件,服务器
来源: https://blog.csdn.net/wgslucky/article/details/116212774