QA###
在Web开发中,质量可以分解为四个维度:
-
到达率:
到达率是指产品的市场普及程度,即查看网站或使用服务的人数。到达率和盈利能力是正相关关系:访问网站的人越多,购买产品或服务的人就越多。从开发的角度来看,搜索引擎优化(SEO)对到达率的影响最大,所以我们会在QA方案里包含SEO。 -
功能
人们一旦访问了你的网站或使用了你的服务,能否把用户留下很大程度上取决于网站功能的质量:一个能像广告宣传那样工作的网站更有可能吸引回头客。与其他几个维度不同,功能测试一般都可以自动执行。 -
可用性
功能关心的是功能的正确性,而可用性评估的是人机交互(HCI)。根本问题是:“这个功能是以对目标受众有用的方式交付的吗?”这个问题经常被换成“它易用吗?”,尽管追求易用性经常跟灵活性或能力是相对的:程序员眼中的“容易”可能跟不懂技术的用户眼中的“容易”不一样。换句话说,评估可用性时你必须考虑目标受众。因为可用性评估的根本输入是用户,所以可用性评估一般无法自动完成。然而,你的QA方案中应该包含用户测试。 -
审美
审美是四个维度中最主观的,因此也是跟开发最不相关的一个维度。尽管跟网站审美相关的开发问题没有几个,但QA方案中还是应该包括网站审美的常规评审。把网站展示给有代表性的样本受众,看他们是否觉得已经过时,或者是不是没能激起你所期望的响应。记住,审美具有时间敏感性(审美标准会随着时间而发生变化),并且因人而异(受到某一受众喜爱的东西可能完全激不起其他受众的兴趣)。
逻辑与展示###
从广义上来讲,网站上有两个“领域”:逻辑(业务逻辑)和表示。
可以认为网站的逻辑存在于纯粹的认知领域; 逻辑域中的事情应该尽可能简单清晰,而表示域复杂还是简单则视需要而定。表示域还是可用性和审美问题要关注的课题,而业务域则不是
测试的类型###
单元测试和集成测试(一般认为“系统测试”属于集成测试)
- 单元测试的粒度非常细,是对单个组件进行测试以确保其功能正确
- 集成测试是对多个组件甚至整个系统之间的交互进行测试
一般而言,单元测试在测试逻辑时更实用,也更恰当。集成测试则在两个领域中都有用。
QA技术概览###
-
页面测试
用来测试页面的表示和前端功能。这同时涉及单元测试和集成测试。我们会用Mocha进行页面测试。 -
跨页测试
对从一个页面转到另一个页面的功能的测试。比如电子商务网站上的结账功能,通常要跨越多个页面。因为这种测试会涉及多个组件,所以一般被当作集成测试。这个测试用的是Zombie.js。 -
逻辑测试
逻辑测试会对逻辑域进行单元和集成测试。它只会测试JavaScript,跟所有表示功能分开。 -
去毛
去毛不是要找错误,而是要找潜在的错误。去毛的一般概念是找出可能有错误的区域,或者可能在将来导致错误发生的问题代码。我们会用JSHint做去毛。 -
链接检查
对简单的项目做链接检查看起来可能没有必要,但简单项目也会发展成复杂项目,破损的链接也将会出现。越早把链接检查放到QA过程里越好。链接检查属于单元测试(链接有效或者无效)。我们会用LinkChecker做链接检查。
页面测试###
对于页面测试,建议把测试真正嵌入到页面中。这样做的优点是在做一个页面时,在浏览器中一加载页面就可以马上发现所有错误。
- 将Mocha测试框架,这个包添加到项目中:
npm install --save-dev mocha
注意,这里用的是--save-dev而不是--save,这是告诉npm要把这个包放在开发依赖项中,不要放在运行时依赖项里。这样当部署网站的现场实例时,可以减少项目的依赖项。
- 因为Mocha要在浏览器中运行,所以我们要把Mocha资源放在public目录下,以便让客户端访问到。我们会把这些资源放在子目录public/vendor中:
mkdir public/vendor
cp node_modules/mocha/mocha.js public/vendor
cp node_modules/mocha/mocha.css public/vendor
- 测试通常需要一个assert(或expect)函数。Node框架中有这个函数,但浏览器中没有,所以我们要用Chai断言库:
npm install --save-dev chai
cp node_modules/chai/chai.js public/vendor
- 我们不希望测试一直运行。默认情况下测试应该是禁用的,但应该非常容易启用。为了满足这两个目标,我们准备用一个URL参数来打开测试; 访问http://localhost:3000?test=1将会加载包含测试的首页。
准备用一些中间件来检测查询字符串中的test=1
。它必须出现在我们定义的所有路由之前:
app.use(function(req, res, next) {
res.locals.showTests = app.get('env') !== 'production' && req.query.test === '1';
next();
});
// 路由放在这里
如果test=1出现在任何页面的查询字符串中(并且不是运行在生产服务器上),属性res.locals.showTests就会被设为true。res.locals对象是要传给视图的上下文的一部分
- 修改views/layouts/main.handlebars,有条件地引入测试框架
修改部分:这里引入了jquery
<head>
<title>Meadowlark Travel</title>
{{#if showTests}}
<link rel="stylesheet" href="/vendor/mocha.css">
{{/if}}
<script src="//code.jquery.com/jquery-2.0.2.min.js"></script>
</head>
结束标签之前:
{{#if showTests}}
<div id="mocha"></div>
<script src="/vendor/mocha.js"></script>
<script src="/vendor/chai.js"></script>
<script>
mocha.ui('tdd');
var assert = chai.assert;
</script>
<script src="/qa/tests-global.js"></script>
{{#if pageTestScript}}
<script src="{{pageTestScript}}"></script>
{{/if}}
<script>mocha.run();</script>
{{/if}}
上面还引入了/qa/global-tests.js脚本,这是每个页面上都要运行的测试; 我们会有选择地链接每个页面特有的测试,这样就可以针对不同的页面做不同的测试。我们先从全局测试开始,然后再增加针对各个页面的测试。我们先从单一的、简单的测试开始,确保页面具有有效的标题。
- 创建文件tests-global.js:
suite('Global Tests', function(){
test('page has a valid title', function(){
assert(document.title && document.title.match(/S/) &&
document.title.toUpperCase() !== 'TODO');
});
});
Mocha支持多种“界面”来控制测试的风格。默认界面是行为驱动开发(BDD),它让你以行为的方式思考。在BDD中,你描述组件和它们的行为,然后用测试去验证这些行为。然而,我发现这些测试经常不适合这一模型,然后BDD语言看起来就显得很奇怪。测试驱动开发(TDD)更具可行性,你描述的是测试集和其中的测试。你可以使用两种界面进行自己的测试,但会造成配置上的困难。因此我在本书中坚持使用TDD。如果你喜欢BDD,或者BDD和TDD混合的风格,当然也可以。
- 运行网站,然后访问http://localhost:3000/?test=1;
接下来添加针对页面的测试。比如想确保关于页面上总是有一个指向联系我们页面的链接。
- 创建一个public/qa/tests-about.js文件:
suite('"About" Page Tests', function(){
test('page should contain link to contact page', function(){
assert($('a[href="/contact"]').length);
});
});
- 还要做最后一件事:在路由中指明视图应该使用哪个页面测试文件。在meadowlark.js中修改关于页面的路由:
app.get('/about', function(req, res) {
res.render('about', {
fortune: fortune.getFortune(),
pageTestScript: '/qa/tests-about.js'
});
});