Unit testing 我可以做些什么来改进我的测试?

Unit testing 我可以做些什么来改进我的测试?,unit-testing,node.js,testing,tdd,mongoose,Unit Testing,Node.js,Testing,Tdd,Mongoose,最近,我尝试在NodeJS中使用Mongoose作为MongoDB包装器进行良好的测试驱动开发 我的问题是我做得对吗。我是否测试了正确的东西,我是否应该做更多的测试,包括空值等。您认为我可以改进哪些方面?你想批评多少就批评多少 测试: var assert = require("assert"), mongoose = require("mongoose"), sugar = require("sugar"), Factory = require("factory-lad

最近,我尝试在NodeJS中使用Mongoose作为MongoDB包装器进行良好的测试驱动开发

我的问题是我做得对吗。我是否测试了正确的东西,我是否应该做更多的测试,包括空值等。您认为我可以改进哪些方面?你想批评多少就批评多少

测试:

var assert = require("assert"),
    mongoose = require("mongoose"),
    sugar = require("sugar"),
    Factory = require("factory-lady"),
    Timekeeper = require("timekeeper"),
    Link = require("./../app/models/link");

mongoose.connect("mongodb://localhost/link_test");

Factory.define("link", Link, {
  createdAt: new Date("2012-04-04"),
  title: "Example",
  updatedAt: new Date("2012-04-05"),
  url: "http://www.example.com"
});

describe("Link", function() {

  describe("validation for", function() {

    ["url", "title"].forEach(function(property) {
      it("must have a " + property, function(done) {
        Factory.build("link", function(link) {
          link[property] = null;
          link.validate(function(err) {
            assert.notEqual(err, null);
            assert.notEqual(err.errors[property], null);
            done();
          });
        });
      });
    });

    it("should default the title to url if missing", function(done) {
      Factory.build("link", function(link) {
        link.title = undefined;
        link.validate(function(err) {
          assert.equal(link.title, link.url);
          done();
        });
      });
    });

    describe("url", function() {

      ["http://example.com", "http://www.example.com",
       "http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message"].forEach(function(url) {
        it(url + " should be valid url", function(done) {
          Factory.build("link", { url: url }, function(link) {
            link.validate(function(err) {
              assert.equal(err, null);
              done();
            });
          });
        });
      });

      ["Invalid url", "example.com"].forEach(function(url) {
        it(url + " should be invalid url", function(done) {
          Factory.build("link", { url: url }, function(link) {
            link.validate(function(err) {
              assert.notEqual(err, null);
              assert.notEqual(err.errors.url, null);
              done();
            });
          });
        });
      });

    });

    describe("missing createdAt or updatedAt", function() {

      beforeEach(function() {
        Timekeeper.freeze(new Date());
      });

      afterEach(function() {
        Timekeeper.reset();
      });

      ["createdAt", "updatedAt"].forEach(function(property) {
        it("should default the " + property + " to now if missing", function(done) {
          Factory.build("link", function(link) {
            link[property] = undefined;
            link.validate(function(err) {
              assert.deepEqual(link[property], new Date());
              done();
            });
          });
        });
      });

      ["createdAt", "updatedAt"].forEach(function(property) {
        it("should leave the " + property + " unchanged if it's given", function(done) {
          Factory.build("link", function(link) {
            var date = new Date("2012-01-01");
            link[property] = date;
            link.validate(function(err) {
              assert.deepEqual(link[property], date);
              done();
            });
          });
        });
      });

      it("should default the updatedAt to now if missing when performing an update", function(done) {
        Factory("link", function(link) {
          link.validate(function(err) {
            assert.equal(link.updatedAt, new Date());
            done();
          });
        });
      });

      it("should leave the updatedAt unchanged if it's given when performing an update", function(done) {
        Factory("link", function(link) {
          var date = new Date("2012-01-01");
          link.updatedAt = date;
          link.validate(function(err) {
            assert.deepEqual(link.updatedAt, date);
            done();
          });
        });
      });

    });

  });

});
var mongoose = require("mongoose"),
    Schema = mongoose.Schema;

var linkSchema = new Schema({
  createdAt: { type: Date, required: true },
  title: { type: String, required: true },
  updatedAt: { type: Date, required: true },
  url: { type: String, required: true, validate: [validUrl, "invalid url"] }
});

function validUrl(url) {
  if ((url instanceof String || typeof url == 'string') && url.length) {
    return url.match(/^\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))$/i); 
  }
}

linkSchema.pre("validate", function (next) {
  if (typeof this.title === "undefined" && typeof this.url !== "undefined") {
    this.title = this.url;
  }
  if (typeof this.createdAt === "undefined") {
    this.createdAt = new Date();
  }
  if (typeof this.updatedAt === "undefined" || !this.isModified("updatedAt")) {
    this.updatedAt = new Date();
  }
  next();
});

module.exports = mongoose.model("Link", linkSchema);
型号:

var assert = require("assert"),
    mongoose = require("mongoose"),
    sugar = require("sugar"),
    Factory = require("factory-lady"),
    Timekeeper = require("timekeeper"),
    Link = require("./../app/models/link");

mongoose.connect("mongodb://localhost/link_test");

Factory.define("link", Link, {
  createdAt: new Date("2012-04-04"),
  title: "Example",
  updatedAt: new Date("2012-04-05"),
  url: "http://www.example.com"
});

