Javascript 如何在Mocha中测试主干子类而不重复对超类的测试?
假设我有两个主干模型,矩形和三角形,每个都延伸多边形Javascript 如何在Mocha中测试主干子类而不重复对超类的测试?,javascript,unit-testing,oop,backbone.js,mocha.js,Javascript,Unit Testing,Oop,Backbone.js,Mocha.js,假设我有两个主干模型,矩形和三角形,每个都延伸多边形 var Polygon=Backbone.Model.extend({ 默认值:{ 宽度:100, 身高:100, 轮换:0 }, 旋转:功能(度){ var oldRotation=this.get('rotation'); var newRotation=(旧旋转+度)%360; 此.set('rotation',newRotation); 返回新循环; } }); var Rectangle=Polygon.extend({ 面积:功能
var Polygon=Backbone.Model.extend({
默认值:{
宽度:100,
身高:100,
轮换:0
},
旋转:功能(度){
var oldRotation=this.get('rotation');
var newRotation=(旧旋转+度)%360;
此.set('rotation',newRotation);
返回新循环;
}
});
var Rectangle=Polygon.extend({
面积:功能(度){
返回this.get('width')*this.get('height');
}
});
var Triangle=Polygon.extend({
面积:功能(度){
返回this.get('width')*this.get('height')/2;
}
}
我想测试矩形和三角形,确保它们各自独立地正确实现rotate
,尽管我知道(目前)它们都继承了多边形的rotate
实现
我不想做的是为矩形和三角形创建单独的单元测试,它们几乎是彼此的精确副本。在Mocha中,我如何为rotate
编写一个测试,并在三角形和矩形的单元测试中重用它
这里是我的单元测试。注意重复的“旋转45度”测试
description('A rectangle',function(){
var r=新矩形({宽度:50,高度:10,旋转:90});
它('正确计算其面积',函数(){
期望(r.面积())等于(500);
});
它('旋转45度',功能(){
期望(r.rotate(45))等于(135);
});
});
描述('三角形',函数(){
var t=新三角形({宽度:50,高度:10,旋转:90});
它('正确计算其面积',函数(){
期望(t.面积())等于(250);
});
它('旋转45度',功能(){
期望(t.rotate(45))等于(135);
});
});
写出来后答案显而易见。我们可以创建一个函数来封装多边形的测试
var describeAPolygon = function (name, p) {
describe(name, function () {
it('rotates by 45 degrees', function () {
expect(p.rotate(45)).to.equal(135);
});
});
};
然后在矩形和三角形的测试中使用它
describe('A rectangle', function () {
var r = new Rectangle({width: 50, height: 10, rotation: 90});
describeAPolygon('A rectangle', r);
it('correctly calculates its area', function () {
expect(r.area()).to.equal(500);
});
});
describe('A triangle', function () {
var t = new Triangle({width: 50, height: 10, rotation: 90});
describeAPolygon('A triangle', t);
it('correctly calculates its area', function () {
expect(t.area()).to.equal(250);
});
});
这是我能找到的最干净的解决方案。我很好奇是否有其他人解决了这个问题并提出了不同的解决方案。我通常做的是:
describe('A rectangle', function () {
var r = new Rectangle({width: 50, height: 10, rotation: 90});
it('should be a polygon', function() {
expect(r).to.be.an.instanceof(Polygon);
});
it('correctly calculates its area', function () {
expect(r.area()).to.equal(500);
});
});
describe('A triangle', function () {
var t = new Triangle({width: 50, height: 10, rotation: 90});
it('should be a polygon', function() {
expect(r).to.be.an.instanceof(Polygon);
});
it('correctly calculates its area', function () {
expect(t.area()).to.equal(250);
});
});
describe('A polygon', function() {
var p = new Polygon({width: 50, height: 10, rotation: 90});
it('rotates by 45 degrees', function () {
expect(p.rotate(45)).to.equal(135);
});
});
如果您使用正确的OOP实践,您的
Polygon
类的方法和结构应该足够安全,可以依赖于任何扩展它的类都不能修改它。如果它在子类中没有更改,为什么要重新测试rotate()
?您可以限制rotate()
测试多边形的测试
。其思想是多边形具有某些不变量,无论测试多边形的哪个子类,这些测试都应始终通过。将来,Triangle可能会实现rotate()
方法来添加一些功能。我希望确保Polygon.rotate()的不变量
仍然满足于Triangle.rotate()
。谢谢。现在我们假设添加另一个方法,cutInHalf(),它返回两个新多边形。三角形和矩形将分别实现cutInHalf()不同。但我仍然想测试两个结果多边形的面积是否与原始多边形的面积相加,无论分割的是哪种类型的多边形。在这种情况下,重复expect(a.area()+b.area()).to.equal(c.area())没有错;
如果a
,b
是分割多边形,而c
是原始多边形。看看ThreeJS是如何测试它的。IMHO测试应该是1.可读,2.快速,但如果你不是这样,你可以用你的方法减少代码重复。