THE VALUE OF SELF-TESTING CODE
程序员的大部分时间用于调试工作。
Classes should contain their own tests.
每工作一点就测试,才容易找到bug。
当然,意味着要编写很多额外的代码。
当需要增加一个功能的时候,我从编写测试开始。通过编写测试,我问自己需要做些什么。
编写测试代码,也让我专注于接口而不是实现。
我也有了一个明确的点-当测试工作时,说明我的工作完成了。
TestDriven Development依赖于编写(失败)测试的短周期,编写代码以使test工作,重构以确保结果尽可能地clean。
SAMPLE CODE TO TEST
下面是一个生产计划的应用UI:
每个province都有demand和price。每个province有producers,其中每一个都能以一定的价格生产一定的数量。还显示了每个producer能获得的收入。
在底部,显示了生产不足(需求-产量),和该计划的利润。
用户可以编辑demand、price,每个producer的production和cost。只要修改一个,其他元素都要立即更新。
我关注软件的业务逻辑-计算利润和不足的类,而不是生成HTML的代码。
业务逻辑涉及两个类:一个代表producer、另一个代表整个province。
类Province:
constructor(doc) {
this._name = doc.name;
this._producers = [];
this._totalProduction = 0;
this._demand = doc.demand;
this._price = doc.price;
doc.producers.forEach(d => this.addProducer(new Producer(this, d)));
}
addProducer(arg) {
this._producers.push(arg);
this._totalProduction += arg.production;
}
此函数创建合适的JSON数据。可以用该函数的结果构造Province对象,来创建用于测试的实例Province。
function sampleProvinceData() {
return {
name: "Asia",
producers: [
{
name: "Byzantium", cost: 10, production: 9},
{
name: "Attalia", cost: 12, production: 10},
{
name: "Sinope", cost: 10, production: 6},
],
demand: 30,
price: 20
};
}
Province类有各种数据值的访问器:
get name() {
return this._name;}
get producers() {
return this._producers.slice();}
get totalProduction() {
return this._totalProduction;}
set totalProduction(arg) {
this._totalProduction = arg;}
get demand() {
return this._demand;}
set demand(arg) {
this._demand = parseInt(arg);}
get price() {
return this._price