最近公司需要做一个mock server。在广告行业中,有时候为了做统计需要像第三方发tracking url或者post一些数据。为了测试,mock server的角色就是代替第三方的server来接收tracking url,然后基于此做进一步的操作。
技术选型
我们这边有一个回归测试框架,是用Python开发的,每次新的feature上线之前需要跑过所有的回归测试,伴随着业务不断发展,新的case会不断被加到回归测试的case集合,现在大概有800多个case。mock server的最终归宿也是继承到回归测试框架中负责第三方相关的测试。首先是技术选型的问题,大家都知道现在使用Go来做Web service极其简单,所以我最开始使用了Go的Gorilla很随意的搭了一个,但是后来考虑到和回归测试框架继承,被否定了,采用了Python。Python做Web Service就是WSGI那一套,也有很多有名的框架像Tornado,Webpy什么的。我本着节约资源的原则选择CherryPy,CherryPy是很轻巧,但是功能以及文档不是很全,对于从0开始上手很不友好,暂且按住不表,之后单独用一篇文章来写。
开发过程
目前有一个最简单的需求是记录Adserver发过来的request的相关信息,比如GET请求的Header, Agent;如果是POST请求的话,还需要记录POST数据。Web server这边最后做成那种RestFul Api的形式,具体到python的web server就是定义一个路由表。那么如何记录log呢?我采用了Python里面的Logger Module,为什么呢?因为它是线程安全的。为什么需要线程安全呢?因为log文件只有一个,而Web Server是多线程的,每个线程都需要记log。我最开始的做法是直接把记log的操作放在server的handler里面做,后来测试的时候才知道这有多么的脑残,因为这会导致记录的顺序不一致。怎么办?先把需要记录的Log内容放到队列里面,然后单独起一个线程去复制读。也就是生产者消费者模型。
改Bug
真正测试开始才发现,真实情况往往要复杂的多。我们的Adserver发送tracking url的时候是多线程并行发的,也就是web server接收到的顺序还是不一致的。尼玛,前面的优化白做了。但是因为我们要做回归测试,测试记录的log是否一致,怎么办呢?最简单的方法将log按行排序再进行比较。但是这样会特别的乱。因为之前记录是按transaction来记录,log形式是transaction:{}, transaction:{},看上去类似json的数据形式,那么我们要不要用一个dict或者其他类json的数据结构来保存起来,然后再比较相应的字段呢?如果你真的要这么做,那么我只能说你实在是太学术了。
我们最后的目的是比较log,log是局部有序的,也就是每个transaction内部的信息是一定,只是多个transaction之间的顺序变了而已,最简单也是最有效的方法是讲每个transaction解析出来,然后对多个transaction进行排序。那么如何解析呢?我们只需要记录的时候每个transaction之间隔一个空格,然后使用python的split()按空行分割就行了。排序呢?直接字符串排序就行了。前面说的按一定的数据结构序列化存放再比较,仔细想一想真的有必要吗?我们的最终目的不过是作个比较而已。
教训
- 技术选型要选文档全的,或者社区活跃的,否则你出了问题都搜不到
- 开发应该随着需求不断细化,切忌过度优化
- 重视多线程这种无法预测的行为,将小概率事件当成必然事件来对待
- 永远不要认为你的代码没有bug
- 改Bug是技术提高的最佳实践之一
- 技术问题不要百度