淘宝指数的开发规范

继风(朱佳墩)

大纲

编码规范

code style

Javascript编码规范

Javascript 陷阱/性能优化/习惯用法

代码审核——提交流程

1. 变更代码必须要被审查后才能提交

2. 开发者发布审查请求时需要填写代码变更
的描述和原因,如果有测试结果,也必须要填写

3. 只有审查人确认"Ship it"后,
开发者才能提交代码

4. Commit log 必须包含代码变更描述和代码审查URL (svn)

具体使用说明

代码审核——审查内容

1. 编码规范

2. 是否符合描述说明

3. 变更代码必须有对应的单元测试覆盖到

* 输入参数覆盖

* 正常逻辑覆盖

* 异常逻辑覆盖

4. 程序逻辑

具体使用说明

代码审核——作用

1. 对开发者:

* 保证代码规范

* 查漏补缺

* 提高代码质量

2. 对审核者:

* 把控程序的功能点

* 学习别人代码的优点

单元测试——作用

代码质量

代码质量如何度量?
如果没有测试你如何保证你的代码质量?

敏捷快速地适应需求

单元测试是否也能让产品经理看得懂?
单元测试是否也能成功一个产品需求的Case?

重构

你有足够信心在没有单元测试的情况下发布你的重构代码吗?
如何检测你重构的代码符合需要?

增强自信心

全是绿灯!
单元测试全部跑通!

鹦鹉螺

去QA

单元测试——工具

mocha + should + jscoverage

好的示例

单元测试

项目结构

program Features

单元测试

Makefile

NAME = taobaoindex
SRC = $(shell find lib -type f -name "*.js")
TESTS = test/*.js
TESTTIMEOUT = 15000
REPORTER = tap
VERSION = $(shell date +%Y%m%d%H%M%S)
SVNURL = $(shell svn info | grep URL | awk '{print $$2}')

test: compile
	@NODE_ENV=test ./node_modules/mocha/bin/mocha \
		--reporter $(REPORTER) --timeout $(TESTTIMEOUT) $(TESTS)
test-cov:
	@JSCOV=1 $(MAKE) test REPORTER=html-cov > coverage.html

test-cov-json:
	@JSCOV=1 $(MAKE) test REPORTER=json-cov
	......

单元测试——小技巧

模拟请求得到的数据

 
var searchApp = require('../controllers/search');
var app = require('../app').create();
var should = require('should');  
  before(function(done) {
    app.listen(0, done);
  });
    describe('/cpv_items', function() {
    var urls = [
      '/cpv_items/50010850/20511,28386;20664,28105;2917619,8496965?query=%E8%BF%9E%E8%A1%A3%E8%A3%99&cid=50010850&hot=63426&title=%E8%95%BE%E4%B8%9D%20%E8%95%BE%E4%B8%9D%E8%8A%B1%E8%BE%B9%20%E9%9F%A9%E7%89%88&datatype=cpv',
      '/cpv_items/50019272/20000,47342;3775809,20144;7221242,4526599?query=%E7%99%BB%E5%B1%B1%E9%9E%8B&cid=50019272&hot=13451&title=%E7%94%B7%E5%A3%AB%20Camel%2F%E9%AA%86%E9%A9%BC%20%E8%80%90%E7%A3%A8&datatype=cpv',
    ];
    urls.forEach(function(url) {
      it(url.substring(0, 30) + '... should return json format', function(done) {
        app.request().get(url).end(function(res) {
          res.should.have.status(200);
          res.should.have.header('content-type', 'application/json; charset=utf-8');
          var items = JSON.parse(res.body);
          items.should.be.an.instanceof(Array);
          items.length.should.above(0);
          for (var j = 0, jl = items.length; j < jl; j++) {
            checkImageItem(items[j]);
          }
          done();
        });
      })
    });
    
  });
	......

http模拟代码

单元测试——小技巧

模拟http请求

 
function mockDataRenderError() {
  var _request = urllib.request;
  before(function() {
    urllib.request = function() {
      var cb = arguments[arguments.length - 1];
      process.nextTick(function() {
        cb(null, new Buffer('{"v": "3.0","c": 200,"m": "数据渲染错误","t": 0,"n": 0,"fn": 0}'));
      });
    };
  });
  after(function() {
    urllib.request = _request;
  });
  return function(err, data, done) {
    should.exist(err);
    err.should.be.an.instanceof(Error);
    err.message.should.equal('数据渲染错误');
    err.data.should.equal('{"v": "3.0","c": 200,"m": "数据渲染错误","t": 0,"n": 0,"fn": 0}');
    should.not.exist(data);
    done();
  };
}
	......

单元测试

result

看见单元测试全部跑过是件很爽的事情

Thank you

/

#