软件的测试与发布

前言

看见有同学讨论公司产品开发过程中的单元测试、集成测试、代码审查、签入、发布等问题,我来说说我以前服务过的公司的做法。

最差的情况是,没有测试、审查,直接签入、发布,所以系统不稳定。

最好的情况,我详细说说。

编码规范

某个我服务过的公司,把代码规范做到近乎极致:严格使用FxCop:多一个空格、空行、private关键字都不允许,条件判断后一行代码必须{}等等、等等,自己实现一套更严格的代码检测:所有字符串必须支持多语言除非写例外禁止、代码全局全文拼写错误检测,等等等等。

另外,namespace必须顺序而且System必须前面,static readonly顺序不能掉转,全局变量不允许_,引用dll不允许copy local,不允许“”只能String.Empty,所有警告视为错误,必须打开overflow check,参试列表要么同一行要么全部分列。

一般新人来会被这些要求逼疯。

代码维护

该系统比较大,2200万行代码,几千个项目,所以自己搞了一套系统,整合了TFS,自动做各种shelf/取所有项目最新版本等事情,自动判断某个项目已经最近被编译,如果是就从缓存取出来无需再编译。

单元测试/整合测试 (Unit Testing/Integration Testing)

该系统有60多万个单元/整合测试,每个项目,不管什么类型的程序(Web页面/console/windows 服务/窗体界面),不过什么什么业务,都带有测试,而且这个测试还有大量的各种严格、智能的玩法,譬如实现类要测,基类都自动测;又譬如数据库相关的测试,强制打开事务/snapshot,完成测试自动回滚,然后判断是否有差异就报错。

签入(Shelf/Check-in)

这套系统禁止手工签入(check-in),这个禁止是系统根本不允许开发人员签入,任何开发人员必须通过shelf把代码提交到下面的自动化分布式编译/测试系统。这个好处是避免了任何人都可以随意把代码搞爆。

自动化分布式编译/测试(CI)

因为测试数量巨大,自己搞了一套分布式编译/测试系统。因为开发人员的机器配置相当高,譬如i9+1TB SSD,所以充分利用了几百台的开发人员机器,都给安装上了2个Hyper-V实例,在里面做CI。

大家可能没理解好,觉得市面上的Team City等都能分布式编译/测试,但是他们这种一般是一个提交只能在一个worker上编译和跑所有测试。但这套东西能把任意测试根据最优解自由组合,然后分布式到几百台*2个Hyper-V里面去做编译CI。譬如60万个测试里面,某几千个,是在机器001跑。

还有,这个测试不会盲目地跑所有60多万个测试,会自动判断代码的改变会影响到那些测试,才去跑相关的测试。

而且最关键的是,这套系统能最优解合并最近大家提交的shelf,然后再去做CI,都成功的话大家都pass,如果失败,再拆开单独跑失败的测试,这样就能节省大量时间。

代码审查(Review)和可用性测试

当上述的自动化分布式编译/测试通过之后,代码审阅者对代码分析、实际跑过之后,才标识该shelf通过,然后开发人员才能交给自动化分布式编译系统去签入代码。

 

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。

批量数据导入的性能与完整性问题

刚才有网友问了一个技术问题:

我从其他接口 采集一批数据,每次上万条左右,然后存到数据库,存库前还要每条每条的判断数据库存不存在这条数据,不存在才能写库,有没有性能好的实现思路啊?

这是典型的批量数据导入的问题,一般追求是速度。

8年前来澳洲后第一份工作是一个做智能表(水电煤等)的公司,软硬件结合,软件系统采集数十万的智能表的数据,系统里一些表,单个超过30亿条记录,每天更新上千万条记录,为了这个专门实现了一个高度优化的批量导入功能。

现在拿微软SQL Server做例子,说说思路。

首先,要实现速度,会考虑批量导入(Bulk Copy),但一般来源数据格式和目标表达格式不一样(譬如字段数量、类型等),甚至需要做一些计算,甚至要从关联表取数据,所以一般先会导入到临时表,然后再插入目标表。

使用Bulk Copy有一个问题,是它不确保插入数据的顺序,所以如果你必须要求数据插入完全按照来源数据的要求,你必须确保Bulk Copy之前主键字段的值是按顺序的,因为簇集索引是物理顺序,所以会默认按这个排序。

插入目标表需要考虑2个问题:

  1. 唯一性:主键可能会重复,一般采用修改主键索引忽略重复记录,但是这个做法可能会忽略掉后面比较新的数据。
  2. 完整性:如果这个批量导入逻辑可以是多线程/多进程跑的话,那么需要额外的逻辑去处理不会重复操作。

插入数据要确保唯一性又要考虑最新数据会被导入,一般做法是判断目标表是否存在数据,如果不存在则插入,如果存在则更新,这个操作是有重复处理浪费时间,所以可以用SQL Server的MERGE语句,把插入和更新合二为一。

有朋友问:“那是否有更快的办法?”。是有的,那就是支持多线程/多进程。思路如下:

  1. 客户端调用BulkCopy,获得起始、结束Id
  2. 完成调用服务器的存储过程处理这批数据

这样做可以支持并发问题,提高性能。

如何成为爆栈成员:

  • 加我微信 unruledboy ,进入技术群

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。