我是Mocha的新手,我正在尝试对此代码运行测试:
"use strict";
process.env.NODE_ENV = 'test';
var assert = require('assert'),
Browser = require('zombie'),
xapp = require('../app'),
app,
User = require('../models/users').User,
testMail = 'aaa@aaa.aaa',
testPassword = 'aD1$#!_é',
server;
before(function(done) {
xapp(function(sapp) {
app = sapp;
server = app.listen(3000, done);
});
});
after(function(done) {
app.closeMongo(function() {
server.close(done);
});
});
function clearDb(done) {
User.findOne({email: testMail}, function(err, user) {
if(err) return done(err);
if(!user) return done();
else {
user.remove(done);
}
});
}
describe('User signup', function() {
this.timeout(3200);
before(clearDb);
describe('Homepage Form', function() {
this.timeout(3200);
it('should load the trial form', function(done) {
Browser.visit('http://localhost:3000/', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
var form = browser.query('form[action="/users/signup"]');
assert.notEqual(form, null, 'Form on homepage exists');
assert.notEqual(browser.query("input[type=email]", form), null, 'has email input on page');
done();
});
});
it('should test the trial form', function(done) {
Browser.visit('http://localhost:3000/', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
browser
.fill('email', testMail)
.pressButton('Sign up', function(err) {
if(err) return done(err);
assert.equal(browser.location.pathname, '/users/signup', 'Links to signup page');
assert.notEqual(browser.text('h1').indexOf('Sign up'), -1, 'Title page contains "Sign up"');
var form = browser.query('form#form-signup');
assert.notEqual(form, null, 'Form on signup page exists');
var emailInput = browser.query('input[type=email]#email', form);
assert.notEqual(emailInput, null, 'has email input on signup page');
assert.equal(emailInput.value, testMail, 'email input has entered value on homepage');
done();
});
});
});
});
describe('Signup page form', function() {
this.timeout(3200);
it('should load the signup form', function(done) {
Browser.visit('http://localhost:3000/users/signup', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
var form = browser.query('form[action="/users/signup"]#form-signup');
assert.notEqual(form, null, 'Form on signup page exists');
assert.equal(form.method, "post", "Form is POST");
assert.notEqual(browser.query("input[type=email]#email", form), null, 'has email input on page');
assert.notEqual(browser.query("input[type=password]#password", form), null, 'has password input on page');
assert.notEqual(browser.query("input[type=password]#passwordConfirm", form), null, 'has password confirmation input on page');
done();
});
});
it('should sign up a test user', function(done) {
Browser.visit('http://localhost:3000/users/signup', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
browser
.fill('Email:', testMail)
.fill('Password:', testPassword)
.fill('Password confirmation:', testPassword)
.pressButton('#form-signup button[type=submit]', function(err) {
if(err) return done(err);
assert.notEqual(browser.query('.alert-success'), null, 'Has success alert');
assert.notEqual(browser.text('.alert-success').indexOf('Sign up successful'), -1, 'Found the text "Sign up successful" in alert');
done();
});
});
});
it('shouldn\'t sign up the same email twice', function(done) {
Browser.visit('http://localhost:3000/users/signup', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
browser
.fill('Email:', testMail)
.fill('Password:', testPassword)
.fill('Password confirmation:', testPassword)
.pressButton('#form-signup button[type=submit]', function(err) {
if(err) return done(err);
assert.equal(browser.location.pathname, '/users/signup', 'Still on the signup page');
assert.notEqual(browser.query('.alert-danger'), null, 'Has danger alert');
assert.notEqual(browser.text('.alert-danger').indexOf('This email address already exists!'), -1, 'Found the text "This email address already exists!" in alert');
done();
});
});
});
});
});
describe('User login', function() {
this.timeout(2500);
after(clearDb);
describe('Homepage form', function() {
this.timeout(3200);
it('should appear when we click login', function(done) {
Browser.visit('http://localhost:3000/', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
assert.equal(browser.query('form[action="/users/login"]'), null, 'No login form should be visible before we click on login');
browser.clickLink('Login', function(err) {
if(err) return done(err);
var form = browser.query('form[action="/users/login"]');
assert.notEqual(form, null, 'Login form should be visible after click on login');
assert.notEqual(browser.query('input[type=email]#email'), null, 'Has email input');
assert.notEqual(browser.query('a', form), null, 'Forgot your password?');
assert.notEqual(browser.query('input[type=password]#password'), null, 'Has password input');
done();
});
});
});
it('should not work with wrong credentials', function(done) {
this.timeout(3200);
Browser.visit('http://localhost:3000/', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
browser.clickLink('Login', function(err) {
if(err) return done(err);
browser
.fill('Email:', testMail)
.fill('Password:', (testPassword + 'a'))
.pressButton('Login', function(err) {
if(err) return done(err);
assert.equal(browser.location.pathname, '/users/login');
assert.notEqual(browser.query('.alert-danger'), null, "Has danger alert");
assert.notEqual(browser.text('.alert-danger').indexOf('Invalid email or password.'), -1, 'alert contain error message "Invalid email or password."');
done();
});
});
});
});
});
describe('Login form', function() {
this.timeout(3200);
it('should login with valid credentials', function(done) {
Browser.visit('http://localhost:3000/users/login', function(err, browser) {
if(err) return done(err);
assert.ok(browser.success, "page loaded");
browser
.fill('#form-signin input[type=email]', testMail)
.fill('#form-signin input[type=password]', testPassword)
.pressButton('Sign in', function(err) {
if(err) return done(err);
assert.equal(browser.location.pathname, '/');
assert.notEqual(browser.query('.alert-success'), null, "Has success alert");
assert.equal(browser.text('.alert-success'), '×Close You are now logged in.');
assert.notEqual(browser.link('Dashboard'), null, 'Has dashboard link');
assert.notEqual(browser.link('Log out'), null, 'Has log out link');
done();
});
});
});
});
});
这是我正在使用的命令:
$ mocha -b -R spec -s 1000
这条消息失败了:
1) "before all" hook
0 passing (2s)
1 failing
1) "before all" hook:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
你能帮我弄清楚这是为什么造成的吗?
我知道如果我更改测试运行器的超时:
$ mocha -b -R spec -s 1000 -t 3000
测试工作正常。但我想知道这个错误的实际原因。
谢谢!
答案 0 :(得分:4)
您收到错误,因为您的顶级before
挂钩需要超过默认的2000毫秒超时延迟才能运行。如果您不知道:before
表示“在此套件中的所有测试之前执行此操作”,这就是为什么错误消息会说“在所有”之前的钩子。
当您执行$ mocha -b -R spec -s 1000 -t 3000
时它会起作用,因为您已将超时时间增加到3000毫秒。您之前挂钩中的代码需要2到3秒才能运行。您可以将此设置置于test/mocha.opts
内,使其永久保留。
答案 1 :(得分:1)
使用BeforeEach而不是Before
问题是,server.listen
正在阻塞,因此回调中的done
语句不会执行,直到所有测试都完成并且server.close
被调用。
一个简单的(和恕我直言)清洁解决方案,以防止违反默认时间限制是为每个测试启动/停止服务器。
变化:
before(function(done) {
xapp(function(sapp) {
app = sapp;
server = app.listen(3000, done);
});
});
after(function(done) {
app.closeMongo(function() {
server.close(done);
});
});
要:
beforeEach(function(done) {
xapp(function(sapp) {
app = sapp;
server = app.listen(3000, done);
});
});
afterEach(function(done) {
app.closeMongo(function() {
server.close(done);
});
});
除非出现问题,否则测试的运行时间不应超过2000毫秒。
另一个可能更好的解决方案是使用专门用于测试API调用的测试框架。