nodemon 热部署

———————————————————————————————————————————
命令行使用的方式
npm install —g nodemon
// 使用nodemon很简单,如果我的应用程序接受主机和端口作为参数,我会这样开始:
nodemon ./server.js localhost 8080
如果不接受主机和端口参数:
nodemon ./server.js
———————————————————————————————————————————
npm install —save-dev nodemon 内部配置的方法(暂无)
———————————————————————————————————————————

BDD与TDD的介绍

BDD,行为驱动开发(注重测试逻辑),TDD是测试驱动开发(注重输出结果)
https://www.cnblogs.com/KevinSong/p/4564046.html 测试驱动开发(TDD)及测试框架Mocha.js入门学习
TDD,全称Test-driven Development,中文测试驱动开发,是来源于Agile敏捷开发的一个极限编程思想。

大致是讲,Developer开发之前,先写测试用例(test case),测试用例写好后,再来实现需要实现的方法或功能,然后跑一遍测试用例,看能否通过。将来新加功能时,也是先加测试用例,然后新功能实现后,再跑一遍所有的测试用例,如果所有用例都成功(Pass),那么则代码质量可以保证。

BDD是Behaviour-driven Development,行为驱动开发,相比TDD,BDD更关注通过测试,观察到程序的行为是否正确,因此它的接口是使用describe。而与BDD相比,TDD更偏重与测试代码的功能是否实现正确,它的接口是suite。

suite就是一组测试用例的集合,可用于对测试用例进行分类。suite里面可以嵌套suite,就像测一个功能的一组测试例子里面再细分测不同小功能的机组测试例子。

Mocha.js的介绍

Javascript测试框架,支持TDD,BDD等多种接口,Mocha.js是被广泛使用的Javascript测试框架,官网:http://mochajs.org/

使用Mocha.js,可以写测试用例,并跑用例来得到结果,同时还支持多种格式的Report来显示结果。支持TDD,BDD等接口,是TDD开发过程中的好帮手。

  1. npm install -g mocha
  2. mocha -h
  3. // 可以查看帮助
  4. /*
  5. suite:定义一组测试用例。
  6. suiteSetup:此方法会在这个suite所有测试用例执行前执行一次,只一次,这是跟setup的区别。
  7. setup:此方法会在每个测试用例执行前都执行一遍。
  8. test:具体执行的测试用例实现代码。
  9. teardown:此方法会在每个测试用例执行后都执行一遍,与setup相反。
  10. suiteTeardown:此方法会在这个suite所有测试用例执行后执行一次,与suiteSetup相反。
  11. */

Test Case测试用例的结构

    我们在写测试用例时,一个被广泛接受的结构是:

    a. Setup: 准备好环境和数据,跑这个测试用例之前的准备

    b. Execution:执行测试(测试用例的实现的主要代码)

    c. Validation:验证结果

    d. Cleanup:现场恢复,一般与a相反。不影响跑后面的测试用例。

案例一

npm install —save-dev mocha
mkdir public/vendor
cp ./node_modules/mocha/mocha.js public/vendor
cp ./node_modules/mocha/mocha.css public/vendor
npm install —save-dev chai
cp ./node_modules/chai/chai.js public/vendor

  1. // http://www.expressjs.com.cn/4x/api.html#app.get.method Express Api
  2. var express = require('express');
  3. var handlebars = require('express3-handlebars').create({ defaultLayout: 'main' });
  4. var app = express();
  5. app.engine('handlebars', handlebars.engine);
  6. app.set('view engine', 'handlebars');
  7. app.set('port', process.env.PORT || 3000);
  8. app.use(express.static(__dirname + '/public')); // 设置静态文件目录,外网可直接访问。
  9. app.use(function (req, res, next) {
  10. console.log('Time: %d', Date.now());
  11. res.locals.showTests = app.get('env') !== 'production' && req.query.test === '1';
  12. next();
  13. });
  14. app.get('/',function(req, res){
  15. res.render('home');
  16. });
  17. app.get('/about',function(req, res){
  18. res.render('about', { pageTestScript: '/qa/tests-about.js' });
  19. });
  20. app.use(function(req, res){
  21. res.status(404);
  22. res.render('404');
  23. });
  24. app.use(function(err, req, res, next){
  25. res.status(500);
  26. res.render('404');
  27. });
  28. app.listen(app.get('port'), function(){
  29. console.log(`Express started on http://localhost:${app.get('port')}; press Ctrl + c to terminate.`);
  30. });
  1. // tests-about.js
  2. suite('"About" Page Tests', function(){
  3. test('page has a valid title', function(){
  4. assert(document.title && document.title.match(/\S/) && document.title.toUpperCase() !== 'TODO')
  5. });
  6. });
  1. // tests-global.js
  2. suite('全局测试', function(){
  3. test('page has a valid title', function(){
  4. assert(document.title && document.title.match(/\S/) && document.title.toUpperCase() !== 'TODO')
  5. });
  6. });
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title></title>
  5. {{#if showTests}}
  6. <link rel="stylesheet" href="/vendor/mocha.css" />
  7. {{/if}}
  8. <style>
  9. #mocha {
  10. font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
  11. margin: 0;
  12. position: fixed;
  13. top: 0;
  14. left: 0;
  15. right: 0;
  16. bottom: 0;
  17. background-color: rgba(0,0,0, 0.3);
  18. color: #c00;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. {{{body}}}
  24. {{#if showTests}}
  25. <div id="mocha"></div>
  26. <script src="/vendor/mocha.js"></script>
  27. <script src="/vendor/chai.js"></script>
  28. <script>
  29. mocha.ui('tdd');
  30. var assert = chai.assert;
  31. </script>
  32. <script src="/qa/tests-global.js"></script>
  33. {{#if pageTestScript}}
  34. <script src="{{pageTestScript}}"></script>
  35. {{/if}}
  36. <script>mocha.run();</script>
  37. {{/if}}
  38. </body>
  39. </html>

案例二 逻辑测试

  1. // fortune.js
  2. var fortuneCookie = [
  3. 'a',
  4. 'b',
  5. 'c',
  6. 'd',
  7. 'e',
  8. ]
  9. export.getFortune = function(){
  10. var idx = Math.floor(Math.random() * fortuneCookie.length);
  11. return fortuneCookie[idx];
  12. }
  13. // test-unit.js
  14. var fortune = require('../lib/fortune.js');
  15. var expect = require('chai').expect;
  16. suite('Fortune cookie tests', function(){
  17. test('getFortune() should return a fortune', function(){
  18. expect(typeof fortune.getFortune() === 'string');
  19. })
  20. })

命令行输入 mocha -u tdd -R spec qa/tests-unit.js