describe("Link", function() {

  describe("validation for", function() {

    ["url", "title"].forEach(function(property) {
      it("must have a " + property, function(done) {
        Factory.build("link", function(link) {
          link[property] = null;
          link.validate(function(err) {
            assert.notEqual(err, null);
            assert.notEqual(err.errors[property], null);
            done();
          });
        });
      });
    });

    it("should default the title to url if missing", function(done) {
      Factory.build("link", function(link) {
        link.title = undefined;
        link.validate(function(err) {
          assert.equal(link.title, link.url);
          done();
        });
      });
    });

    describe("url", function() {

      ["http://example.com", "http://www.example.com",
       "http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message"].forEach(function(url) {
        it(url + " should be valid url", function(done) {
          Factory.build("link", { url: url }, function(link) {
            link.validate(function(err) {
              assert.equal(err, null);
              done();
            });
          });
        });
      });

      ["Invalid url", "example.com"].forEach(function(url) {
        it(url + " should be invalid url", function(done) {
          Factory.build("link", { url: url }, function(link) {
            link.validate(function(err) {
              assert.notEqual(err, null);
              assert.notEqual(err.errors.url, null);
              done();
            });
          });
        });
      });

    });

    describe("missing createdAt or updatedAt", function() {

      beforeEach(function() {
        Timekeeper.freeze(new Date());
      });

      afterEach(function() {
        Timekeeper.reset();
      });

      ["createdAt", "updatedAt"].forEach(function(property) {
        it("should default the " + property + " to now if missing", function(done) {
          Factory.build("link", function(link) {
            link[property] = undefined;
            link.validate(function(err) {
              assert.deepEqual(link[property], new Date());
              done();
            });
          });
        });
      });

      ["createdAt", "updatedAt"].forEach(function(property) {
        it("should leave the " + property + " unchanged if it's given", function(done) {
          Factory.build("link", function(link) {
            var date = new Date("2012-01-01");
            link[property] = date;
            link.validate(function(err) {
              assert.deepEqual(link[property], date);
              done();
            });
          });
        });
      });

      it("should default the updatedAt to now if missing when performing an update", function(done) {
        Factory("link", function(link) {
          link.validate(function(err) {
            assert.equal(link.updatedAt, new Date());
            done();
          });
        });
      });

      it("should leave the updatedAt unchanged if it's given when performing an update", function(done) {
        Factory("link", function(link) {
          var date = new Date("2012-01-01");
          link.updatedAt = date;
          link.validate(function(err) {
            assert.deepEqual(link.updatedAt, date);
            done();
          });
        });
      });

    });

  });

});
var mongoose = require("mongoose"),
    Schema = mongoose.Schema;

var linkSchema = new Schema({
  createdAt: { type: Date, required: true },
  title: { type: String, required: true },
  updatedAt: { type: Date, required: true },
  url: { type: String, required: true, validate: [validUrl, "invalid url"] }
});

function validUrl(url) {
  if ((url instanceof String || typeof url == 'string') && url.length) {
    return url.match(/^\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))$/i); 
  }
}

linkSchema.pre("validate", function (next) {
  if (typeof this.title === "undefined" && typeof this.url !== "undefined") {
    this.title = this.url;
  }
  if (typeof this.createdAt === "undefined") {
    this.createdAt = new Date();
  }
  if (typeof this.updatedAt === "undefined" || !this.isModified("updatedAt")) {
    this.updatedAt = new Date();
  }
  next();
});

module.exports = mongoose.model("Link", linkSchema);
var mongoose=require(“mongoose”),
Schema=mongoose.Schema;
var linkSchema=新模式({
createdAt:{type:Date,required:true},
标题:{type:String,必需:true},
updatedAt:{type:Date,required:true},
url:{type:String,必需:true,验证:[validUrl,“无效url”]}
});
函数validUrl(url){
if((url instanceof String | | typeof url=='String')&&url.length){
返回url.match(/^\b((?:https?:\/\/\/\/)[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()]+\([^\s()]+\([^\s())*)+((?:([^\s())+)+(([^\s())+)+)+(([^\s())+)+)*(([^\s())+)+)+)*(([^\s())+)+)+)*(([^-+)+)+):(([^-+)+)+)+)+):(([^-+)+)+)+)+)+)*(((([^-+)+)+)+)+)+)+)+)+)(((((^;
}
}
linkSchema.pre(“验证”,函数(下一步){
if(typeof this.title==“未定义”&&typeof this.url!==“未定义”){
this.title=this.url;
}
if(typeof this.createdAt==“未定义”){
this.createdAt=新日期();
}
if(typeof this.updatedAt==“undefined”| |!this.isModified(“updatedAt”)){
this.updatedAt=新日期();
}
next();
});
module.exports=mongoose.model(“Link”,linkSchema);

总而言之,您的测试似乎涵盖了代码。 也许您可以添加更多的URL来更好地测试validul函数

通常,需要进行的测试数量取决于您的需求。您是否需要更多的测试取决于许多因素,例如:您对代码的信心、可能接触并“破坏”代码的人数、整个系统的大小和复杂性、代码的用户(他们是您团队的一部分还是外部人员?),数据的来源(在它到达你的代码之前是否经过验证?)和你的偏执程度。没有一个万能的答案